diff options
-rw-r--r-- | arch/powerpc/include/asm/emulated_ops.h | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc-opcode.h | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/processor.h | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 15 | ||||
-rw-r--r-- | arch/powerpc/kernel/process.c | 16 | ||||
-rw-r--r-- | arch/powerpc/kernel/sysfs.c | 38 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 24 |
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 | ||
57 | extern u32 ppc_warn_emulated; | 61 | extern 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) |
422 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 422 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
423 | #endif /* CONFIG_ALTIVEC */ | 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 | 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 */ |
523 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 529 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
524 | #endif /* CONFIG_ALTIVEC */ | 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 | /* 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 | */ |
705 | extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ | ||
706 | |||
705 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 707 | int 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); | |||
182 | static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL); | 182 | static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL); |
183 | static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr); | 183 | static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr); |
184 | static SYSDEV_ATTR(purr, 0600, show_purr, store_purr); | 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 | #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 | ||
1511 | u32 ppc_warn_emulated; | 1535 | u32 ppc_warn_emulated; |