diff options
Diffstat (limited to 'arch/powerpc/kernel/fpu.S')
-rw-r--r-- | arch/powerpc/kernel/fpu.S | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index e0ada05f2df3..caeaabf11a2f 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -35,6 +35,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | |||
35 | 2: REST_32VSRS(n,c,base); \ | 35 | 2: REST_32VSRS(n,c,base); \ |
36 | 3: | 36 | 3: |
37 | 37 | ||
38 | #define __REST_32FPVSRS_TRANSACT(n,c,base) \ | ||
39 | BEGIN_FTR_SECTION \ | ||
40 | b 2f; \ | ||
41 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | ||
42 | REST_32FPRS_TRANSACT(n,base); \ | ||
43 | b 3f; \ | ||
44 | 2: REST_32VSRS_TRANSACT(n,c,base); \ | ||
45 | 3: | ||
46 | |||
38 | #define __SAVE_32FPVSRS(n,c,base) \ | 47 | #define __SAVE_32FPVSRS(n,c,base) \ |
39 | BEGIN_FTR_SECTION \ | 48 | BEGIN_FTR_SECTION \ |
40 | b 2f; \ | 49 | b 2f; \ |
@@ -45,11 +54,68 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | |||
45 | 3: | 54 | 3: |
46 | #else | 55 | #else |
47 | #define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base) | 56 | #define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base) |
57 | #define __REST_32FPVSRS_TRANSACT(n,b,base) REST_32FPRS(n, base) | ||
48 | #define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base) | 58 | #define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base) |
49 | #endif | 59 | #endif |
50 | #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base) | 60 | #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base) |
61 | #define REST_32FPVSRS_TRANSACT(n,c,base) \ | ||
62 | __REST_32FPVSRS_TRANSACT(n,__REG_##c,__REG_##base) | ||
51 | #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base) | 63 | #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base) |
52 | 64 | ||
65 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
66 | /* | ||
67 | * Wrapper to call load_up_fpu from C. | ||
68 | * void do_load_up_fpu(struct pt_regs *regs); | ||
69 | */ | ||
70 | _GLOBAL(do_load_up_fpu) | ||
71 | mflr r0 | ||
72 | std r0, 16(r1) | ||
73 | stdu r1, -112(r1) | ||
74 | |||
75 | subi r6, r3, STACK_FRAME_OVERHEAD | ||
76 | /* load_up_fpu expects r12=MSR, r13=PACA, and returns | ||
77 | * with r12 = new MSR. | ||
78 | */ | ||
79 | ld r12,_MSR(r6) | ||
80 | GET_PACA(r13) | ||
81 | |||
82 | bl load_up_fpu | ||
83 | std r12,_MSR(r6) | ||
84 | |||
85 | ld r0, 112+16(r1) | ||
86 | addi r1, r1, 112 | ||
87 | mtlr r0 | ||
88 | blr | ||
89 | |||
90 | |||
91 | /* void do_load_up_transact_fpu(struct thread_struct *thread) | ||
92 | * | ||
93 | * This is similar to load_up_fpu but for the transactional version of the FP | ||
94 | * register set. It doesn't mess with the task MSR or valid flags. | ||
95 | * Furthermore, we don't do lazy FP with TM currently. | ||
96 | */ | ||
97 | _GLOBAL(do_load_up_transact_fpu) | ||
98 | mfmsr r6 | ||
99 | ori r5,r6,MSR_FP | ||
100 | #ifdef CONFIG_VSX | ||
101 | BEGIN_FTR_SECTION | ||
102 | oris r5,r5,MSR_VSX@h | ||
103 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | ||
104 | #endif | ||
105 | SYNC | ||
106 | MTMSRD(r5) | ||
107 | |||
108 | lfd fr0,THREAD_TRANSACT_FPSCR(r3) | ||
109 | MTFSF_L(fr0) | ||
110 | REST_32FPVSRS_TRANSACT(0, R4, R3) | ||
111 | |||
112 | /* FP/VSX off again */ | ||
113 | MTMSRD(r6) | ||
114 | SYNC | ||
115 | |||
116 | blr | ||
117 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
118 | |||
53 | /* | 119 | /* |
54 | * This task wants to use the FPU now. | 120 | * This task wants to use the FPU now. |
55 | * On UP, disable FP for the task which had the FPU previously, | 121 | * On UP, disable FP for the task which had the FPU previously, |