Date: Sat, 6 Mar 2010 16:45:55 +0000 (UTC) From: Ivan Voras <ivoras@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r204799 - in stable/7/sys: amd64/amd64 i386/i386 kern sys Message-ID: <201003061645.o26Gjteh079167@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ivoras Date: Sat Mar 6 16:45:55 2010 New Revision: 204799 URL: http://svn.freebsd.org/changeset/base/204799 Log: MFC virtual machine guest detection code and r204420 - code to disable superpages on buggy AMD CPUs. Reviewed by: alc Modified: stable/7/sys/amd64/amd64/pmap.c stable/7/sys/i386/i386/pmap.c stable/7/sys/kern/subr_param.c stable/7/sys/sys/systm.h Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/amd64/amd64/pmap.c ============================================================================== --- stable/7/sys/amd64/amd64/pmap.c Sat Mar 6 16:27:43 2010 (r204798) +++ stable/7/sys/amd64/amd64/pmap.c Sat Mar 6 16:45:55 2010 (r204799) @@ -658,6 +658,15 @@ pmap_init(void) pv_entry_high_water = 9 * (pv_entry_max / 10); /* + * Disable large page mappings by default if the kernel is running in + * a virtual machine on an AMD Family 10h processor. This is a work- + * around for Erratum 383. + */ + if (vm_guest == VM_GUEST_VM && cpu_vendor_id == CPU_VENDOR_AMD && + CPUID_TO_FAMILY(cpu_id) == 0x10) + pg_ps_enabled = 0; + + /* * Are large page mappings enabled? */ TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); Modified: stable/7/sys/i386/i386/pmap.c ============================================================================== --- stable/7/sys/i386/i386/pmap.c Sat Mar 6 16:27:43 2010 (r204798) +++ stable/7/sys/i386/i386/pmap.c Sat Mar 6 16:45:55 2010 (r204799) @@ -672,6 +672,15 @@ pmap_init(void) pv_entry_high_water = 9 * (pv_entry_max / 10); /* + * Disable large page mappings by default if the kernel is running in + * a virtual machine on an AMD Family 10h processor. This is a work- + * around for Erratum 383. + */ + if (vm_guest == VM_GUEST_VM && cpu_vendor_id == CPU_VENDOR_AMD && + CPUID_TO_FAMILY(cpu_id) == 0x10) + pg_ps_enabled = 0; + + /* * Are large page mappings enabled? */ TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); Modified: stable/7/sys/kern/subr_param.c ============================================================================== --- stable/7/sys/kern/subr_param.c Sat Mar 6 16:27:43 2010 (r204798) +++ stable/7/sys/kern/subr_param.c Sat Mar 6 16:45:55 2010 (r204799) @@ -57,6 +57,13 @@ __FBSDID("$FreeBSD$"); # else # define HZ 100 # endif +# ifndef HZ_VM +# define HZ_VM 100 +# endif +#else +# ifndef HZ_VM +# define HZ_VM HZ +# endif #endif #define NPROC (20 + 16 * maxusers) #ifndef NBUF @@ -66,6 +73,8 @@ __FBSDID("$FreeBSD$"); #define MAXFILES (maxproc * 2) #endif +static int sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS); + int hz; int tick; int maxusers; /* base tunable */ @@ -79,6 +88,7 @@ int nswbuf; long maxswzone; /* max swmeta KVA storage */ long maxbcache; /* max buffer cache KVA storage */ long maxpipekva; /* Limit on pipe KVA */ +int vm_guest; /* Running as virtual machine guest? */ u_long maxtsiz; /* max text size */ u_long dfldsiz; /* initial data size limit */ u_long maxdsiz; /* max data size */ @@ -110,6 +120,9 @@ SYSCTL_ULONG(_kern, OID_AUTO, maxssiz, C "Maximum stack size"); SYSCTL_ULONG(_kern, OID_AUTO, sgrowsiz, CTLFLAG_RDTUN, &sgrowsiz, 0, "Amount to grow stack on a stack fault"); +SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING, + NULL, 0, sysctl_kern_vm_guest, "A", + "Virtual machine guest detected? (none|generic)"); /* * These have to be allocated somewhere; allocating @@ -119,14 +132,73 @@ SYSCTL_ULONG(_kern, OID_AUTO, sgrowsiz, struct buf *swbuf; /* + * The elements of this array are ordered based upon the values of the + * corresponding enum VM_GUEST members. + */ +static const char *const vm_guest_sysctl_names[] = { + "none", + "generic", + NULL +}; + +static const char *const vm_bnames[] = { + "QEMU", /* QEMU */ + "Plex86", /* Plex86 */ + "Bochs", /* Bochs */ + NULL +}; + +static const char *const vm_pnames[] = { + "VMware Virtual Platform", /* VMWare VM */ + "Virtual Machine", /* Microsoft VirtualPC */ + "VirtualBox", /* Sun xVM VirtualBox */ + "Parallels Virtual Platform", /* Parallels VM */ + NULL +}; + + +/* + * Detect known Virtual Machine hosts by inspecting the emulated BIOS. + */ +static enum VM_GUEST +detect_virtual(void) +{ + char *sysenv; + int i; + + sysenv = getenv("smbios.bios.vendor"); + if (sysenv != NULL) { + for (i = 0; vm_bnames[i] != NULL; i++) + if (strcmp(sysenv, vm_bnames[i]) == 0) { + freeenv(sysenv); + return (VM_GUEST_VM); + } + freeenv(sysenv); + } + sysenv = getenv("smbios.system.product"); + if (sysenv != NULL) { + for (i = 0; vm_pnames[i] != NULL; i++) + if (strcmp(sysenv, vm_pnames[i]) == 0) { + freeenv(sysenv); + return (VM_GUEST_VM); + } + freeenv(sysenv); + } + return (VM_GUEST_NO); +} + +/* * Boot time overrides that are not scaled against main memory */ void init_param1(void) { - hz = HZ; + vm_guest = detect_virtual(); + hz = -1; TUNABLE_INT_FETCH("kern.hz", &hz); + if (hz == -1) + hz = vm_guest > VM_GUEST_NO ? HZ_VM : HZ; tick = 1000000 / hz; #ifdef VM_SWZONE_SIZE_MAX @@ -213,3 +285,13 @@ init_param3(long kmempages) maxpipekva = 512 * 1024; TUNABLE_LONG_FETCH("kern.ipc.maxpipekva", &maxpipekva); } + +/* + * Sysctl stringiying handler for kern.vm_guest. + */ +static int +sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS) +{ + return (SYSCTL_OUT(req, vm_guest_sysctl_names[vm_guest], + strlen(vm_guest_sysctl_names[vm_guest]))); +} Modified: stable/7/sys/sys/systm.h ============================================================================== --- stable/7/sys/sys/systm.h Sat Mar 6 16:27:43 2010 (r204798) +++ stable/7/sys/sys/systm.h Sat Mar 6 16:45:55 2010 (r204799) @@ -70,6 +70,14 @@ extern int boothowto; /* reboot flags, extern int bootverbose; /* nonzero to print verbose messages */ extern int maxusers; /* system tune hint */ +extern int vm_guest; /* Running as virtual machine guest? */ + +/* + * Detected virtual machine guest types. The intention is to expand + * and/or add to the VM_GUEST_VM type if specific VM functionality is + * ever implemented (e.g. vendor-specific paravirtualization features). + */ +enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM }; #ifdef INVARIANTS /* The option is always available */ #define KASSERT(exp,msg) do { \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003061645.o26Gjteh079167>