xen: use hypercall rather than clts
authorJeremy Fitzhardinge <jeremy@goop.org>
Mon, 26 May 2008 22:31:01 +0000 (23:31 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 27 May 2008 08:11:35 +0000 (10:11 +0200)
Xen will trap and emulate clts, but its better to use a hypercall.
Also, xenner doesn't handle clts.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/xen/enlighten.c
include/asm-x86/xen/hypercall.h

index a05b7721bc81d8f66f342ef348a216704fd12e7b..446f4cd649e6d771e5d35c24fae30cb12321cd03 100644 (file)
@@ -607,6 +607,30 @@ static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm,
        xen_mc_issue(PARAVIRT_LAZY_MMU);
 }
 
+static void xen_clts(void)
+{
+       struct multicall_space mcs;
+
+       mcs = xen_mc_entry(0);
+
+       MULTI_fpu_taskswitch(mcs.mc, 0);
+
+       xen_mc_issue(PARAVIRT_LAZY_CPU);
+}
+
+static void xen_write_cr0(unsigned long cr0)
+{
+       struct multicall_space mcs;
+
+       /* Only pay attention to cr0.TS; everything else is
+          ignored. */
+       mcs = xen_mc_entry(0);
+
+       MULTI_fpu_taskswitch(mcs.mc, (cr0 & X86_CR0_TS) != 0);
+
+       xen_mc_issue(PARAVIRT_LAZY_CPU);
+}
+
 static void xen_write_cr2(unsigned long cr2)
 {
        x86_read_percpu(xen_vcpu)->arch.cr2 = cr2;
@@ -978,10 +1002,10 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
        .set_debugreg = xen_set_debugreg,
        .get_debugreg = xen_get_debugreg,
 
-       .clts = native_clts,
+       .clts = xen_clts,
 
        .read_cr0 = native_read_cr0,
-       .write_cr0 = native_write_cr0,
+       .write_cr0 = xen_write_cr0,
 
        .read_cr4 = native_read_cr4,
        .read_cr4_safe = native_read_cr4_safe,
index c2ccd997ed3537f00ff3ea78195a845d3dd27d0c..897ff79cca3b481dedea80436dcf2632c1cc3fbc 100644 (file)
@@ -314,6 +314,13 @@ HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
        return _hypercall2(int, nmi_op, op, arg);
 }
 
+static inline void
+MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
+{
+       mcl->op = __HYPERVISOR_fpu_taskswitch;
+       mcl->args[0] = set;
+}
+
 static inline void
 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
                        pte_t new_val, unsigned long flags)