[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86: allow pv guests to disable TSC for applications



Linux, under CONFIG_SECCOMP, has been capable of hiding the TSC from
processes for quite a while. This patch enables this to actually work
for pv kernels, by allowing them to control CR4.TSD (and, as a simple
thing to do at the same time, CR4.DE).

Applies cleanly only on top of the previously submitted debug register
handling patch.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-10-10/xen/arch/x86/acpi/power.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/acpi/power.c   2007-10-29 11:19:58.000000000 
+0100
+++ 2007-10-10/xen/arch/x86/acpi/power.c        2007-10-26 15:08:38.000000000 
+0200
@@ -155,6 +155,8 @@ static int enter_state(u32 state)
 
     pmprintk(XENLOG_DEBUG, "Back to C.");
 
+    write_cr4(idle_vcpu[smp_processor_id()]->arch.cr4);
+
     device_power_up();
 
     pmprintk(XENLOG_INFO, "Finishing wakeup from ACPI S%d state.", state);
Index: 2007-10-10/xen/arch/x86/domain.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/domain.c       2007-10-26 16:47:52.000000000 
+0200
+++ 2007-10-10/xen/arch/x86/domain.c    2007-10-29 11:20:35.000000000 +0100
@@ -413,6 +413,8 @@ int vcpu_initialise(struct vcpu *v)
             v->arch.schedule_tail = continue_idle_domain;
             v->arch.cr3           = __pa(idle_pg_table);
         }
+        else
+            v->arch.cr4 = mmu_cr4_features;
     }
 
     v->arch.perdomain_ptes =
