diff options
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r-- | arch/ppc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/ppc/kernel/align.c | 12 | ||||
-rw-r--r-- | arch/ppc/kernel/cpu_setup_6xx.S | 42 | ||||
-rw-r--r-- | arch/ppc/kernel/entry.S | 59 | ||||
-rw-r--r-- | arch/ppc/kernel/fpu.S | 133 | ||||
-rw-r--r-- | arch/ppc/kernel/head.S | 163 | ||||
-rw-r--r-- | arch/ppc/kernel/head_44x.S | 6 | ||||
-rw-r--r-- | arch/ppc/kernel/head_booke.h | 7 | ||||
-rw-r--r-- | arch/ppc/kernel/head_fsl_booke.S | 8 | ||||
-rw-r--r-- | arch/ppc/kernel/misc.S | 12 | ||||
-rw-r--r-- | arch/ppc/kernel/ptrace.c | 5 | ||||
-rw-r--r-- | arch/ppc/kernel/traps.c | 2 |
12 files changed, 266 insertions, 184 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 86bc878cb3ee..b284451802c9 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile | |||
@@ -9,6 +9,7 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o | |||
9 | extra-$(CONFIG_8xx) := head_8xx.o | 9 | extra-$(CONFIG_8xx) := head_8xx.o |
10 | extra-$(CONFIG_6xx) += idle_6xx.o | 10 | extra-$(CONFIG_6xx) += idle_6xx.o |
11 | extra-$(CONFIG_POWER4) += idle_power4.o | 11 | extra-$(CONFIG_POWER4) += idle_power4.o |
12 | extra-$(CONFIG_PPC_FPU) += fpu.o | ||
12 | extra-y += vmlinux.lds | 13 | extra-y += vmlinux.lds |
13 | 14 | ||
14 | obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ | 15 | obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ |
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c index 79c929475037..ff81da9598d8 100644 --- a/arch/ppc/kernel/align.c +++ b/arch/ppc/kernel/align.c | |||
@@ -290,6 +290,10 @@ fix_alignment(struct pt_regs *regs) | |||
290 | /* lwm, stmw */ | 290 | /* lwm, stmw */ |
291 | nb = (32 - reg) * 4; | 291 | nb = (32 - reg) * 4; |
292 | } | 292 | } |
293 | |||
294 | if (!access_ok((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb+nb0)) | ||
295 | return -EFAULT; /* bad address */ | ||
296 | |||
293 | rptr = (unsigned char *) ®s->gpr[reg]; | 297 | rptr = (unsigned char *) ®s->gpr[reg]; |
294 | if (flags & LD) { | 298 | if (flags & LD) { |
295 | for (i = 0; i < nb; ++i) | 299 | for (i = 0; i < nb; ++i) |
@@ -368,16 +372,24 @@ fix_alignment(struct pt_regs *regs) | |||
368 | 372 | ||
369 | /* Single-precision FP load and store require conversions... */ | 373 | /* Single-precision FP load and store require conversions... */ |
370 | case LD+F+S: | 374 | case LD+F+S: |
375 | #ifdef CONFIG_PPC_FPU | ||
371 | preempt_disable(); | 376 | preempt_disable(); |
372 | enable_kernel_fp(); | 377 | enable_kernel_fp(); |
373 | cvt_fd(&data.f, &data.d, ¤t->thread.fpscr); | 378 | cvt_fd(&data.f, &data.d, ¤t->thread.fpscr); |
374 | preempt_enable(); | 379 | preempt_enable(); |
380 | #else | ||
381 | return 0; | ||
382 | #endif | ||
375 | break; | 383 | break; |
376 | case ST+F+S: | 384 | case ST+F+S: |
385 | #ifdef CONFIG_PPC_FPU | ||
377 | preempt_disable(); | 386 | preempt_disable(); |
378 | enable_kernel_fp(); | 387 | enable_kernel_fp(); |
379 | cvt_df(&data.d, &data.f, ¤t->thread.fpscr); | 388 | cvt_df(&data.d, &data.f, ¤t->thread.fpscr); |
380 | preempt_enable(); | 389 | preempt_enable(); |
390 | #else | ||
391 | return 0; | ||
392 | #endif | ||
381 | break; | 393 | break; |
382 | } | 394 | } |
383 | 395 | ||
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S index 74f781b486a3..468721d9ebd2 100644 --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S | |||
@@ -30,12 +30,14 @@ _GLOBAL(__setup_cpu_604) | |||
30 | blr | 30 | blr |
31 | _GLOBAL(__setup_cpu_750) | 31 | _GLOBAL(__setup_cpu_750) |
32 | mflr r4 | 32 | mflr r4 |
33 | bl __init_fpu_registers | ||
33 | bl setup_common_caches | 34 | bl setup_common_caches |
34 | bl setup_750_7400_hid0 | 35 | bl setup_750_7400_hid0 |
35 | mtlr r4 | 36 | mtlr r4 |
36 | blr | 37 | blr |
37 | _GLOBAL(__setup_cpu_750cx) | 38 | _GLOBAL(__setup_cpu_750cx) |
38 | mflr r4 | 39 | mflr r4 |
40 | bl __init_fpu_registers | ||
39 | bl setup_common_caches | 41 | bl setup_common_caches |
40 | bl setup_750_7400_hid0 | 42 | bl setup_750_7400_hid0 |
41 | bl setup_750cx | 43 | bl setup_750cx |
@@ -43,6 +45,7 @@ _GLOBAL(__setup_cpu_750cx) | |||
43 | blr | 45 | blr |
44 | _GLOBAL(__setup_cpu_750fx) | 46 | _GLOBAL(__setup_cpu_750fx) |
45 | mflr r4 | 47 | mflr r4 |
48 | bl __init_fpu_registers | ||
46 | bl setup_common_caches | 49 | bl setup_common_caches |
47 | bl setup_750_7400_hid0 | 50 | bl setup_750_7400_hid0 |
48 | bl setup_750fx | 51 | bl setup_750fx |
@@ -50,6 +53,7 @@ _GLOBAL(__setup_cpu_750fx) | |||
50 | blr | 53 | blr |
51 | _GLOBAL(__setup_cpu_7400) | 54 | _GLOBAL(__setup_cpu_7400) |
52 | mflr r4 | 55 | mflr r4 |
56 | bl __init_fpu_registers | ||
53 | bl setup_7400_workarounds | 57 | bl setup_7400_workarounds |
54 | bl setup_common_caches | 58 | bl setup_common_caches |
55 | bl setup_750_7400_hid0 | 59 | bl setup_750_7400_hid0 |
@@ -57,6 +61,7 @@ _GLOBAL(__setup_cpu_7400) | |||
57 | blr | 61 | blr |
58 | _GLOBAL(__setup_cpu_7410) | 62 | _GLOBAL(__setup_cpu_7410) |
59 | mflr r4 | 63 | mflr r4 |
64 | bl __init_fpu_registers | ||
60 | bl setup_7410_workarounds | 65 | bl setup_7410_workarounds |
61 | bl setup_common_caches | 66 | bl setup_common_caches |
62 | bl setup_750_7400_hid0 | 67 | bl setup_750_7400_hid0 |
@@ -80,7 +85,7 @@ setup_common_caches: | |||
80 | bne 1f /* don't invalidate the D-cache */ | 85 | bne 1f /* don't invalidate the D-cache */ |
81 | ori r8,r8,HID0_DCI /* unless it wasn't enabled */ | 86 | ori r8,r8,HID0_DCI /* unless it wasn't enabled */ |
82 | 1: sync | 87 | 1: sync |
83 | mtspr SPRN_HID0,r8 /* enable and invalidate caches */ | 88 | mtspr SPRN_HID0,r8 /* enable and invalidate caches */ |
84 | sync | 89 | sync |
85 | mtspr SPRN_HID0,r11 /* enable caches */ | 90 | mtspr SPRN_HID0,r11 /* enable caches */ |
86 | sync | 91 | sync |
@@ -152,9 +157,13 @@ setup_7410_workarounds: | |||
152 | setup_750_7400_hid0: | 157 | setup_750_7400_hid0: |
153 | mfspr r11,SPRN_HID0 | 158 | mfspr r11,SPRN_HID0 |
154 | ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC | 159 | ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC |
160 | oris r11,r11,HID0_DPM@h | ||
155 | BEGIN_FTR_SECTION | 161 | BEGIN_FTR_SECTION |
156 | oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ | 162 | xori r11,r11,HID0_BTIC |
157 | END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | 163 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) |
164 | BEGIN_FTR_SECTION | ||
165 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ | ||
166 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) | ||
158 | li r3,HID0_SPD | 167 | li r3,HID0_SPD |
159 | andc r11,r11,r3 /* clear SPD: enable speculative */ | 168 | andc r11,r11,r3 /* clear SPD: enable speculative */ |
160 | li r3,0 | 169 | li r3,0 |
@@ -218,13 +227,15 @@ setup_745x_specifics: | |||
218 | 227 | ||
219 | /* All of the bits we have to set..... | 228 | /* All of the bits we have to set..... |
220 | */ | 229 | */ |
221 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC | 230 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE |
231 | ori r11,r11,HID0_LRSTK | HID0_BTIC | ||
232 | oris r11,r11,HID0_DPM@h | ||
222 | BEGIN_FTR_SECTION | 233 | BEGIN_FTR_SECTION |
223 | xori r11,r11,HID0_BTIC | 234 | xori r11,r11,HID0_BTIC |
224 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) | 235 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) |
225 | BEGIN_FTR_SECTION | 236 | BEGIN_FTR_SECTION |
226 | oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ | 237 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ |
227 | END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | 238 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) |
228 | 239 | ||
229 | /* All of the bits we have to clear.... | 240 | /* All of the bits we have to clear.... |
230 | */ | 241 | */ |
@@ -248,6 +259,25 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | |||
248 | isync | 259 | isync |
249 | blr | 260 | blr |
250 | 261 | ||
262 | /* | ||
263 | * Initialize the FPU registers. This is needed to work around an errata | ||
264 | * in some 750 cpus where using a not yet initialized FPU register after | ||
265 | * power on reset may hang the CPU | ||
266 | */ | ||
267 | _GLOBAL(__init_fpu_registers) | ||
268 | mfmsr r10 | ||
269 | ori r11,r10,MSR_FP | ||
270 | mtmsr r11 | ||
271 | isync | ||
272 | addis r9,r3,empty_zero_page@ha | ||
273 | addi r9,r9,empty_zero_page@l | ||
274 | REST_32FPRS(0,r9) | ||
275 | sync | ||
276 | mtmsr r10 | ||
277 | isync | ||
278 | blr | ||
279 | |||
280 | |||
251 | /* Definitions for the table use to save CPU states */ | 281 | /* Definitions for the table use to save CPU states */ |
252 | #define CS_HID0 0 | 282 | #define CS_HID0 0 |
253 | #define CS_HID1 4 | 283 | #define CS_HID1 4 |
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 035217d6c0f1..5f075dbc4ee7 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S | |||
@@ -563,6 +563,65 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
563 | addi r1,r1,INT_FRAME_SIZE | 563 | addi r1,r1,INT_FRAME_SIZE |
564 | blr | 564 | blr |
565 | 565 | ||
566 | .globl fast_exception_return | ||
567 | fast_exception_return: | ||
568 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | ||
569 | andi. r10,r9,MSR_RI /* check for recoverable interrupt */ | ||
570 | beq 1f /* if not, we've got problems */ | ||
571 | #endif | ||
572 | |||
573 | 2: REST_4GPRS(3, r11) | ||
574 | lwz r10,_CCR(r11) | ||
575 | REST_GPR(1, r11) | ||
576 | mtcr r10 | ||
577 | lwz r10,_LINK(r11) | ||
578 | mtlr r10 | ||
579 | REST_GPR(10, r11) | ||
580 | mtspr SPRN_SRR1,r9 | ||
581 | mtspr SPRN_SRR0,r12 | ||
582 | REST_GPR(9, r11) | ||
583 | REST_GPR(12, r11) | ||
584 | lwz r11,GPR11(r11) | ||
585 | SYNC | ||
586 | RFI | ||
587 | |||
588 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | ||
589 | /* check if the exception happened in a restartable section */ | ||
590 | 1: lis r3,exc_exit_restart_end@ha | ||
591 | addi r3,r3,exc_exit_restart_end@l | ||
592 | cmplw r12,r3 | ||
593 | bge 3f | ||
594 | lis r4,exc_exit_restart@ha | ||
595 | addi r4,r4,exc_exit_restart@l | ||
596 | cmplw r12,r4 | ||
597 | blt 3f | ||
598 | lis r3,fee_restarts@ha | ||
599 | tophys(r3,r3) | ||
600 | lwz r5,fee_restarts@l(r3) | ||
601 | addi r5,r5,1 | ||
602 | stw r5,fee_restarts@l(r3) | ||
603 | mr r12,r4 /* restart at exc_exit_restart */ | ||
604 | b 2b | ||
605 | |||
606 | .comm fee_restarts,4 | ||
607 | |||
608 | /* aargh, a nonrecoverable interrupt, panic */ | ||
609 | /* aargh, we don't know which trap this is */ | ||
610 | /* but the 601 doesn't implement the RI bit, so assume it's OK */ | ||
611 | 3: | ||
612 | BEGIN_FTR_SECTION | ||
613 | b 2b | ||
614 | END_FTR_SECTION_IFSET(CPU_FTR_601) | ||
615 | li r10,-1 | ||
616 | stw r10,TRAP(r11) | ||
617 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
618 | lis r10,MSR_KERNEL@h | ||
619 | ori r10,r10,MSR_KERNEL@l | ||
620 | bl transfer_to_handler_full | ||
621 | .long nonrecoverable_exception | ||
622 | .long ret_from_except | ||
623 | #endif | ||
624 | |||
566 | .globl sigreturn_exit | 625 | .globl sigreturn_exit |
567 | sigreturn_exit: | 626 | sigreturn_exit: |
568 | subi r1,r3,STACK_FRAME_OVERHEAD | 627 | subi r1,r3,STACK_FRAME_OVERHEAD |
diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S new file mode 100644 index 000000000000..6189b26f640f --- /dev/null +++ b/arch/ppc/kernel/fpu.S | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * FPU support code, moved here from head.S so that it can be used | ||
3 | * by chips which use other head-whatever.S files. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <asm/processor.h> | ||
14 | #include <asm/page.h> | ||
15 | #include <asm/mmu.h> | ||
16 | #include <asm/pgtable.h> | ||
17 | #include <asm/cputable.h> | ||
18 | #include <asm/cache.h> | ||
19 | #include <asm/thread_info.h> | ||
20 | #include <asm/ppc_asm.h> | ||
21 | #include <asm/offsets.h> | ||
22 | |||
23 | /* | ||
24 | * This task wants to use the FPU now. | ||
25 | * On UP, disable FP for the task which had the FPU previously, | ||
26 | * and save its floating-point registers in its thread_struct. | ||
27 | * Load up this task's FP registers from its thread_struct, | ||
28 | * enable the FPU for the current task and return to the task. | ||
29 | */ | ||
30 | .globl load_up_fpu | ||
31 | load_up_fpu: | ||
32 | mfmsr r5 | ||
33 | ori r5,r5,MSR_FP | ||
34 | #ifdef CONFIG_PPC64BRIDGE | ||
35 | clrldi r5,r5,1 /* turn off 64-bit mode */ | ||
36 | #endif /* CONFIG_PPC64BRIDGE */ | ||
37 | SYNC | ||
38 | MTMSRD(r5) /* enable use of fpu now */ | ||
39 | isync | ||
40 | /* | ||
41 | * For SMP, we don't do lazy FPU switching because it just gets too | ||
42 | * horrendously complex, especially when a task switches from one CPU | ||
43 | * to another. Instead we call giveup_fpu in switch_to. | ||
44 | */ | ||
45 | #ifndef CONFIG_SMP | ||
46 | tophys(r6,0) /* get __pa constant */ | ||
47 | addis r3,r6,last_task_used_math@ha | ||
48 | lwz r4,last_task_used_math@l(r3) | ||
49 | cmpwi 0,r4,0 | ||
50 | beq 1f | ||
51 | add r4,r4,r6 | ||
52 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | ||
53 | SAVE_32FPRS(0, r4) | ||
54 | mffs fr0 | ||
55 | stfd fr0,THREAD_FPSCR-4(r4) | ||
56 | lwz r5,PT_REGS(r4) | ||
57 | add r5,r5,r6 | ||
58 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
59 | li r10,MSR_FP|MSR_FE0|MSR_FE1 | ||
60 | andc r4,r4,r10 /* disable FP for previous task */ | ||
61 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
62 | 1: | ||
63 | #endif /* CONFIG_SMP */ | ||
64 | /* enable use of FP after return */ | ||
65 | mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ | ||
66 | lwz r4,THREAD_FPEXC_MODE(r5) | ||
67 | ori r9,r9,MSR_FP /* enable FP for current */ | ||
68 | or r9,r9,r4 | ||
69 | lfd fr0,THREAD_FPSCR-4(r5) | ||
70 | mtfsf 0xff,fr0 | ||
71 | REST_32FPRS(0, r5) | ||
72 | #ifndef CONFIG_SMP | ||
73 | subi r4,r5,THREAD | ||
74 | sub r4,r4,r6 | ||
75 | stw r4,last_task_used_math@l(r3) | ||
76 | #endif /* CONFIG_SMP */ | ||
77 | /* restore registers and return */ | ||
78 | /* we haven't used ctr or xer or lr */ | ||
79 | b fast_exception_return | ||
80 | |||
81 | /* | ||
82 | * FP unavailable trap from kernel - print a message, but let | ||
83 | * the task use FP in the kernel until it returns to user mode. | ||
84 | */ | ||
85 | .globl KernelFP | ||
86 | KernelFP: | ||
87 | lwz r3,_MSR(r1) | ||
88 | ori r3,r3,MSR_FP | ||
89 | stw r3,_MSR(r1) /* enable use of FP after return */ | ||
90 | lis r3,86f@h | ||
91 | ori r3,r3,86f@l | ||
92 | mr r4,r2 /* current */ | ||
93 | lwz r5,_NIP(r1) | ||
94 | bl printk | ||
95 | b ret_from_except | ||
96 | 86: .string "floating point used in kernel (task=%p, pc=%x)\n" | ||
97 | .align 4,0 | ||
98 | |||
99 | /* | ||
100 | * giveup_fpu(tsk) | ||
101 | * Disable FP for the task given as the argument, | ||
102 | * and save the floating-point registers in its thread_struct. | ||
103 | * Enables the FPU for use in the kernel on return. | ||
104 | */ | ||
105 | .globl giveup_fpu | ||
106 | giveup_fpu: | ||
107 | mfmsr r5 | ||
108 | ori r5,r5,MSR_FP | ||
109 | SYNC_601 | ||
110 | ISYNC_601 | ||
111 | MTMSRD(r5) /* enable use of fpu now */ | ||
112 | SYNC_601 | ||
113 | isync | ||
114 | cmpwi 0,r3,0 | ||
115 | beqlr- /* if no previous owner, done */ | ||
116 | addi r3,r3,THREAD /* want THREAD of task */ | ||
117 | lwz r5,PT_REGS(r3) | ||
118 | cmpwi 0,r5,0 | ||
119 | SAVE_32FPRS(0, r3) | ||
120 | mffs fr0 | ||
121 | stfd fr0,THREAD_FPSCR-4(r3) | ||
122 | beq 1f | ||
123 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
124 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | ||
125 | andc r4,r4,r3 /* disable FP for previous task */ | ||
126 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
127 | 1: | ||
128 | #ifndef CONFIG_SMP | ||
129 | li r5,0 | ||
130 | lis r4,last_task_used_math@ha | ||
131 | stw r5,last_task_used_math@l(r4) | ||
132 | #endif /* CONFIG_SMP */ | ||
133 | blr | ||
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 1a89a71e0acc..a931d773715f 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S | |||
@@ -775,133 +775,6 @@ InstructionSegment: | |||
775 | EXC_XFER_STD(0x480, UnknownException) | 775 | EXC_XFER_STD(0x480, UnknownException) |
776 | #endif /* CONFIG_PPC64BRIDGE */ | 776 | #endif /* CONFIG_PPC64BRIDGE */ |
777 | 777 | ||
778 | /* | ||
779 | * This task wants to use the FPU now. | ||
780 | * On UP, disable FP for the task which had the FPU previously, | ||
781 | * and save its floating-point registers in its thread_struct. | ||
782 | * Load up this task's FP registers from its thread_struct, | ||
783 | * enable the FPU for the current task and return to the task. | ||
784 | */ | ||
785 | load_up_fpu: | ||
786 | mfmsr r5 | ||
787 | ori r5,r5,MSR_FP | ||
788 | #ifdef CONFIG_PPC64BRIDGE | ||
789 | clrldi r5,r5,1 /* turn off 64-bit mode */ | ||
790 | #endif /* CONFIG_PPC64BRIDGE */ | ||
791 | SYNC | ||
792 | MTMSRD(r5) /* enable use of fpu now */ | ||
793 | isync | ||
794 | /* | ||
795 | * For SMP, we don't do lazy FPU switching because it just gets too | ||
796 | * horrendously complex, especially when a task switches from one CPU | ||
797 | * to another. Instead we call giveup_fpu in switch_to. | ||
798 | */ | ||
799 | #ifndef CONFIG_SMP | ||
800 | tophys(r6,0) /* get __pa constant */ | ||
801 | addis r3,r6,last_task_used_math@ha | ||
802 | lwz r4,last_task_used_math@l(r3) | ||
803 | cmpwi 0,r4,0 | ||
804 | beq 1f | ||
805 | add r4,r4,r6 | ||
806 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | ||
807 | SAVE_32FPRS(0, r4) | ||
808 | mffs fr0 | ||
809 | stfd fr0,THREAD_FPSCR-4(r4) | ||
810 | lwz r5,PT_REGS(r4) | ||
811 | add r5,r5,r6 | ||
812 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
813 | li r10,MSR_FP|MSR_FE0|MSR_FE1 | ||
814 | andc r4,r4,r10 /* disable FP for previous task */ | ||
815 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
816 | 1: | ||
817 | #endif /* CONFIG_SMP */ | ||
818 | /* enable use of FP after return */ | ||
819 | mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ | ||
820 | lwz r4,THREAD_FPEXC_MODE(r5) | ||
821 | ori r9,r9,MSR_FP /* enable FP for current */ | ||
822 | or r9,r9,r4 | ||
823 | lfd fr0,THREAD_FPSCR-4(r5) | ||
824 | mtfsf 0xff,fr0 | ||
825 | REST_32FPRS(0, r5) | ||
826 | #ifndef CONFIG_SMP | ||
827 | subi r4,r5,THREAD | ||
828 | sub r4,r4,r6 | ||
829 | stw r4,last_task_used_math@l(r3) | ||
830 | #endif /* CONFIG_SMP */ | ||
831 | /* restore registers and return */ | ||
832 | /* we haven't used ctr or xer or lr */ | ||
833 | /* fall through to fast_exception_return */ | ||
834 | |||
835 | .globl fast_exception_return | ||
836 | fast_exception_return: | ||
837 | andi. r10,r9,MSR_RI /* check for recoverable interrupt */ | ||
838 | beq 1f /* if not, we've got problems */ | ||
839 | 2: REST_4GPRS(3, r11) | ||
840 | lwz r10,_CCR(r11) | ||
841 | REST_GPR(1, r11) | ||
842 | mtcr r10 | ||
843 | lwz r10,_LINK(r11) | ||
844 | mtlr r10 | ||
845 | REST_GPR(10, r11) | ||
846 | mtspr SPRN_SRR1,r9 | ||
847 | mtspr SPRN_SRR0,r12 | ||
848 | REST_GPR(9, r11) | ||
849 | REST_GPR(12, r11) | ||
850 | lwz r11,GPR11(r11) | ||
851 | SYNC | ||
852 | RFI | ||
853 | |||
854 | /* check if the exception happened in a restartable section */ | ||
855 | 1: lis r3,exc_exit_restart_end@ha | ||
856 | addi r3,r3,exc_exit_restart_end@l | ||
857 | cmplw r12,r3 | ||
858 | bge 3f | ||
859 | lis r4,exc_exit_restart@ha | ||
860 | addi r4,r4,exc_exit_restart@l | ||
861 | cmplw r12,r4 | ||
862 | blt 3f | ||
863 | lis r3,fee_restarts@ha | ||
864 | tophys(r3,r3) | ||
865 | lwz r5,fee_restarts@l(r3) | ||
866 | addi r5,r5,1 | ||
867 | stw r5,fee_restarts@l(r3) | ||
868 | mr r12,r4 /* restart at exc_exit_restart */ | ||
869 | b 2b | ||
870 | |||
871 | .comm fee_restarts,4 | ||
872 | |||
873 | /* aargh, a nonrecoverable interrupt, panic */ | ||
874 | /* aargh, we don't know which trap this is */ | ||
875 | /* but the 601 doesn't implement the RI bit, so assume it's OK */ | ||
876 | 3: | ||
877 | BEGIN_FTR_SECTION | ||
878 | b 2b | ||
879 | END_FTR_SECTION_IFSET(CPU_FTR_601) | ||
880 | li r10,-1 | ||
881 | stw r10,TRAP(r11) | ||
882 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
883 | li r10,MSR_KERNEL | ||
884 | bl transfer_to_handler_full | ||
885 | .long nonrecoverable_exception | ||
886 | .long ret_from_except | ||
887 | |||
888 | /* | ||
889 | * FP unavailable trap from kernel - print a message, but let | ||
890 | * the task use FP in the kernel until it returns to user mode. | ||
891 | */ | ||
892 | KernelFP: | ||
893 | lwz r3,_MSR(r1) | ||
894 | ori r3,r3,MSR_FP | ||
895 | stw r3,_MSR(r1) /* enable use of FP after return */ | ||
896 | lis r3,86f@h | ||
897 | ori r3,r3,86f@l | ||
898 | mr r4,r2 /* current */ | ||
899 | lwz r5,_NIP(r1) | ||
900 | bl printk | ||
901 | b ret_from_except | ||
902 | 86: .string "floating point used in kernel (task=%p, pc=%x)\n" | ||
903 | .align 4,0 | ||
904 | |||
905 | #ifdef CONFIG_ALTIVEC | 778 | #ifdef CONFIG_ALTIVEC |
906 | /* Note that the AltiVec support is closely modeled after the FP | 779 | /* Note that the AltiVec support is closely modeled after the FP |
907 | * support. Changes to one are likely to be applicable to the | 780 | * support. Changes to one are likely to be applicable to the |
@@ -1016,42 +889,6 @@ giveup_altivec: | |||
1016 | #endif /* CONFIG_ALTIVEC */ | 889 | #endif /* CONFIG_ALTIVEC */ |
1017 | 890 | ||
1018 | /* | 891 | /* |
1019 | * giveup_fpu(tsk) | ||
1020 | * Disable FP for the task given as the argument, | ||
1021 | * and save the floating-point registers in its thread_struct. | ||
1022 | * Enables the FPU for use in the kernel on return. | ||
1023 | */ | ||
1024 | .globl giveup_fpu | ||
1025 | giveup_fpu: | ||
1026 | mfmsr r5 | ||
1027 | ori r5,r5,MSR_FP | ||
1028 | SYNC_601 | ||
1029 | ISYNC_601 | ||
1030 | MTMSRD(r5) /* enable use of fpu now */ | ||
1031 | SYNC_601 | ||
1032 | isync | ||
1033 | cmpwi 0,r3,0 | ||
1034 | beqlr- /* if no previous owner, done */ | ||
1035 | addi r3,r3,THREAD /* want THREAD of task */ | ||
1036 | lwz r5,PT_REGS(r3) | ||
1037 | cmpwi 0,r5,0 | ||
1038 | SAVE_32FPRS(0, r3) | ||
1039 | mffs fr0 | ||
1040 | stfd fr0,THREAD_FPSCR-4(r3) | ||
1041 | beq 1f | ||
1042 | lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1043 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | ||
1044 | andc r4,r4,r3 /* disable FP for previous task */ | ||
1045 | stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1046 | 1: | ||
1047 | #ifndef CONFIG_SMP | ||
1048 | li r5,0 | ||
1049 | lis r4,last_task_used_math@ha | ||
1050 | stw r5,last_task_used_math@l(r4) | ||
1051 | #endif /* CONFIG_SMP */ | ||
1052 | blr | ||
1053 | |||
1054 | /* | ||
1055 | * This code is jumped to from the startup code to copy | 892 | * This code is jumped to from the startup code to copy |
1056 | * the kernel image to physical address 0. | 893 | * the kernel image to physical address 0. |
1057 | */ | 894 | */ |
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 9ed8165a3d6c..9b6a8e513657 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S | |||
@@ -426,7 +426,11 @@ interrupt_base: | |||
426 | PROGRAM_EXCEPTION | 426 | PROGRAM_EXCEPTION |
427 | 427 | ||
428 | /* Floating Point Unavailable Interrupt */ | 428 | /* Floating Point Unavailable Interrupt */ |
429 | #ifdef CONFIG_PPC_FPU | ||
430 | FP_UNAVAILABLE_EXCEPTION | ||
431 | #else | ||
429 | EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) | 432 | EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) |
433 | #endif | ||
430 | 434 | ||
431 | /* System Call Interrupt */ | 435 | /* System Call Interrupt */ |
432 | START_EXCEPTION(SystemCall) | 436 | START_EXCEPTION(SystemCall) |
@@ -686,8 +690,10 @@ _GLOBAL(giveup_altivec) | |||
686 | * | 690 | * |
687 | * The 44x core does not have an FPU. | 691 | * The 44x core does not have an FPU. |
688 | */ | 692 | */ |
693 | #ifndef CONFIG_PPC_FPU | ||
689 | _GLOBAL(giveup_fpu) | 694 | _GLOBAL(giveup_fpu) |
690 | blr | 695 | blr |
696 | #endif | ||
691 | 697 | ||
692 | /* | 698 | /* |
693 | * extern void abort(void) | 699 | * extern void abort(void) |
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h index 884dac916bce..f213d12eec08 100644 --- a/arch/ppc/kernel/head_booke.h +++ b/arch/ppc/kernel/head_booke.h | |||
@@ -337,4 +337,11 @@ label: | |||
337 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 337 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
338 | EXC_XFER_LITE(0x0900, timer_interrupt) | 338 | EXC_XFER_LITE(0x0900, timer_interrupt) |
339 | 339 | ||
340 | #define FP_UNAVAILABLE_EXCEPTION \ | ||
341 | START_EXCEPTION(FloatingPointUnavailable) \ | ||
342 | NORMAL_EXCEPTION_PROLOG; \ | ||
343 | bne load_up_fpu; /* if from user, just load it up */ \ | ||
344 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
345 | EXC_XFER_EE_LITE(0x800, KernelFP) | ||
346 | |||
340 | #endif /* __HEAD_BOOKE_H__ */ | 347 | #endif /* __HEAD_BOOKE_H__ */ |
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index d64bf61d2b1f..f22ddce36135 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S | |||
@@ -504,7 +504,11 @@ interrupt_base: | |||
504 | PROGRAM_EXCEPTION | 504 | PROGRAM_EXCEPTION |
505 | 505 | ||
506 | /* Floating Point Unavailable Interrupt */ | 506 | /* Floating Point Unavailable Interrupt */ |
507 | #ifdef CONFIG_PPC_FPU | ||
508 | FP_UNAVAILABLE_EXCEPTION | ||
509 | #else | ||
507 | EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) | 510 | EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) |
511 | #endif | ||
508 | 512 | ||
509 | /* System Call Interrupt */ | 513 | /* System Call Interrupt */ |
510 | START_EXCEPTION(SystemCall) | 514 | START_EXCEPTION(SystemCall) |
@@ -916,10 +920,12 @@ _GLOBAL(giveup_spe) | |||
916 | /* | 920 | /* |
917 | * extern void giveup_fpu(struct task_struct *prev) | 921 | * extern void giveup_fpu(struct task_struct *prev) |
918 | * | 922 | * |
919 | * The e500 core does not have an FPU. | 923 | * Not all FSL Book-E cores have an FPU |
920 | */ | 924 | */ |
925 | #ifndef CONFIG_PPC_FPU | ||
921 | _GLOBAL(giveup_fpu) | 926 | _GLOBAL(giveup_fpu) |
922 | blr | 927 | blr |
928 | #endif | ||
923 | 929 | ||
924 | /* | 930 | /* |
925 | * extern void abort(void) | 931 | * extern void abort(void) |
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 73f7c23b0dd4..e4f1615ec13f 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
@@ -1096,17 +1096,7 @@ _GLOBAL(_get_SP) | |||
1096 | * and exceptions as if the cpu had performed the load or store. | 1096 | * and exceptions as if the cpu had performed the load or store. |
1097 | */ | 1097 | */ |
1098 | 1098 | ||
1099 | #if defined(CONFIG_4xx) || defined(CONFIG_E500) | 1099 | #ifdef CONFIG_PPC_FPU |
1100 | _GLOBAL(cvt_fd) | ||
1101 | lfs 0,0(r3) | ||
1102 | stfd 0,0(r4) | ||
1103 | blr | ||
1104 | |||
1105 | _GLOBAL(cvt_df) | ||
1106 | lfd 0,0(r3) | ||
1107 | stfs 0,0(r4) | ||
1108 | blr | ||
1109 | #else | ||
1110 | _GLOBAL(cvt_fd) | 1100 | _GLOBAL(cvt_fd) |
1111 | lfd 0,-4(r5) /* load up fpscr value */ | 1101 | lfd 0,-4(r5) /* load up fpscr value */ |
1112 | mtfsf 0xff,0 | 1102 | mtfsf 0xff,0 |
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index 426b6f7d9de3..59d59a8dc249 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
27 | #include <linux/user.h> | 27 | #include <linux/user.h> |
28 | #include <linux/security.h> | 28 | #include <linux/security.h> |
29 | #include <linux/signal.h> | ||
29 | 30 | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/page.h> | 32 | #include <asm/page.h> |
@@ -356,7 +357,7 @@ int sys_ptrace(long request, long pid, long addr, long data) | |||
356 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | 357 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ |
357 | case PTRACE_CONT: { /* restart after signal. */ | 358 | case PTRACE_CONT: { /* restart after signal. */ |
358 | ret = -EIO; | 359 | ret = -EIO; |
359 | if ((unsigned long) data > _NSIG) | 360 | if (!valid_signal(data)) |
360 | break; | 361 | break; |
361 | if (request == PTRACE_SYSCALL) { | 362 | if (request == PTRACE_SYSCALL) { |
362 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 363 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
@@ -389,7 +390,7 @@ int sys_ptrace(long request, long pid, long addr, long data) | |||
389 | 390 | ||
390 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | 391 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ |
391 | ret = -EIO; | 392 | ret = -EIO; |
392 | if ((unsigned long) data > _NSIG) | 393 | if (!valid_signal(data)) |
393 | break; | 394 | break; |
394 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 395 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
395 | set_single_step(child); | 396 | set_single_step(child); |
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 361865c4bc84..f8e7e324a173 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c | |||
@@ -176,7 +176,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
176 | #else | 176 | #else |
177 | #define get_mc_reason(regs) (mfspr(SPRN_MCSR)) | 177 | #define get_mc_reason(regs) (mfspr(SPRN_MCSR)) |
178 | #endif | 178 | #endif |
179 | #define REASON_FP 0 | 179 | #define REASON_FP ESR_FP |
180 | #define REASON_ILLEGAL ESR_PIL | 180 | #define REASON_ILLEGAL ESR_PIL |
181 | #define REASON_PRIVILEGED ESR_PPR | 181 | #define REASON_PRIVILEGED ESR_PPR |
182 | #define REASON_TRAP ESR_PTR | 182 | #define REASON_TRAP ESR_PTR |