aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/emulated_ops.h4
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h4
-rw-r--r--arch/powerpc/include/asm/processor.h4
-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
8 files changed, 106 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h
index f0fb4fc1f6e6..45921672b97a 100644
--- a/arch/powerpc/include/asm/emulated_ops.h
+++ b/arch/powerpc/include/asm/emulated_ops.h
@@ -52,6 +52,10 @@ extern struct ppc_emulated {
52#ifdef CONFIG_VSX 52#ifdef CONFIG_VSX
53 struct ppc_emulated_entry vsx; 53 struct ppc_emulated_entry vsx;
54#endif 54#endif
55#ifdef CONFIG_PPC64
56 struct ppc_emulated_entry mfdscr;
57 struct ppc_emulated_entry mtdscr;
58#endif
55} ppc_emulated; 59} ppc_emulated;
56 60
57extern u32 ppc_warn_emulated; 61extern u32 ppc_warn_emulated;
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 3e25b258568e..e472659d906c 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -41,6 +41,10 @@
41#define PPC_INST_RFCI 0x4c000066 41#define PPC_INST_RFCI 0x4c000066
42#define PPC_INST_RFDI 0x4c00004e 42#define PPC_INST_RFDI 0x4c00004e
43#define PPC_INST_RFMCI 0x4c00004c 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#define PPC_INST_STRING 0x7c00042a 49#define PPC_INST_STRING 0x7c00042a
46#define PPC_INST_STRING_MASK 0xfc0007fe 50#define PPC_INST_STRING_MASK 0xfc0007fe
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index de1967a1ff57..d50c2b6d9bc3 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -238,6 +238,10 @@ struct thread_struct {
238#ifdef CONFIG_KVM_BOOK3S_32_HANDLER 238#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
239 void* kvm_shadow_vcpu; /* KVM internal data */ 239 void* kvm_shadow_vcpu; /* KVM internal data */
240#endif /* CONFIG_KVM_BOOK3S_32_HANDLER */ 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#define ARCH_MIN_TASKALIGN 16 247#define ARCH_MIN_TASKALIGN 16
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;