aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@au1.ibm.com>2011-03-02 10:18:48 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-04-27 00:18:19 -0400
commitefcac6589a277c10060e4be44b9455cf43838dc1 (patch)
treed2236c1e9385baff297f0652c5a22b74f6acb149 /arch/powerpc/kernel
parentf0aae3238fc1c28b543cbaaa0e7c5d57685f5f89 (diff)
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>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kernel/entry_64.S15
-rw-r--r--arch/powerpc/kernel/process.c16
-rw-r--r--arch/powerpc/kernel/sysfs.c38
-rw-r--r--arch/powerpc/kernel/traps.c24
5 files changed, 94 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 23e6a93145ab..6887661ac072 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -74,6 +74,7 @@ int main(void)
74 DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); 74 DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
75 DEFINE(SIGSEGV, SIGSEGV); 75 DEFINE(SIGSEGV, SIGSEGV);
76 DEFINE(NMI_MASK, NMI_MASK); 76 DEFINE(NMI_MASK, NMI_MASK);
77 DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
77#else 78#else
78 DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); 79 DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
79#endif /* CONFIG_PPC64 */ 80#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index dbf5bfafd7bc..64693706ebfd 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -421,6 +421,12 @@ BEGIN_FTR_SECTION
421 std r24,THREAD_VRSAVE(r3) 421 std r24,THREAD_VRSAVE(r3)
422END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 422END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
423#endif /* CONFIG_ALTIVEC */ 423#endif /* CONFIG_ALTIVEC */
424#ifdef CONFIG_PPC64
425BEGIN_FTR_SECTION
426 mfspr r25,SPRN_DSCR
427 std r25,THREAD_DSCR(r3)
428END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
429#endif
424 and. r0,r0,r22 430 and. r0,r0,r22
425 beq+ 1f 431 beq+ 1f
426 andc r22,r22,r0 432 andc r22,r22,r0
@@ -522,6 +528,15 @@ BEGIN_FTR_SECTION
522 mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */ 528 mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */
523END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 529END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
524#endif /* CONFIG_ALTIVEC */ 530#endif /* CONFIG_ALTIVEC */
531#ifdef CONFIG_PPC64
532BEGIN_FTR_SECTION
533 ld r0,THREAD_DSCR(r4)
534 cmpd r0,r25
535 beq 1f
536 mtspr SPRN_DSCR,r0
5371:
538END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
539#endif
525 540
526 /* r3-r13 are destroyed -- Cort */ 541 /* r3-r13 are destroyed -- Cort */
527 REST_8GPRS(14, r1) 542 REST_8GPRS(14, r1)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index f74f355a9617..a01c2d93fd2f 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -702,6 +702,8 @@ void prepare_to_copy(struct task_struct *tsk)
702/* 702/*
703 * Copy a thread.. 703 * Copy a thread..
704 */ 704 */
705extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
706
705int copy_thread(unsigned long clone_flags, unsigned long usp, 707int copy_thread(unsigned long clone_flags, unsigned long usp,
706 unsigned long unused, struct task_struct *p, 708 unsigned long unused, struct task_struct *p,
707 struct pt_regs *regs) 709 struct pt_regs *regs)
@@ -769,6 +771,20 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
769 p->thread.ksp_vsid = sp_vsid; 771 p->thread.ksp_vsid = sp_vsid;
770 } 772 }
771#endif /* CONFIG_PPC_STD_MMU_64 */ 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 * The PPC64 ABI makes use of a TOC to contain function 790 * The PPC64 ABI makes use of a TOC to contain function
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index c0d8c2006bf4..f0f2199e64e1 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -182,6 +182,41 @@ static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
182static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL); 182static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
183static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr); 183static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
184static SYSDEV_ATTR(purr, 0600, show_purr, store_purr); 184static SYSDEV_ATTR(purr, 0600, show_purr, store_purr);
185
186unsigned long dscr_default = 0;
187EXPORT_SYMBOL(dscr_default);
188
189static 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
195static 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
210static SYSDEV_CLASS_ATTR(dscr_default, 0600,
211 show_dscr_default, store_dscr_default);
212
213static 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#endif /* CONFIG_PPC64 */ 220#endif /* CONFIG_PPC64 */
186 221
187#ifdef HAS_PPC_PMC_PA6T 222#ifdef HAS_PPC_PMC_PA6T
@@ -617,6 +652,9 @@ static int __init topology_init(void)
617 if (cpu_online(cpu)) 652 if (cpu_online(cpu))
618 register_cpu_online(cpu); 653 register_cpu_online(cpu);
619 } 654 }
655#ifdef CONFIG_PPC64
656 sysfs_create_dscr_default();
657#endif /* CONFIG_PPC64 */
620 658
621 return 0; 659 return 0;
622} 660}
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5ddb801bc154..cb71cf29edea 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -909,6 +909,26 @@ static int emulate_instruction(struct pt_regs *regs)
909 return emulate_isel(regs, instword); 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 return -EINVAL; 932 return -EINVAL;
913} 933}
914 934
@@ -1506,6 +1526,10 @@ struct ppc_emulated ppc_emulated = {
1506#ifdef CONFIG_VSX 1526#ifdef CONFIG_VSX
1507 WARN_EMULATED_SETUP(vsx), 1527 WARN_EMULATED_SETUP(vsx),
1508#endif 1528#endif
1529#ifdef CONFIG_PPC64
1530 WARN_EMULATED_SETUP(mfdscr),
1531 WARN_EMULATED_SETUP(mtdscr),
1532#endif
1509}; 1533};
1510 1534
1511u32 ppc_warn_emulated; 1535u32 ppc_warn_emulated;