From d276c3c782fe9d16f460f77c407d125ae75c9dde Mon Sep 17 00:00:00 2001 From: Venkatesh Srinivas Date: Fri, 18 May 2012 21:28:44 -0700 Subject: [PATCH] kernel -- vmm_guest & CLFLUSH * Introduce 'vmm_guest', to indicate the kernel in running in a virtualized environment of some sort, either a vkernel, or in KVM/QEMU. Use the CPUID flag 'VMM' to detect a VM. * Implement wrappers for CLFLUSH instruction * Store CLFLUSH cache line size in cpu_clflush_line_size * Disable CLFLUSH on VMMs by masking it out in cpu feature flags. Originally-from: David Shao, FreeBSD --- sys/cpu/i386/include/cpufunc.h | 6 ++++++ sys/cpu/x86_64/include/cpufunc.h | 6 ++++++ sys/kern/subr_param.c | 1 + sys/platform/pc32/i386/initcpu.c | 15 ++++++++++++++- sys/platform/pc32/i386/machdep.c | 4 ++-- sys/platform/pc32/include/md_var.h | 1 + sys/platform/pc64/include/md_var.h | 1 + sys/platform/pc64/x86_64/initcpu.c | 13 +++++++++++++ sys/platform/pc64/x86_64/machdep.c | 4 ++-- sys/platform/vkernel/platform/init.c | 2 ++ sys/platform/vkernel64/platform/init.c | 2 ++ sys/sys/kernel.h | 1 + 12 files changed, 51 insertions(+), 5 deletions(-) diff --git a/sys/cpu/i386/include/cpufunc.h b/sys/cpu/i386/include/cpufunc.h index d51d474..f1a61eb 100644 --- a/sys/cpu/i386/include/cpufunc.h +++ b/sys/cpu/i386/include/cpufunc.h @@ -142,6 +142,12 @@ btrl(u_int *mask, int bit) } static __inline void +clflush(u_long addr) +{ + __asm __volatile("clflush %0" : : "m" (*(char *) addr)); +} + +static __inline void do_cpuid(u_int ax, u_int *p) { __asm __volatile("cpuid" diff --git a/sys/cpu/x86_64/include/cpufunc.h b/sys/cpu/x86_64/include/cpufunc.h index 2e2af76..1163f3f 100644 --- a/sys/cpu/x86_64/include/cpufunc.h +++ b/sys/cpu/x86_64/include/cpufunc.h @@ -125,6 +125,12 @@ bsrq(u_long mask) } static __inline void +clflush(u_long addr) +{ + __asm __volatile("clflush %0" : : "m" (*(char *) addr)); +} + +static __inline void do_cpuid(u_int ax, u_int *p) { __asm __volatile("cpuid" diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c index f7a062f..71f7b64 100644 --- a/sys/kern/subr_param.c +++ b/sys/kern/subr_param.c @@ -88,6 +88,7 @@ int nbuf; int nswbuf; long maxswzone; /* max swmeta KVA storage */ long maxbcache; /* max buffer cache KVA storage */ +int vmm_guest = 0; /* Running as virtual machine guest? */ u_quad_t maxtsiz; /* max text size */ u_quad_t dfldsiz; /* initial data size limit */ u_quad_t maxdsiz; /* max data size */ diff --git a/sys/platform/pc32/i386/initcpu.c b/sys/platform/pc32/i386/initcpu.c index 8e7df82..5cb8e30 100644 --- a/sys/platform/pc32/i386/initcpu.c +++ b/sys/platform/pc32/i386/initcpu.c @@ -27,7 +27,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/initcpu.c,v 1.19.2.9 2003/04/05 13:47:19 dwmalone Exp $ - * $DragonFly: src/sys/platform/pc32/i386/initcpu.c,v 1.10 2006/12/23 00:27:03 swildner Exp $ */ #include "opt_cpu.h" @@ -84,6 +83,7 @@ u_int cpu_procinfo = 0; /* HyperThreading Info / Brand Index / CLFUSH */ u_int cpu_procinfo2 = 0; /* Multicore info */ char cpu_vendor[20] = ""; /* CPU Origin code */ u_int cpu_vendor_id = 0; /* CPU vendor ID */ +u_int cpu_clflush_line_size = 32; /* Default CLFLUSH line size */ SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD, &via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU"); @@ -685,6 +685,19 @@ initializecpu(void) break; } enable_sse(); + + if (cpu_feature2 & CPUID2_VMM) + vmm_guest = 1; + + /* Disable CLFLUSH on VMMs */ + if (cpu_feature & CPUID_CLFSH) { + if (vmm_guest) + cpu_feature &= ~CPUID_CLFSH; + else + cpu_clflush_line_size = + ((cpu_procinfo >> 8) & 0xff) * 8; + } + } #if defined(I586_CPU) && defined(CPU_WT_ALLOC) diff --git a/sys/platform/pc32/i386/machdep.c b/sys/platform/pc32/i386/machdep.c index 6864c51..aef97b8 100644 --- a/sys/platform/pc32/i386/machdep.c +++ b/sys/platform/pc32/i386/machdep.c @@ -1953,13 +1953,13 @@ init386(int first) TUNABLE_INT_FETCH("hw.lapic_enable", &lapic_enable); /* - * Some of the virtaul machines do not work w/ I/O APIC + * Some of the virtual machines do not work w/ I/O APIC * enabled. If the user does not explicitly enable or * disable the I/O APIC (ioapic_enable < 0), then we * disable I/O APIC on all virtual machines. */ if (ioapic_enable < 0) { - if (cpu_feature2 & CPUID2_VMM) + if (vmm_guest) ioapic_enable = 0; else ioapic_enable = 1; diff --git a/sys/platform/pc32/include/md_var.h b/sys/platform/pc32/include/md_var.h index 0e78241..2366dca 100644 --- a/sys/platform/pc32/include/md_var.h +++ b/sys/platform/pc32/include/md_var.h @@ -61,6 +61,7 @@ extern u_int amd_feature; extern u_int amd_feature2; extern u_int via_feature_rng; extern u_int via_feature_xcrypt; +extern u_int cpu_clflush_line_size; extern u_int cpu_fxsr; extern u_int cpu_high; extern u_int cpu_id; diff --git a/sys/platform/pc64/include/md_var.h b/sys/platform/pc64/include/md_var.h index cffe7c9..f929264 100644 --- a/sys/platform/pc64/include/md_var.h +++ b/sys/platform/pc64/include/md_var.h @@ -49,6 +49,7 @@ extern u_int via_feature_rng; extern u_int via_feature_xcrypt; extern u_int amd_feature; extern u_int amd_feature2; +extern u_int cpu_clflush_line_size; extern u_int cpu_fxsr; extern u_int cpu_high; extern u_int cpu_id; diff --git a/sys/platform/pc64/x86_64/initcpu.c b/sys/platform/pc64/x86_64/initcpu.c index 165173a..0caae8b 100644 --- a/sys/platform/pc64/x86_64/initcpu.c +++ b/sys/platform/pc64/x86_64/initcpu.c @@ -63,6 +63,7 @@ char cpu_vendor[20]; /* CPU Origin code */ u_int cpu_vendor_id; /* CPU vendor ID */ u_int cpu_fxsr; /* SSE enabled */ u_int cpu_mxcsr_mask; /* Valid bits in mxcsr */ +u_int cpu_clflush_line_size = 32; /* Default CLFLUSH line size */ SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD, &via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU"); @@ -179,4 +180,16 @@ initializecpu(void) CPUID_TO_FAMILY(cpu_id) == 0x6 && CPUID_TO_MODEL(cpu_id) >= 0xf) init_via(); + + if (cpu_feature2 & CPUID2_VMM) + vmm_guest = 1; + + /* Disable CLFLUSH on VMMs */ + if (cpu_feature & CPUID_CLFSH) { + if (vmm_guest) + cpu_feature &= ~CPUID_CLFSH; + else + cpu_clflush_line_size = + ((cpu_procinfo >> 8) & 0xff) * 8; + } } diff --git a/sys/platform/pc64/x86_64/machdep.c b/sys/platform/pc64/x86_64/machdep.c index 204407e..bd0bacd 100644 --- a/sys/platform/pc64/x86_64/machdep.c +++ b/sys/platform/pc64/x86_64/machdep.c @@ -1911,7 +1911,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) TUNABLE_INT_FETCH("hw.lapic_enable", &lapic_enable); /* - * Some of the virtaul machines do not work w/ I/O APIC + * Some of the virtual machines do not work w/ I/O APIC * enabled. If the user does not explicitly enable or * disable the I/O APIC (ioapic_enable < 0), then we * disable I/O APIC on all virtual machines. @@ -1921,7 +1921,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) * 'cpu_feature2' */ if (ioapic_enable < 0) { - if (cpu_feature2 & CPUID2_VMM) + if (vmm_guest) ioapic_enable = 0; else ioapic_enable = 1; diff --git a/sys/platform/vkernel/platform/init.c b/sys/platform/vkernel/platform/init.c index fc5a910..5b649ed 100644 --- a/sys/platform/vkernel/platform/init.c +++ b/sys/platform/vkernel/platform/init.c @@ -351,6 +351,8 @@ main(int ac, char **av) setrealcpu(); init_kqueue(); + vmm_guest = 1; + /* * Check TSC */ diff --git a/sys/platform/vkernel64/platform/init.c b/sys/platform/vkernel64/platform/init.c index c6d2c09..7be297a 100644 --- a/sys/platform/vkernel64/platform/init.c +++ b/sys/platform/vkernel64/platform/init.c @@ -348,6 +348,8 @@ main(int ac, char **av) setrealcpu(); init_kqueue(); + vmm_guest = 1; + /* * Check TSC */ diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index ea39332..acada19 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -86,6 +86,7 @@ extern int profhz; /* profiling clock's frequency */ extern int ticks; extern int lbolt; /* once a second sleep address */ extern void *lbolt_syncer; /* approx 1 hz but may be sped up */ +extern int vmm_guest; /* Running as virtual machine guest? */ /* * Enumerated types for known system startup interfaces. -- 1.7.7.2