@@ -1195,6 +1197,12 @@ static void paravirt_ctxt_switch_to(stru
     set_int80_direct_trap(v);
     switch_kernel_stack(v);
 
+    if ( unlikely(idle_vcpu[v->processor]->arch.cr4 != v->arch.cr4) )
+    {
+        idle_vcpu[v->processor]->arch.cr4 = v->arch.cr4;
+        write_cr4(v->arch.cr4);
+    }
+
     /* Maybe switch the debug registers. */
     cond_loaddebug(v, 0);
     cond_loaddebug(v, 1);
Index: 2007-10-10/xen/arch/x86/flushtlb.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/flushtlb.c     2007-10-29 11:19:58.000000000 
+0100
+++ 2007-10-10/xen/arch/x86/flushtlb.c  2007-10-29 12:03:23.000000000 +0100
@@ -23,6 +23,19 @@
 u32 tlbflush_clock = 1U;
 DEFINE_PER_CPU(u32, tlbflush_time);
 
+static inline void __pge_off(void)
+{
+    write_cr4(mmu_cr4_features & ~X86_CR4_PGE);
+}
+
+static inline void __pge_on(void)
+{
+    struct vcpu *idle = idle_vcpu[smp_processor_id()];
+
+    write_cr4(likely(idle != NULL) && likely(idle != INVALID_VCPU) &&
+              likely(idle->arch.cr4) ? idle->arch.cr4 : mmu_cr4_features);
+}
+
 /*
  * pre_flush(): Increment the virtual TLB-flush clock. Returns new clock value.
  * 
Index: 2007-10-10/xen/arch/x86/hvm/vmx/vmcs.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/hvm/vmx/vmcs.c 2007-10-29 11:19:58.000000000 
+0100
+++ 2007-10-10/xen/arch/x86/hvm/vmx/vmcs.c      2007-10-26 14:35:40.000000000 
+0200
@@ -498,7 +498,7 @@ static int construct_vmcs(struct vcpu *v
 
     /* Host control registers. */
     __vmwrite(HOST_CR0, read_cr0() | X86_CR0_TS);
-    __vmwrite(HOST_CR4, read_cr4());
+    __vmwrite(HOST_CR4, mmu_cr4_features);
 
     /* Host CS:RIP. */
     __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
Index: 2007-10-10/xen/arch/x86/hvm/vmx/vmx.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/hvm/vmx/vmx.c  2007-10-29 09:01:31.000000000 
+0100
+++ 2007-10-10/xen/arch/x86/hvm/vmx/vmx.c       2007-10-29 09:10:52.000000000 
+0100
@@ -728,6 +728,7 @@ static void vmx_ctxt_switch_from(struct 
 
 static void vmx_ctxt_switch_to(struct vcpu *v)
 {
+    idle_vcpu[v->processor]->arch.cr4 = mmu_cr4_features;
     vmx_restore_guest_msrs(v);
     vmx_restore_dr(v);
 }
Index: 2007-10-10/xen/arch/x86/setup.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/setup.c        2007-10-29 11:19:58.000000000 
+0100
+++ 2007-10-10/xen/arch/x86/setup.c     2007-10-29 12:00:01.000000000 +0100
@@ -412,7 +412,7 @@ void __init __start_xen(unsigned long mb
 
     parse_video_info();
 
-    set_current((struct vcpu *)0xfffff000); /* debug sanity */
+    set_current(INVALID_VCPU); /* debug sanity */
     idle_vcpu[0] = current;
     set_processor_id(0); /* needed early, for smp_processor_id() */
 
Index: 2007-10-10/xen/arch/x86/traps.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/traps.c        2007-10-26 15:53:13.000000000 
+0200
+++ 2007-10-10/xen/arch/x86/traps.c     2007-10-26 16:55:03.000000000 +0200
@@ -1717,10 +1717,24 @@ static int emulate_privileged_op(struct 
             break;
 
         case 4: /* Write CR4 */
-            if ( *reg != (read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE)) )
-                gdprintk(XENLOG_WARNING,
-                         "Attempt to change CR4 flags %08lx -> %08lx\n",
-                         read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE), *reg);
+            res = read_cr4();
+            if ( *reg != (res & ~(X86_CR4_PGE|X86_CR4_PSE)) )
+            {
+                unsigned long hv_cr4_mask = ~X86_CR4_TSD;
+
+                if ( cpu_has_de && IS_PRIV(v->domain) )
+                    hv_cr4_mask &= ~X86_CR4_DE;
+                if ( (*reg & hv_cr4_mask) !=
+                     (res & hv_cr4_mask & ~(X86_CR4_PGE|X86_CR4_PSE)) )
+                    gdprintk(XENLOG_WARNING,
+                             "Attempt to change CR4 flags %08lx -> %08lx\n",
+                             res & ~(X86_CR4_PGE|X86_CR4_PSE), *reg);
+                res &= hv_cr4_mask;
+                res |= *reg & ~hv_cr4_mask;
+                v->arch.cr4 = res;
+                idle_vcpu[v->processor]->arch.cr4 = v->arch.cr4;
+                write_cr4(res);
+            }
             break;
 
         default:
@@ -1785,6 +1799,10 @@ static int emulate_privileged_op(struct 
         }
         break;
 
+    case 0x31: /* RDTSC */
+        rdtsc(regs->eax, regs->edx);
+        break;
+
     case 0x32: /* RDMSR */
         switch ( regs->ecx )
         {
Index: 2007-10-10/xen/include/asm-x86/domain.h
===================================================================
--- 2007-10-10.orig/xen/include/asm-x86/domain.h        2007-10-29 
11:19:58.000000000 +0100
+++ 2007-10-10/xen/include/asm-x86/domain.h     2007-10-26 17:14:51.000000000 
+0200
@@ -18,6 +18,8 @@
 #define is_pv_32on64_vcpu(v)   (is_pv_32on64_domain((v)->domain))
 #define IS_COMPAT(d)           (is_pv_32on64_domain(d))
 
+#define INVALID_VCPU ((struct vcpu *)0xfffff000)
+
 struct trap_bounce {
     uint32_t      error_code;
     uint8_t       flags; /* TBF_ */
@@ -321,6 +323,7 @@ struct arch_vcpu
     pagetable_t shadow_table[4];        /* (MFN) shadow(s) of guest */
     pagetable_t monitor_table;          /* (MFN) hypervisor PT (for HVM) */
     unsigned long cr3;                  /* (MA) value to install in HW CR3 */
+    unsigned long cr4;                  /* guest-customized CR4 value */
 
     /* Current LDT details. */
     unsigned long shadow_ldt_mapcnt;
Index: 2007-10-10/xen/include/asm-x86/page.h
===================================================================
--- 2007-10-10.orig/xen/include/asm-x86/page.h  2007-10-29 11:19:58.000000000 
+0100
+++ 2007-10-10/xen/include/asm-x86/page.h       2007-10-26 14:21:48.000000000 
+0200
@@ -294,9 +294,6 @@ void paging_init(void);
 void setup_idle_pagetable(void);
 #endif /* !defined(__ASSEMBLY__) */
 
-#define __pge_off() write_cr4(mmu_cr4_features & ~X86_CR4_PGE)
-#define __pge_on()  write_cr4(mmu_cr4_features)
-
 #define _PAGE_PRESENT  0x001U
 #define _PAGE_RW       0x002U
 #define _PAGE_USER     0x004U



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.