svn commit: r204799 - in stable/7/sys: amd64/amd64 i386/i386 kern
sys
Ivan Voras
ivoras at FreeBSD.org
Sat Mar 6 16:45:55 UTC 2010
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 { \
More information about the svn-src-all
mailing list