diff options
author | Sam bobroff <sam.bobroff@au1.ibm.com> | 2014-05-21 02:32:38 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-05-27 23:35:40 -0400 |
commit | 1739ea9e13e636590dd56c2f4ca85e783da512e7 (patch) | |
tree | fcdebf258849e18544f05cdabcf176837c0b3778 /arch/powerpc/kernel | |
parent | 39a360ef7234942333436709fd6cf641d5c51b7b (diff) |
powerpc: Fix regression of per-CPU DSCR setting
Since commit "efcac65 powerpc: Per process DSCR + some fixes (try#4)"
it is no longer possible to set the DSCR on a per-CPU basis.
The old behaviour was to minipulate the DSCR SPR directly but this is no
longer sufficient: the value is quickly overwritten by context switching.
This patch stores the per-CPU DSCR value in a kernel variable rather than
directly in the SPR and it is used whenever a process has not set the DSCR
itself. The sysfs interface (/sys/devices/system/cpu/cpuN/dscr) is unchanged.
Writes to the old global default (/sys/devices/system/cpu/dscr_default)
now set all of the per-CPU values and reads return the last written value.
The new per-CPU default is added to the paca_struct and is used everywhere
outside of sysfs.c instead of the old global default.
Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/sysfs.c | 32 | ||||
-rw-r--r-- | arch/powerpc/kernel/tm.S | 16 |
4 files changed, 25 insertions, 33 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index dba8140ebc20..cba2697406b7 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -247,6 +247,7 @@ int main(void) | |||
247 | #endif | 247 | #endif |
248 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 248 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
249 | DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); | 249 | DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); |
250 | DEFINE(PACA_DSCR, offsetof(struct paca_struct, dscr_default)); | ||
250 | DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime)); | 251 | DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime)); |
251 | DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user)); | 252 | DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user)); |
252 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | 253 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 9fde8a1bf1e1..911d45366f59 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -387,12 +387,6 @@ _GLOBAL(ret_from_kernel_thread) | |||
387 | li r3,0 | 387 | li r3,0 |
388 | b syscall_exit | 388 | b syscall_exit |
389 | 389 | ||
390 | .section ".toc","aw" | ||
391 | DSCR_DEFAULT: | ||
392 | .tc dscr_default[TC],dscr_default | ||
393 | |||
394 | .section ".text" | ||
395 | |||
396 | /* | 390 | /* |
397 | * This routine switches between two different tasks. The process | 391 | * This routine switches between two different tasks. The process |
398 | * state of one is saved on its kernel stack. Then the state | 392 | * state of one is saved on its kernel stack. Then the state |
@@ -577,11 +571,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
577 | #ifdef CONFIG_PPC64 | 571 | #ifdef CONFIG_PPC64 |
578 | BEGIN_FTR_SECTION | 572 | BEGIN_FTR_SECTION |
579 | lwz r6,THREAD_DSCR_INHERIT(r4) | 573 | lwz r6,THREAD_DSCR_INHERIT(r4) |
580 | ld r7,DSCR_DEFAULT@toc(2) | ||
581 | ld r0,THREAD_DSCR(r4) | 574 | ld r0,THREAD_DSCR(r4) |
582 | cmpwi r6,0 | 575 | cmpwi r6,0 |
583 | bne 1f | 576 | bne 1f |
584 | ld r0,0(r7) | 577 | ld r0,PACA_DSCR(r13) |
585 | 1: | 578 | 1: |
586 | BEGIN_FTR_SECTION_NESTED(70) | 579 | BEGIN_FTR_SECTION_NESTED(70) |
587 | mfspr r8, SPRN_FSCR | 580 | mfspr r8, SPRN_FSCR |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index e2a1d6fb3297..67fd2fd2620a 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -484,7 +484,6 @@ SYSFS_PMCSETUP(pmc8, SPRN_PMC8); | |||
484 | SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); | 484 | SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); |
485 | SYSFS_SPRSETUP(purr, SPRN_PURR); | 485 | SYSFS_SPRSETUP(purr, SPRN_PURR); |
486 | SYSFS_SPRSETUP(spurr, SPRN_SPURR); | 486 | SYSFS_SPRSETUP(spurr, SPRN_SPURR); |
487 | SYSFS_SPRSETUP(dscr, SPRN_DSCR); | ||
488 | SYSFS_SPRSETUP(pir, SPRN_PIR); | 487 | SYSFS_SPRSETUP(pir, SPRN_PIR); |
489 | 488 | ||
490 | /* | 489 | /* |
@@ -494,12 +493,27 @@ SYSFS_SPRSETUP(pir, SPRN_PIR); | |||
494 | */ | 493 | */ |
495 | static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); | 494 | static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); |
496 | static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); | 495 | static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); |
497 | static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); | ||
498 | static DEVICE_ATTR(purr, 0400, show_purr, store_purr); | 496 | static DEVICE_ATTR(purr, 0400, show_purr, store_purr); |
499 | static DEVICE_ATTR(pir, 0400, show_pir, NULL); | 497 | static DEVICE_ATTR(pir, 0400, show_pir, NULL); |
500 | 498 | ||
501 | unsigned long dscr_default = 0; | 499 | static unsigned long dscr_default; |
502 | EXPORT_SYMBOL(dscr_default); | 500 | |
501 | static void read_dscr(void *val) | ||
502 | { | ||
503 | *(unsigned long *)val = get_paca()->dscr_default; | ||
504 | } | ||
505 | |||
506 | static void write_dscr(void *val) | ||
507 | { | ||
508 | get_paca()->dscr_default = *(unsigned long *)val; | ||
509 | if (!current->thread.dscr_inherit) { | ||
510 | current->thread.dscr = *(unsigned long *)val; | ||
511 | mtspr(SPRN_DSCR, *(unsigned long *)val); | ||
512 | } | ||
513 | } | ||
514 | |||
515 | SYSFS_SPRSETUP_SHOW_STORE(dscr); | ||
516 | static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); | ||
503 | 517 | ||
504 | static void add_write_permission_dev_attr(struct device_attribute *attr) | 518 | static void add_write_permission_dev_attr(struct device_attribute *attr) |
505 | { | 519 | { |
@@ -512,14 +526,6 @@ static ssize_t show_dscr_default(struct device *dev, | |||
512 | return sprintf(buf, "%lx\n", dscr_default); | 526 | return sprintf(buf, "%lx\n", dscr_default); |
513 | } | 527 | } |
514 | 528 | ||
515 | static void update_dscr(void *dummy) | ||
516 | { | ||
517 | if (!current->thread.dscr_inherit) { | ||
518 | current->thread.dscr = dscr_default; | ||
519 | mtspr(SPRN_DSCR, dscr_default); | ||
520 | } | ||
521 | } | ||
522 | |||
523 | static ssize_t __used store_dscr_default(struct device *dev, | 529 | static ssize_t __used store_dscr_default(struct device *dev, |
524 | struct device_attribute *attr, const char *buf, | 530 | struct device_attribute *attr, const char *buf, |
525 | size_t count) | 531 | size_t count) |
@@ -532,7 +538,7 @@ static ssize_t __used store_dscr_default(struct device *dev, | |||
532 | return -EINVAL; | 538 | return -EINVAL; |
533 | dscr_default = val; | 539 | dscr_default = val; |
534 | 540 | ||
535 | on_each_cpu(update_dscr, NULL, 1); | 541 | on_each_cpu(write_dscr, &val, 1); |
536 | 542 | ||
537 | return count; | 543 | return count; |
538 | } | 544 | } |
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index ee061c3715de..2a324f4cb1b9 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S | |||
@@ -78,12 +78,6 @@ _GLOBAL(tm_abort) | |||
78 | TABORT(R3) | 78 | TABORT(R3) |
79 | blr | 79 | blr |
80 | 80 | ||
81 | .section ".toc","aw" | ||
82 | DSCR_DEFAULT: | ||
83 | .tc dscr_default[TC],dscr_default | ||
84 | |||
85 | .section ".text" | ||
86 | |||
87 | /* void tm_reclaim(struct thread_struct *thread, | 81 | /* void tm_reclaim(struct thread_struct *thread, |
88 | * unsigned long orig_msr, | 82 | * unsigned long orig_msr, |
89 | * uint8_t cause) | 83 | * uint8_t cause) |
@@ -298,9 +292,8 @@ dont_backup_fp: | |||
298 | mtlr r0 | 292 | mtlr r0 |
299 | ld r2, STK_GOT(r1) | 293 | ld r2, STK_GOT(r1) |
300 | 294 | ||
301 | /* Load system default DSCR */ | 295 | /* Load CPU's default DSCR */ |
302 | ld r4, DSCR_DEFAULT@toc(r2) | 296 | ld r0, PACA_DSCR(r13) |
303 | ld r0, 0(r4) | ||
304 | mtspr SPRN_DSCR, r0 | 297 | mtspr SPRN_DSCR, r0 |
305 | 298 | ||
306 | blr | 299 | blr |
@@ -479,9 +472,8 @@ restore_gprs: | |||
479 | mtlr r0 | 472 | mtlr r0 |
480 | ld r2, STK_GOT(r1) | 473 | ld r2, STK_GOT(r1) |
481 | 474 | ||
482 | /* Load system default DSCR */ | 475 | /* Load CPU's default DSCR */ |
483 | ld r4, DSCR_DEFAULT@toc(r2) | 476 | ld r0, PACA_DSCR(r13) |
484 | ld r0, 0(r4) | ||
485 | mtspr SPRN_DSCR, r0 | 477 | mtspr SPRN_DSCR, r0 |
486 | 478 | ||
487 | blr | 479 | blr |