Commit efcac6589a277c10060e4be44b9455cf43838dc1

Authored by Alexey Kardashevskiy
Committed by Benjamin Herrenschmidt
1 parent f0aae3238f

powerpc: Per process DSCR + some fixes (try#4)

The DSCR (aka Data Stream Control Register) is supported on some
server PowerPC chips and allow some control over the prefetch
of data streams.

This patch allows the value to be specified per thread by emulating
the corresponding mfspr and mtspr instructions. Children of such
threads inherit the value. Other threads use a default value that
can be specified in sysfs - /sys/devices/system/cpu/dscr_default.

If a thread starts with non default value in the sysfs entry,
all children threads inherit this non default value even if
the sysfs value is changed later.

Signed-off-by: Alexey Kardashevskiy <aik@au1.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Showing 8 changed files with 106 additions and 0 deletions Side-by-side Diff

arch/powerpc/include/asm/emulated_ops.h
... ... @@ -52,6 +52,10 @@
52 52 #ifdef CONFIG_VSX
53 53 struct ppc_emulated_entry vsx;
54 54 #endif
  55 +#ifdef CONFIG_PPC64
  56 + struct ppc_emulated_entry mfdscr;
  57 + struct ppc_emulated_entry mtdscr;
  58 +#endif
55 59 } ppc_emulated;
56 60  
57 61 extern u32 ppc_warn_emulated;
arch/powerpc/include/asm/ppc-opcode.h
... ... @@ -41,6 +41,10 @@
41 41 #define PPC_INST_RFCI 0x4c000066
42 42 #define PPC_INST_RFDI 0x4c00004e
43 43 #define PPC_INST_RFMCI 0x4c00004c
  44 +#define PPC_INST_MFSPR_DSCR 0x7c1102a6
  45 +#define PPC_INST_MFSPR_DSCR_MASK 0xfc1fffff
  46 +#define PPC_INST_MTSPR_DSCR 0x7c1103a6
  47 +#define PPC_INST_MTSPR_DSCR_MASK 0xfc1fffff
44 48  
45 49 #define PPC_INST_STRING 0x7c00042a
46 50 #define PPC_INST_STRING_MASK 0xfc0007fe
arch/powerpc/include/asm/processor.h
... ... @@ -238,6 +238,10 @@
238 238 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
239 239 void* kvm_shadow_vcpu; /* KVM internal data */
240 240 #endif /* CONFIG_KVM_BOOK3S_32_HANDLER */
  241 +#ifdef CONFIG_PPC64
  242 + unsigned long dscr;
  243 + int dscr_inherit;
  244 +#endif
241 245 };
242 246  
243 247 #define ARCH_MIN_TASKALIGN 16
arch/powerpc/kernel/asm-offsets.c
... ... @@ -74,6 +74,7 @@
74 74 DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
75 75 DEFINE(SIGSEGV, SIGSEGV);
76 76 DEFINE(NMI_MASK, NMI_MASK);
  77 + DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
77 78 #else
78 79 DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
79 80 #endif /* CONFIG_PPC64 */
arch/powerpc/kernel/entry_64.S
... ... @@ -421,6 +421,12 @@
421 421 std r24,THREAD_VRSAVE(r3)
422 422 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
423 423 #endif /* CONFIG_ALTIVEC */
  424 +#ifdef CONFIG_PPC64
  425 +BEGIN_FTR_SECTION
  426 + mfspr r25,SPRN_DSCR
  427 + std r25,THREAD_DSCR(r3)
  428 +END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
  429 +#endif
424 430 and. r0,r0,r22
425 431 beq+ 1f
426 432 andc r22,r22,r0
... ... @@ -522,6 +528,15 @@
522 528 mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
523 529 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
524 530 #endif /* CONFIG_ALTIVEC */
  531 +#ifdef CONFIG_PPC64
  532 +BEGIN_FTR_SECTION
  533 + ld r0,THREAD_DSCR(r4)
  534 + cmpd r0,r25
  535 + beq 1f
  536 + mtspr SPRN_DSCR,r0
  537 +1:
  538 +END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
  539 +#endif
525 540  
526 541 /* r3-r13 are destroyed -- Cort */
527 542 REST_8GPRS(14, r1)
arch/powerpc/kernel/process.c
... ... @@ -702,6 +702,8 @@
702 702 /*
703 703 * Copy a thread..
704 704 */
  705 +extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
  706 +
