]> xenbits.xensource.com Git - xen.git/commitdiff
bitkeeper revision 1.1236.1.16 (421db67dL0mXatHebAtt9KpMqkCIBQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 24 Feb 2005 11:11:57 +0000 (11:11 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 24 Feb 2005 11:11:57 +0000 (11:11 +0000)
More FPU fixes. Extend taskswitch hypercall to allow TS bit to be
cleared as well as set.

extras/mini-os/h/hypervisor.h
linux-2.4.29-xen-sparse/arch/xen/kernel/process.c
linux-2.4.29-xen-sparse/include/asm-xen/system.h
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c
linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h
linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h
netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c
netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h
xen/arch/x86/traps.c

index fee36d5b9c1b74093448bbefcb339ede329af4c7..e3642537571652b5f96d4ea5fb5276031434b8ca 100644 (file)
@@ -126,12 +126,18 @@ static __inline__ int HYPERVISOR_set_callbacks(
 }
 #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;
 }
index ad7e82dc7904a796260149b13a7cc8bf25ef38d1..905b51c1133f424873846eff8306172d2382ff47 100644 (file)
@@ -334,7 +334,7 @@ void fastcall __switch_to(struct task_struct *prev_p, struct task_struct *next_p
             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);
index 9be6e291feb9677922d529417880ba9b2bf4cffb..fd9faf34cb74439de1683a4b77450a791f464155 100644 (file)
@@ -109,7 +109,7 @@ static inline unsigned long _get_base(char * addr)
 
 /* 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__ */
 
index 207140ee6006f344da90a59b988d4b82bdff9cfe..017b167c388f91f97ae44e1d439fc4fd4edd8a59 100644 (file)
@@ -500,7 +500,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
         */
        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);
        }
 
        /*
index 54f014e6052783ba1a4bcce90edb1fde7ef2d2b3..49ce793c7b0094cf112e31d3039be95296b2d619 100644 (file)
@@ -902,14 +902,6 @@ asmlinkage void math_state_restore(struct pt_regs regs)
        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);
index 6e882483a6cc925e58a1e91eb6313ce8a3ec2127..77b6a507bdf41cd4c76889829f4216a3daaf3575 100644 (file)
@@ -106,17 +106,16 @@ static inline unsigned long _get_base(char * addr)
 /*
  * 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__ */
 
index 09a1bb7d83384e25d21419bb0f1adcd24d913a57..b82db08f70df16b0815ff4221bc06e8cc20b892e 100644 (file)
@@ -212,12 +212,16 @@ HYPERVISOR_set_callbacks(
 
 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;
 }
index 5ec2d45271c58a567742578a153f085de9fac6f7..ded45387823ee2bf2457b0bb095546c98c4c28f7 100644 (file)
@@ -412,7 +412,7 @@ i386_proc0_tss_ldt_init()
        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 @@ i386_switch_context(struct pcb *new)
 
        ci = curcpu();
        if (ci->ci_fpused) {
-               HYPERVISOR_fpu_taskswitch();
+               HYPERVISOR_fpu_taskswitch(1);
                ci->ci_fpused = 0;
        }
 
index eb91c2a980419c128d386213355f9fe491714891..2ac01b4d25c67b28f206c2f6eabc28f823058374 100644 (file)
@@ -180,12 +180,16 @@ HYPERVISOR_set_callbacks(
 }
 
 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;
 }
index fc4d464e084234860f10d902f24cbf483f73a134..422c737c43baa86e4c259febd9045600048273b9 100644 (file)
@@ -348,6 +348,25 @@ asmlinkage int do_page_fault(struct xen_regs *regs)
     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 @@ static int emulate_privileged_op(struct xen_regs *regs)
     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 @@ static int emulate_privileged_op(struct xen_regs *regs)
         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 */
@@ -827,14 +834,6 @@ long do_set_trap_table(trap_info_t *traps)
 }
 
 
-long do_fpu_taskswitch(void)
-{
-    set_bit(EDF_GUEST_STTS, &current->ed_flags);
-    stts();
-    return 0;
-}
-
-
 #if defined(__i386__)
 #define DB_VALID_ADDR(_a) \
     ((_a) <= (PAGE_OFFSET - 4))