From: BitKeeper B. <ri...@su...> - 2005-02-25 15:09:02
|
ChangeSet 1.1252, 2005/02/24 11:11:57+00:00, ka...@sc... More FPU fixes. Extend taskswitch hypercall to allow TS bit to be cleared as well as set. extras/mini-os/h/hypervisor.h | 10 ++- linux-2.4.29-xen-sparse/arch/xen/kernel/process.c | 2 linux-2.4.29-xen-sparse/include/asm-xen/system.h | 2 linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c | 2 linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c | 8 -- linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h | 5 - linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h | 8 +- netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c | 4 - netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h | 8 +- xen/arch/x86/traps.c | 43 ++++++-------- 10 files changed, 48 insertions(+), 44 deletions(-) diff -Nru a/extras/mini-os/h/hypervisor.h b/extras/mini-os/h/hypervisor.h --- a/extras/mini-os/h/hypervisor.h 2005-02-24 07:01:31 -05:00 +++ b/extras/mini-os/h/hypervisor.h 2005-02-24 07:01:31 -05:00 @@ -126,12 +126,18 @@ } #endif -static __inline__ int HYPERVISOR_fpu_taskswitch(void) +static __inline__ int +HYPERVISOR_fpu_taskswitch( + int set) { int ret; + unsigned long ign; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" ); + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set) + : "memory" ); return ret; } diff -Nru a/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c b/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c --- a/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c 2005-02-24 07:01:31 -05:00 +++ b/linux-2.4.29-xen-sparse/arch/xen/kernel/process.c 2005-02-24 07:01:31 -05:00 @@ -334,7 +334,7 @@ asm volatile( "fnsave %0 ; fwait" : "=m" (prev_p->thread.i387.fsave) ); prev_p->flags &= ~PF_USEDFPU; - queue_multicall0(__HYPERVISOR_fpu_taskswitch); + queue_multicall1(__HYPERVISOR_fpu_taskswitch, 1); } queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0); diff -Nru a/linux-2.4.29-xen-sparse/include/asm-xen/system.h b/linux-2.4.29-xen-sparse/include/asm-xen/system.h --- a/linux-2.4.29-xen-sparse/include/asm-xen/system.h 2005-02-24 07:01:31 -05:00 +++ b/linux-2.4.29-xen-sparse/include/asm-xen/system.h 2005-02-24 07:01:31 -05:00 @@ -109,7 +109,7 @@ /* NB. 'clts' is done for us by Xen during virtual trap. */ #define clts() ((void)0) -#define stts() (HYPERVISOR_fpu_taskswitch()) +#define stts() (HYPERVISOR_fpu_taskswitch(1)) #endif /* __KERNEL__ */ diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c 2005-02-24 07:01:31 -05:00 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c 2005-02-24 07:01:31 -05:00 @@ -500,7 +500,7 @@ */ if (prev_p->thread_info->status & TS_USEDFPU) { __save_init_fpu(prev_p); /* _not_ save_init_fpu() */ - queue_multicall0(__HYPERVISOR_fpu_taskswitch); + queue_multicall1(__HYPERVISOR_fpu_taskswitch, 1); } /* diff -Nru a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c 2005-02-24 07:01:31 -05:00 +++ b/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c 2005-02-24 07:01:31 -05:00 @@ -902,14 +902,6 @@ struct thread_info *thread = current_thread_info(); struct task_struct *tsk = thread->task; - /* - * A trap in kernel mode can be ignored. It'll be the fast XOR or - * copying libraries, which will correctly save/restore state and - * reset the TS bit in CR0. - */ - if ((regs.xcs & 2) == 0) - return; - /* NB. 'clts' is done for us by Xen during virtual trap. */ if (!tsk->used_math) init_fpu(tsk); diff -Nru a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h --- a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h 2005-02-24 07:01:31 -05:00 +++ b/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h 2005-02-24 07:01:31 -05:00 @@ -106,17 +106,16 @@ /* * Clear and set 'TS' bit respectively */ -#define clts() __asm__ __volatile__ ("clts") +#define clts() (HYPERVISOR_fpu_taskswitch(0)) #define read_cr0() \ BUG(); #define write_cr0(x) \ BUG(); - #define read_cr4() \ BUG(); #define write_cr4(x) \ BUG(); -#define stts() (HYPERVISOR_fpu_taskswitch()) +#define stts() (HYPERVISOR_fpu_taskswitch(1)) #endif /* __KERNEL__ */ diff -Nru a/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h --- a/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h 2005-02-24 07:01:31 -05:00 +++ b/linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h 2005-02-24 07:01:31 -05:00 @@ -212,12 +212,16 @@ static inline int HYPERVISOR_fpu_taskswitch( - void) + int set) { int ret; + unsigned long ign; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" ); + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set) + : "memory" ); return ret; } diff -Nru a/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c b/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c --- a/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c 2005-02-24 07:01:31 -05:00 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c 2005-02-24 07:01:31 -05:00 @@ -412,7 +412,7 @@ ltr(lwp0.l_md.md_tss_sel); lldt(pcb->pcb_ldt_sel); #else - HYPERVISOR_fpu_taskswitch(); + HYPERVISOR_fpu_taskswitch(1); XENPRINTF(("lwp tss sp %p ss %04x/%04x\n", (void *)pcb->pcb_tss.tss_esp0, pcb->pcb_tss.tss_ss0, IDXSEL(pcb->pcb_tss.tss_ss0))); @@ -455,7 +455,7 @@ ci = curcpu(); if (ci->ci_fpused) { - HYPERVISOR_fpu_taskswitch(); + HYPERVISOR_fpu_taskswitch(1); ci->ci_fpused = 0; } diff -Nru a/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h b/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h --- a/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h 2005-02-24 07:01:31 -05:00 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h 2005-02-24 07:01:31 -05:00 @@ -180,12 +180,16 @@ } static inline int -HYPERVISOR_fpu_taskswitch(void) +HYPERVISOR_fpu_taskswitch(int set) { int ret; + unsigned long ign; + __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" ); + : "=a" (ret), "=b" (ign) + : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set) + : "memory" ); return ret; } diff -Nru a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c 2005-02-24 07:01:31 -05:00 +++ b/xen/arch/x86/traps.c 2005-02-24 07:01:31 -05:00 @@ -348,6 +348,25 @@ return 0; } +long do_fpu_taskswitch(int set) +{ + struct exec_domain *ed = current; + + if ( set ) + { + set_bit(EDF_GUEST_STTS, &ed->ed_flags); + stts(); + } + else + { + clear_bit(EDF_GUEST_STTS, &ed->ed_flags); + if ( test_bit(EDF_USEDFPU, &ed->ed_flags) ) + clts(); + } + + return 0; +} + static int emulate_privileged_op(struct xen_regs *regs) { extern void *decode_reg(struct xen_regs *regs, u8 b); @@ -369,9 +388,7 @@ switch ( opcode ) { case 0x06: /* CLTS */ - clear_bit(EDF_GUEST_STTS, &ed->ed_flags); - if ( test_bit(EDF_USEDFPU, &ed->ed_flags) ) - clts(); + (void)do_fpu_taskswitch(0); break; case 0x09: /* WBINVD */ @@ -420,17 +437,7 @@ switch ( (opcode >> 3) & 7 ) { case 0: /* Write CR0 */ - if ( *reg & X86_CR0_TS ) - { - set_bit(EDF_GUEST_STTS, &ed->ed_flags); - stts(); - } - else - { - clear_bit(EDF_GUEST_STTS, &ed->ed_flags); - if ( test_bit(EDF_USEDFPU, &ed->ed_flags) ) - clts(); - } + (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS)); break; case 2: /* Write CR2 */ @@ -823,14 +830,6 @@ UNLOCK_BIGLOCK(current->domain); - return 0; -} - - -long do_fpu_taskswitch(void) -{ - set_bit(EDF_GUEST_STTS, ¤t->ed_flags); - stts(); return 0; } |