diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-11-23 02:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-11-23 02:00:47 +0000 |
commit | 06615f62b17d7de6e12d2f5ec6b88cf30af08413 (patch) | |
tree | 8766f208847d4876a6db619aebbf54d53b76eb44 /arch/ia64/kernel/traps.c | |
parent | fa9bdb574f4febb751848a685d9a9017e04e1d53 (diff) |
Merge with Linux 2.4.0-test10.
Diffstat (limited to 'arch/ia64/kernel/traps.c')
-rw-r--r-- | arch/ia64/kernel/traps.c | 82 |
1 files changed, 45 insertions, 37 deletions
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index bf1abd839..43340bf85 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -192,38 +192,45 @@ ia64_ni_syscall (unsigned long arg0, unsigned long arg1, unsigned long arg2, uns } /* - * disabled_fp_fault() is called when a user-level process attempts to - * access one of the registers f32..f127 while it doesn't own the + * disabled_fph_fault() is called when a user-level process attempts + * to access one of the registers f32..f127 when it doesn't own the * fp-high register partition. When this happens, we save the current * fph partition in the task_struct of the fpu-owner (if necessary) * and then load the fp-high partition of the current task (if - * necessary). + * necessary). Note that the kernel has access to fph by the time we + * get here, as the IVT's "Diabled FP-Register" handler takes care of + * clearing psr.dfh. */ static inline void disabled_fph_fault (struct pt_regs *regs) { - struct task_struct *fpu_owner = ia64_get_fpu_owner(); + struct ia64_psr *psr = ia64_psr(regs); - /* first, clear psr.dfh and psr.mfh: */ - regs->cr_ipsr &= ~(IA64_PSR_DFH | IA64_PSR_MFH); - if (fpu_owner != current) { - ia64_set_fpu_owner(current); + /* first, grant user-level access to fph partition: */ + psr->dfh = 0; +#ifndef CONFIG_SMP + { + struct task_struct *fpu_owner = ia64_get_fpu_owner(); - if (fpu_owner && ia64_psr(ia64_task_regs(fpu_owner))->mfh) { - ia64_psr(ia64_task_regs(fpu_owner))->mfh = 0; - fpu_owner->thread.flags |= IA64_THREAD_FPH_VALID; - __ia64_save_fpu(fpu_owner->thread.fph); - } - if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) { - __ia64_load_fpu(current->thread.fph); - } else { - __ia64_init_fpu(); - /* - * Set mfh because the state in thread.fph does not match - * the state in the fph partition. - */ - ia64_psr(regs)->mfh = 1; - } + if (fpu_owner == current) + return; + + if (fpu_owner) + ia64_flush_fph(fpu_owner); + + ia64_set_fpu_owner(current); + } +#endif /* !CONFIG_SMP */ + if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) { + __ia64_load_fpu(current->thread.fph); + psr->mfh = 0; + } else { + __ia64_init_fpu(); + /* + * Set mfh because the state in thread.fph does not match the state in + * the fph partition. + */ + psr->mfh = 1; } } @@ -247,20 +254,21 @@ fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long * kernel, so set those bits in the mask and set the low volatile * pointer to point to these registers. */ - fp_state.bitmask_low64 = 0xffc0; /* bit6..bit15 */ #ifndef FPSWA_BUG - fp_state.fp_state_low_volatile = ®s->f6; + fp_state.bitmask_low64 = 0x3c0; /* bit 6..9 */ + fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) ®s->f6; #else + fp_state.bitmask_low64 = 0xffc0; /* bit6..bit15 */ f6_15[0] = regs->f6; f6_15[1] = regs->f7; f6_15[2] = regs->f8; f6_15[3] = regs->f9; - __asm__ ("stf.spill %0=f10" : "=m"(f6_15[4])); - __asm__ ("stf.spill %0=f11" : "=m"(f6_15[5])); - __asm__ ("stf.spill %0=f12" : "=m"(f6_15[6])); - __asm__ ("stf.spill %0=f13" : "=m"(f6_15[7])); - __asm__ ("stf.spill %0=f14" : "=m"(f6_15[8])); - __asm__ ("stf.spill %0=f15" : "=m"(f6_15[9])); + __asm__ ("stf.spill %0=f10%P0" : "=m"(f6_15[4])); + __asm__ ("stf.spill %0=f11%P0" : "=m"(f6_15[5])); + __asm__ ("stf.spill %0=f12%P0" : "=m"(f6_15[6])); + __asm__ ("stf.spill %0=f13%P0" : "=m"(f6_15[7])); + __asm__ ("stf.spill %0=f14%P0" : "=m"(f6_15[8])); + __asm__ ("stf.spill %0=f15%P0" : "=m"(f6_15[9])); fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) f6_15; #endif /* @@ -279,12 +287,12 @@ fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long (unsigned long *) isr, (unsigned long *) pr, (unsigned long *) ifs, &fp_state); #ifdef FPSWA_BUG - __asm__ ("ldf.fill f10=%0" :: "m"(f6_15[4])); - __asm__ ("ldf.fill f11=%0" :: "m"(f6_15[5])); - __asm__ ("ldf.fill f12=%0" :: "m"(f6_15[6])); - __asm__ ("ldf.fill f13=%0" :: "m"(f6_15[7])); - __asm__ ("ldf.fill f14=%0" :: "m"(f6_15[8])); - __asm__ ("ldf.fill f15=%0" :: "m"(f6_15[9])); + __asm__ ("ldf.fill f10=%0%P0" :: "m"(f6_15[4])); + __asm__ ("ldf.fill f11=%0%P0" :: "m"(f6_15[5])); + __asm__ ("ldf.fill f12=%0%P0" :: "m"(f6_15[6])); + __asm__ ("ldf.fill f13=%0%P0" :: "m"(f6_15[7])); + __asm__ ("ldf.fill f14=%0%P0" :: "m"(f6_15[8])); + __asm__ ("ldf.fill f15=%0%P0" :: "m"(f6_15[9])); regs->f6 = f6_15[0]; regs->f7 = f6_15[1]; regs->f8 = f6_15[2]; |