705 707 int copy_thread(unsigned long clone_flags, unsigned long usp,
706 708 unsigned long unused, struct task_struct *p,
707 709 struct pt_regs *regs)
... ... @@ -769,6 +771,20 @@
769 771 p->thread.ksp_vsid = sp_vsid;
770 772 }
771 773 #endif /* CONFIG_PPC_STD_MMU_64 */
  774 +#ifdef CONFIG_PPC64
  775 + if (cpu_has_feature(CPU_FTR_DSCR)) {
  776 + if (current->thread.dscr_inherit) {
  777 + p->thread.dscr_inherit = 1;
  778 + p->thread.dscr = current->thread.dscr;
  779 + } else if (0 != dscr_default) {
  780 + p->thread.dscr_inherit = 1;
  781 + p->thread.dscr = dscr_default;
  782 + } else {
  783 + p->thread.dscr_inherit = 0;
  784 + p->thread.dscr = 0;
  785 + }
  786 + }
  787 +#endif
772 788  
773 789 /*
774 790 * The PPC64 ABI makes use of a TOC to contain function
arch/powerpc/kernel/sysfs.c
... ... @@ -182,6 +182,41 @@
182 182 static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
183 183 static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
184 184 static SYSDEV_ATTR(purr, 0600, show_purr, store_purr);
  185 +
  186 +unsigned long dscr_default = 0;
  187 +EXPORT_SYMBOL(dscr_default);
  188 +
  189 +static ssize_t show_dscr_default(struct sysdev_class *class,
  190 + struct sysdev_class_attribute *attr, char *buf)
  191 +{
  192 + return sprintf(buf, "%lx\n", dscr_default);
  193 +}
  194 +
  195 +static ssize_t __used store_dscr_default(struct sysdev_class *class,
  196 + struct sysdev_class_attribute *attr, const char *buf,
  197 + size_t count)
  198 +{
  199 + unsigned long val;
  200 + int ret = 0;
  201 +
  202 + ret = sscanf(buf, "%lx", &val);
  203 + if (ret != 1)
  204 + return -EINVAL;
  205 + dscr_default = val;
  206 +
  207 + return count;
  208 +}
  209 +
  210 +static SYSDEV_CLASS_ATTR(dscr_default, 0600,
  211 + show_dscr_default, store_dscr_default);
  212 +
  213 +static void sysfs_create_dscr_default(void)
  214 +{
  215 + int err = 0;
  216 + if (cpu_has_feature(CPU_FTR_DSCR))
  217 + err = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
  218 + &attr_dscr_default.attr);
  219 +}
185 220 #endif /* CONFIG_PPC64 */
186 221  
187 222 #ifdef HAS_PPC_PMC_PA6T
... ... @@ -617,6 +652,9 @@
617 652 if (cpu_online(cpu))
618 653 register_cpu_online(cpu);
619 654 }
  655 +#ifdef CONFIG_PPC64
  656 + sysfs_create_dscr_default();
  657 +#endif /* CONFIG_PPC64 */
620 658  
621 659 return 0;
622 660 }
arch/powerpc/kernel/traps.c
... ... @@ -909,6 +909,26 @@
909 909 return emulate_isel(regs, instword);
910 910 }
911 911  
  912 +#ifdef CONFIG_PPC64
  913 + /* Emulate the mfspr rD, DSCR. */
  914 + if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) &&
  915 + cpu_has_feature(CPU_FTR_DSCR)) {
  916 + PPC_WARN_EMULATED(mfdscr, regs);
  917 + rd = (instword >> 21) & 0x1f;
  918 + regs->gpr[rd] = mfspr(SPRN_DSCR);
  919 + return 0;
  920 + }
  921 + /* Emulate the mtspr DSCR, rD. */
  922 + if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) &&
  923 + cpu_has_feature(CPU_FTR_DSCR)) {
  924 + PPC_WARN_EMULATED(mtdscr, regs);
  925 + rd = (instword >> 21) & 0x1f;
  926 + mtspr(SPRN_DSCR, regs->gpr[rd]);
  927 + current->thread.dscr_inherit = 1;
  928 + return 0;
  929 + }
  930 +#endif
  931 +
912 932 return -EINVAL;
913 933 }
914 934  
... ... @@ -1505,6 +1525,10 @@
1505 1525 #endif
1506 1526 #ifdef CONFIG_VSX
1507 1527 WARN_EMULATED_SETUP(vsx),
  1528 +#endif
  1529 +#ifdef CONFIG_PPC64
  1530 + WARN_EMULATED_SETUP(mfdscr),
  1531 + WARN_EMULATED_SETUP(mtdscr),
1508 1532 #endif
1509 1533 };
1510 1534