powerpc: Fix regression of per-CPU DSCR setting
authorSam bobroff <sam.bobroff@au1.ibm.com>
Wed, 21 May 2014 06:32:38 +0000 (16:32 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 28 May 2014 03:35:40 +0000 (13:35 +1000)
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>
arch/powerpc/include/asm/paca.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/tm.S
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index 8e956a0b6e85ac4474b71373fee731bc7f5d6044..bb0bd25f20d0aeb7b43ac061e3c59835955f1c8b 100644 (file)
@@ -92,7 +92,10 @@ struct paca_struct {
        struct slb_shadow *slb_shadow_ptr;
        struct dtl_entry *dispatch_log;
        struct dtl_entry *dispatch_log_end;
+#endif /* CONFIG_PPC_STD_MMU_64 */
+       u64 dscr_default;               /* per-CPU default DSCR */
 
+#ifdef CONFIG_PPC_STD_MMU_64
        /*
         * Now, starting in cacheline 2, the exception save areas
         */
index dba8140ebc20b8d425bafabe5a0edf57bea2e1bb..cba2697406b70175a0fcb1721e83381c42497fcf 100644 (file)
@@ -247,6 +247,7 @@ int main(void)
 #endif
        DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
        DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
+       DEFINE(PACA_DSCR, offsetof(struct paca_struct, dscr_default));
        DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
        DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user));
        DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
index 9fde8a1bf1e14d617cce4a8093ff210536e271f2..911d45366f596c764a4ad001025760de4f07c5e8 100644 (file)
@@ -387,12 +387,6 @@ _GLOBAL(ret_from_kernel_thread)
        li      r3,0
        b       syscall_exit
 
-       .section        ".toc","aw"
-DSCR_DEFAULT:
-       .tc dscr_default[TC],dscr_default
-
-       .section        ".text"
-
 /*
  * This routine switches between two different tasks.  The process
  * state of one is saved on its kernel stack.  Then the state
@@ -577,11 +571,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #ifdef CONFIG_PPC64
 BEGIN_FTR_SECTION
        lwz     r6,THREAD_DSCR_INHERIT(r4)
-       ld      r7,DSCR_DEFAULT@toc(2)
        ld      r0,THREAD_DSCR(r4)
        cmpwi   r6,0
        bne     1f
-       ld      r0,0(r7)
+       ld      r0,PACA_DSCR(r13)
 1:
 BEGIN_FTR_SECTION_NESTED(70)
        mfspr   r8, SPRN_FSCR
index e2a1d6fb3297ec4a9f14578705cc3cf71bf989b3..67fd2fd2620ae64a2f44cced5a25b68d49877c50 100644 (file)
@@ -484,7 +484,6 @@ SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
 SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
 SYSFS_SPRSETUP(purr, SPRN_PURR);
 SYSFS_SPRSETUP(spurr, SPRN_SPURR);
-SYSFS_SPRSETUP(dscr, SPRN_DSCR);
 SYSFS_SPRSETUP(pir, SPRN_PIR);
 
 /*
@@ -494,12 +493,27 @@ SYSFS_SPRSETUP(pir, SPRN_PIR);
 */
 static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
 static DEVICE_ATTR(spurr, 0400, show_spurr, NULL);
-static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
 static DEVICE_ATTR(purr, 0400, show_purr, store_purr);
 static DEVICE_ATTR(pir, 0400, show_pir, NULL);
 
-unsigned long dscr_default = 0;
-EXPORT_SYMBOL(dscr_default);
+static unsigned long dscr_default;
+
+static void read_dscr(void *val)
+{
+       *(unsigned long *)val = get_paca()->dscr_default;
+}
+
+static void write_dscr(void *val)
+{
+       get_paca()->dscr_default = *(unsigned long *)val;
+       if (!current->thread.dscr_inherit) {
+               current->thread.dscr = *(unsigned long *)val;
+               mtspr(SPRN_DSCR, *(unsigned long *)val);
+       }
+}
+
+SYSFS_SPRSETUP_SHOW_STORE(dscr);
+static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
 
 static void add_write_permission_dev_attr(struct device_attribute *attr)
 {
@@ -512,14 +526,6 @@ static ssize_t show_dscr_default(struct device *dev,
        return sprintf(buf, "%lx\n", dscr_default);
 }
 
-static void update_dscr(void *dummy)
-{
-       if (!current->thread.dscr_inherit) {
-               current->thread.dscr = dscr_default;
-               mtspr(SPRN_DSCR, dscr_default);
-       }
-}
-
 static ssize_t __used store_dscr_default(struct device *dev,
                struct device_attribute *attr, const char *buf,
                size_t count)
@@ -532,7 +538,7 @@ static ssize_t __used store_dscr_default(struct device *dev,
                return -EINVAL;
        dscr_default = val;
 
-       on_each_cpu(update_dscr, NULL, 1);
+       on_each_cpu(write_dscr, &val, 1);
 
        return count;
 }
index ee061c3715deb0b66247247938a60a46d34e5131..2a324f4cb1b9bd2d7354b783641d40ed54c5a2c2 100644 (file)
@@ -78,12 +78,6 @@ _GLOBAL(tm_abort)
        TABORT(R3)
        blr
 
-       .section        ".toc","aw"
-DSCR_DEFAULT:
-       .tc dscr_default[TC],dscr_default
-
-       .section        ".text"
-
 /* void tm_reclaim(struct thread_struct *thread,
  *                 unsigned long orig_msr,
  *                uint8_t cause)
@@ -298,9 +292,8 @@ dont_backup_fp:
        mtlr    r0
        ld      r2, STK_GOT(r1)
 
-       /* Load system default DSCR */
-       ld      r4, DSCR_DEFAULT@toc(r2)
-       ld      r0, 0(r4)
+       /* Load CPU's default DSCR */
+       ld      r0, PACA_DSCR(r13)
        mtspr   SPRN_DSCR, r0
 
        blr
@@ -479,9 +472,8 @@ restore_gprs:
        mtlr    r0
        ld      r2, STK_GOT(r1)
 
-       /* Load system default DSCR */
-       ld      r4, DSCR_DEFAULT@toc(r2)
-       ld      r0, 0(r4)
+       /* Load CPU's default DSCR */
+       ld      r0, PACA_DSCR(r13)
        mtspr   SPRN_DSCR, r0
 
        blr
index 9f0ad718e4766bd2b114d4314def16a46b304ebe..12f4ce5b4f7891e8779e86978bd915a9bf1ebbbe 100644 (file)
@@ -286,8 +286,7 @@ kvm_start_guest:
        beq     kvm_no_guest
 
        /* Set HSTATE_DSCR(r13) to something sensible */
-       LOAD_REG_ADDR(r6, dscr_default)
-       ld      r6, 0(r6)
+       ld      r6, PACA_DSCR(r13)
        std     r6, HSTATE_DSCR(r13)
 
        bl      kvmppc_hv_entry