aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r--arch/powerpc/kernel/process.c113
1 files changed, 61 insertions, 52 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7de41c3948ec..219f3634115e 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -53,6 +53,7 @@ extern unsigned long _get_SP(void);
53#ifndef CONFIG_SMP 53#ifndef CONFIG_SMP
54struct task_struct *last_task_used_math = NULL; 54struct task_struct *last_task_used_math = NULL;
55struct task_struct *last_task_used_altivec = NULL; 55struct task_struct *last_task_used_altivec = NULL;
56struct task_struct *last_task_used_vsx = NULL;
56struct task_struct *last_task_used_spe = NULL; 57struct task_struct *last_task_used_spe = NULL;
57#endif 58#endif
58 59
@@ -104,17 +105,6 @@ void enable_kernel_fp(void)
104} 105}
105EXPORT_SYMBOL(enable_kernel_fp); 106EXPORT_SYMBOL(enable_kernel_fp);
106 107
107int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
108{
109 if (!tsk->thread.regs)
110 return 0;
111 flush_fp_to_thread(current);
112
113 memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
114
115 return 1;
116}
117
118#ifdef CONFIG_ALTIVEC 108#ifdef CONFIG_ALTIVEC
119void enable_kernel_altivec(void) 109void enable_kernel_altivec(void)
120{ 110{
@@ -148,36 +138,48 @@ void flush_altivec_to_thread(struct task_struct *tsk)
148 preempt_enable(); 138 preempt_enable();
149 } 139 }
150} 140}
141#endif /* CONFIG_ALTIVEC */
151 142
152int dump_task_altivec(struct task_struct *tsk, elf_vrregset_t *vrregs) 143#ifdef CONFIG_VSX
144#if 0
145/* not currently used, but some crazy RAID module might want to later */
146void enable_kernel_vsx(void)
153{ 147{
154 /* ELF_NVRREG includes the VSCR and VRSAVE which we need to save 148 WARN_ON(preemptible());
155 * separately, see below */
156 const int nregs = ELF_NVRREG - 2;
157 elf_vrreg_t *reg;
158 u32 *dest;
159
160 if (tsk == current)
161 flush_altivec_to_thread(tsk);
162
163 reg = (elf_vrreg_t *)vrregs;
164
165 /* copy the 32 vr registers */
166 memcpy(reg, &tsk->thread.vr[0], nregs * sizeof(*reg));
167 reg += nregs;
168 149
169 /* copy the vscr */ 150#ifdef CONFIG_SMP
170 memcpy(reg, &tsk->thread.vscr, sizeof(*reg)); 151 if (current->thread.regs && (current->thread.regs->msr & MSR_VSX))
171 reg++; 152 giveup_vsx(current);
153 else
154 giveup_vsx(NULL); /* just enable vsx for kernel - force */
155#else
156 giveup_vsx(last_task_used_vsx);
157#endif /* CONFIG_SMP */
158}
159EXPORT_SYMBOL(enable_kernel_vsx);
160#endif
172 161
173 /* vrsave is stored in the high 32bit slot of the final 128bits */ 162void giveup_vsx(struct task_struct *tsk)
174 memset(reg, 0, sizeof(*reg)); 163{
175 dest = (u32 *)reg; 164 giveup_fpu(tsk);
176 *dest = tsk->thread.vrsave; 165 giveup_altivec(tsk);
166 __giveup_vsx(tsk);
167}
177 168
178 return 1; 169void flush_vsx_to_thread(struct task_struct *tsk)
170{
171 if (tsk->thread.regs) {
172 preempt_disable();
173 if (tsk->thread.regs->msr & MSR_VSX) {
174#ifdef CONFIG_SMP
175 BUG_ON(tsk != current);
176#endif
177 giveup_vsx(tsk);
178 }
179 preempt_enable();
180 }
179} 181}
180#endif /* CONFIG_ALTIVEC */ 182#endif /* CONFIG_VSX */
181 183
182#ifdef CONFIG_SPE 184#ifdef CONFIG_SPE
183 185
@@ -209,14 +211,6 @@ void flush_spe_to_thread(struct task_struct *tsk)
209 preempt_enable(); 211 preempt_enable();
210 } 212 }
211} 213}
212
213int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
214{
215 flush_spe_to_thread(current);
216 /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
217 memcpy(evrregs, &current->thread.evr[0], sizeof(u32) * 35);
218 return 1;
219}
220#endif /* CONFIG_SPE */ 214#endif /* CONFIG_SPE */
221 215
222#ifndef CONFIG_SMP 216#ifndef CONFIG_SMP
@@ -233,6 +227,10 @@ void discard_lazy_cpu_state(void)
233 if (last_task_used_altivec == current) 227 if (last_task_used_altivec == current)
234 last_task_used_altivec = NULL; 228 last_task_used_altivec = NULL;
235#endif /* CONFIG_ALTIVEC */ 229#endif /* CONFIG_ALTIVEC */
230#ifdef CONFIG_VSX
231 if (last_task_used_vsx == current)
232 last_task_used_vsx = NULL;
233#endif /* CONFIG_VSX */
236#ifdef CONFIG_SPE 234#ifdef CONFIG_SPE
237 if (last_task_used_spe == current) 235 if (last_task_used_spe == current)
238 last_task_used_spe = NULL; 236 last_task_used_spe = NULL;
@@ -297,6 +295,11 @@ struct task_struct *__switch_to(struct task_struct *prev,
297 if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) 295 if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))
298 giveup_altivec(prev); 296 giveup_altivec(prev);
299#endif /* CONFIG_ALTIVEC */ 297#endif /* CONFIG_ALTIVEC */
298#ifdef CONFIG_VSX
299 if (prev->thread.regs && (prev->thread.regs->msr & MSR_VSX))
300 /* VMX and FPU registers are already save here */
301 __giveup_vsx(prev);
302#endif /* CONFIG_VSX */
300#ifdef CONFIG_SPE 303#ifdef CONFIG_SPE
301 /* 304 /*
302 * If the previous thread used spe in the last quantum 305 * If the previous thread used spe in the last quantum
@@ -317,6 +320,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
317 if (new->thread.regs && last_task_used_altivec == new) 320 if (new->thread.regs && last_task_used_altivec == new)
318 new->thread.regs->msr |= MSR_VEC; 321 new->thread.regs->msr |= MSR_VEC;
319#endif /* CONFIG_ALTIVEC */ 322#endif /* CONFIG_ALTIVEC */
323#ifdef CONFIG_VSX
324 if (new->thread.regs && last_task_used_vsx == new)
325 new->thread.regs->msr |= MSR_VSX;
326#endif /* CONFIG_VSX */
320#ifdef CONFIG_SPE 327#ifdef CONFIG_SPE
321 /* Avoid the trap. On smp this this never happens since 328 /* Avoid the trap. On smp this this never happens since
322 * we don't set last_task_used_spe 329 * we don't set last_task_used_spe
@@ -417,6 +424,8 @@ static struct regbit {
417 {MSR_EE, "EE"}, 424 {MSR_EE, "EE"},
418 {MSR_PR, "PR"}, 425 {MSR_PR, "PR"},
419 {MSR_FP, "FP"}, 426 {MSR_FP, "FP"},
427 {MSR_VEC, "VEC"},
428 {MSR_VSX, "VSX"},
420 {MSR_ME, "ME"}, 429 {MSR_ME, "ME"},
421 {MSR_IR, "IR"}, 430 {MSR_IR, "IR"},
422 {MSR_DR, "DR"}, 431 {MSR_DR, "DR"},
@@ -484,10 +493,8 @@ void show_regs(struct pt_regs * regs)
484 * Lookup NIP late so we have the best change of getting the 493 * Lookup NIP late so we have the best change of getting the
485 * above info out without failing 494 * above info out without failing
486 */ 495 */
487 printk("NIP ["REG"] ", regs->nip); 496 printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip);
488 print_symbol("%s\n", regs->nip); 497 printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link);
489 printk("LR ["REG"] ", regs->link);
490 print_symbol("%s\n", regs->link);
491#endif 498#endif
492 show_stack(current, (unsigned long *) regs->gpr[1]); 499 show_stack(current, (unsigned long *) regs->gpr[1]);
493 if (!user_mode(regs)) 500 if (!user_mode(regs))
@@ -534,6 +541,7 @@ void prepare_to_copy(struct task_struct *tsk)
534{ 541{
535 flush_fp_to_thread(current); 542 flush_fp_to_thread(current);
536 flush_altivec_to_thread(current); 543 flush_altivec_to_thread(current);
544 flush_vsx_to_thread(current);
537 flush_spe_to_thread(current); 545 flush_spe_to_thread(current);
538} 546}
539 547
@@ -689,6 +697,9 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
689#endif 697#endif
690 698
691 discard_lazy_cpu_state(); 699 discard_lazy_cpu_state();
700#ifdef CONFIG_VSX
701 current->thread.used_vsr = 0;
702#endif
692 memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); 703 memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
693 current->thread.fpscr.val = 0; 704 current->thread.fpscr.val = 0;
694#ifdef CONFIG_ALTIVEC 705#ifdef CONFIG_ALTIVEC
@@ -971,8 +982,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
971 newsp = stack[0]; 982 newsp = stack[0];
972 ip = stack[STACK_FRAME_LR_SAVE]; 983 ip = stack[STACK_FRAME_LR_SAVE];
973 if (!firstframe || ip != lr) { 984 if (!firstframe || ip != lr) {
974 printk("["REG"] ["REG"] ", sp, ip); 985 printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
975 print_symbol("%s", ip);
976 if (firstframe) 986 if (firstframe)
977 printk(" (unreliable)"); 987 printk(" (unreliable)");
978 printk("\n"); 988 printk("\n");
@@ -987,10 +997,9 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
987 && stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) { 997 && stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
988 struct pt_regs *regs = (struct pt_regs *) 998 struct pt_regs *regs = (struct pt_regs *)
989 (sp + STACK_FRAME_OVERHEAD); 999 (sp + STACK_FRAME_OVERHEAD);
990 printk("--- Exception: %lx", regs->trap);
991 print_symbol(" at %s\n", regs->nip);
992 lr = regs->link; 1000 lr = regs->link;
993 print_symbol(" LR = %s\n", lr); 1001 printk("--- Exception: %lx at %pS\n LR = %pS\n",
1002 regs->trap, (void *)regs->nip, (void *)lr);
994 firstframe = 1; 1003 firstframe = 1;
995 } 1004 }
996 1005