[patch] Auto-setting hz to 100 inside QEMU/VMWare

Martin Voros martin_voros at yahoo.com
Tue Jan 1 12:52:43 PST 2008


It works fine here (VMware). 

Martin

----- Original Message ----
From: Mike Silbersack <silby at silby.com>
To: Robert Watson <rwatson at FreeBSD.org>
Cc: current at freebsd.org
Sent: Sunday, December 30, 2007 1:01:43 AM
Subject: Re: [patch] Auto-setting hz to 100 inside QEMU/VMWare



On Fri, 28 Dec 2007, Robert Watson wrote:

> I like the general idea, but one thing that does worry me is that
 this 
> prevents me from using config to set HZ at all, I have to set it at
 runtime 
> using the tunable.  Could we add an:

Attached is a patch which attempts to address all of Robert's concerns
 and 
includes all the strings for the various VMs that people have mailed in
 to 
me.

Please test/review. :)

Mike "Silby" Silbersack

-----Inline Attachment Follows-----

diff -u -r /usr/src/sys.old/amd64/amd64/machdep.c
 /usr/src/sys/amd64/amd64/machdep.c
--- /usr/src/sys.old/amd64/amd64/machdep.c    2007-12-29
 03:01:02.000000000 -0600
+++ /usr/src/sys/amd64/amd64/machdep.c    2007-12-29 18:57:01.000000000
 -0600
@@ -1935,3 +1935,33 @@
 }
 
 #endif /* KDB */
+
+/* kenv strings used to identify various VM environments */
+
+static char *vm_strings[] = {
+        "hint.acpi.0.oem", "QEMU",
+        "hint.acpi.0.oem", "VBOX", /* VirtualBox */
+        "smbios.system.maker", "VMware, Inc.",
+        "smbios.bios.vendor", "Parallels Software International Inc.",
+        NULL
+        };
+
+int
+detect_virtualmachine(void)
+{
+    char *envptr;
+    int i;
+    for (i = 0; ; i += 2) {
+        if (vm_strings[i] == NULL)
+            break;
+        envptr = getenv(vm_strings[i]);
+        if (envptr) {
+            if (strncmp(envptr, vm_strings[i+1],
 strlen(vm_strings[i+1])) == 0) {
+                freeenv(envptr);
+                return 1;
+            }
+            freeenv(envptr);
+        }
+    }
+    return 0;
+}
diff -u -r /usr/src/sys.old/arm/arm/machdep.c
 /usr/src/sys/arm/arm/machdep.c
--- /usr/src/sys.old/arm/arm/machdep.c    2007-12-29 03:01:06.000000000
 -0600
+++ /usr/src/sys/arm/arm/machdep.c    2007-12-29 18:57:21.000000000
 -0600
@@ -631,3 +631,9 @@
     pcb->un_32.pcb32_lr = tf->tf_usr_lr;
     pcb->un_32.pcb32_sp = tf->tf_usr_sp;
 }
+
+int
+detect_virtualmachine(void)
+{
+    return 0;
+}
diff -u -r /usr/src/sys.old/conf/NOTES /usr/src/sys/conf/NOTES
--- /usr/src/sys.old/conf/NOTES    2007-12-29 03:01:19.000000000 -0600
+++ /usr/src/sys/conf/NOTES    2007-12-29 18:54:40.000000000 -0600
@@ -1115,6 +1115,7 @@
 # the accuracy of operation.
 
 options     HZ=100
+options     VIRTUAL_HZ=100
 
 # Enable support for the kernel PLL to use an external PPS signal,
 # under supervision of [x]ntpd(8)
diff -u -r /usr/src/sys.old/conf/options /usr/src/sys/conf/options
--- /usr/src/sys.old/conf/options    2007-12-29 03:01:19.000000000
 -0600
+++ /usr/src/sys/conf/options    2007-12-29 03:06:22.000000000 -0600
@@ -262,6 +262,7 @@
 
 # Options used only in subr_param.c.
 HZ        opt_param.h
+VIRTUAL_HZ    opt_param.h
 MAXFILES    opt_param.h
 NBUF        opt_param.h
 NSFBUFS        opt_param.h
diff -u -r /usr/src/sys.old/i386/i386/machdep.c
 /usr/src/sys/i386/i386/machdep.c
--- /usr/src/sys.old/i386/i386/machdep.c    2007-12-29
 03:01:29.000000000 -0600
+++ /usr/src/sys/i386/i386/machdep.c    2007-12-29 03:59:05.000000000
 -0600
@@ -3110,3 +3110,33 @@
 }
 
 #endif /* KDB */
+
+/* kenv strings used to identify various VM environments */
+
+static char *vm_strings[] = {
+        "hint.acpi.0.oem", "QEMU",
+        "hint.acpi.0.oem", "VBOX", /* VirtualBox */
+        "smbios.system.maker", "VMware, Inc.",
+        "smbios.bios.vendor", "Parallels Software International Inc.",
+        NULL
+        };
+
+int
+detect_virtualmachine(void)
+{
+    char *envptr;
+    int i;
+    for (i = 0; ; i += 2) {
+        if (vm_strings[i] == NULL)
+            break;
+        envptr = getenv(vm_strings[i]);
+        if (envptr) {
+            if (strncmp(envptr, vm_strings[i+1],
 strlen(vm_strings[i+1])) == 0) {
+                freeenv(envptr);
+                return 1;
+            }
+            freeenv(envptr);
+        }
+    }
+    return 0;
+}
diff -u -r /usr/src/sys.old/ia64/ia64/machdep.c
 /usr/src/sys/ia64/ia64/machdep.c
--- /usr/src/sys.old/ia64/ia64/machdep.c    2007-12-29
 03:01:29.000000000 -0600
+++ /usr/src/sys/ia64/ia64/machdep.c    2007-12-29 19:02:23.000000000
 -0600
@@ -1531,3 +1531,9 @@
 {
     return (ENODEV);
 }
+
+int
+detect_virtualmachine(void)
+{
+    return 0;
+}
diff -u -r /usr/src/sys.old/kern/subr_param.c
 /usr/src/sys/kern/subr_param.c
--- /usr/src/sys.old/kern/subr_param.c    2007-12-29 03:01:29.000000000
 -0600
+++ /usr/src/sys/kern/subr_param.c    2007-12-29 03:14:23.000000000
 -0600
@@ -58,6 +58,9 @@
 #    define    HZ 100
 #  endif
 #endif
+#ifndef VIRTUAL_HZ
+#  define    VIRTUAL_HZ 100
+#endif
 #define    NPROC (20 + 16 * maxusers)
 #ifndef NBUF
 #define NBUF 0
@@ -109,7 +112,16 @@
 init_param1(void)
 {
 
-    hz = HZ;
+    /* Virtualization environments can't keep up with a
+     * 1000hz tick rate, leading to highly inaccurate
+     * timekeeping by FreeBSD guests.  To fix this problem,
+     * drop back to 100hz when we detect that we are running
+     * inside a virtual machine.
+     */
+    if (detect_virtualmachine())
+        hz = VIRTUAL_HZ;
+    else
+        hz = HZ;
     TUNABLE_INT_FETCH("kern.hz", &hz);
     tick = 1000000 / hz;
 
diff -u -r /usr/src/sys.old/pc98/pc98/machdep.c
 /usr/src/sys/pc98/pc98/machdep.c
--- /usr/src/sys.old/pc98/pc98/machdep.c    2007-12-29
 03:01:34.000000000 -0600
+++ /usr/src/sys/pc98/pc98/machdep.c    2007-12-29 19:01:49.000000000
 -0600
@@ -2791,3 +2791,9 @@
 }
 
 #endif /* KDB */
+
+int
+detect_virtualmachine(void)
+{
+    return 0;
+}
diff -u -r /usr/src/sys.old/powerpc/powerpc/intr_machdep.c
 /usr/src/sys/powerpc/powerpc/intr_machdep.c
--- /usr/src/sys.old/powerpc/powerpc/intr_machdep.c    2007-12-29
 03:01:34.000000000 -0600
+++ /usr/src/sys/powerpc/powerpc/intr_machdep.c    2007-12-29
 18:59:36.000000000 -0600
@@ -304,3 +304,9 @@
     if (i != NULL)
         PIC_MASK(pic, i->irq);
 }
+
+int
+detect_virtualmachine(void)
+{
+    return 0;
+}
diff -u -r /usr/src/sys.old/sparc64/sparc64/machdep.c
 /usr/src/sys/sparc64/sparc64/machdep.c
--- /usr/src/sys.old/sparc64/sparc64/machdep.c    2007-12-29
 03:01:35.000000000 -0600
+++ /usr/src/sys/sparc64/sparc64/machdep.c    2007-12-29
 19:01:33.000000000 -0600
@@ -910,3 +910,9 @@
     mtx_pool_unlock(mtxpool_sleep, ut);
     return (ut);
 }
+
+int
+detect_virtualmachine(void)
+{
+    return 0;
+}
diff -u -r /usr/src/sys.old/sun4v/sun4v/machdep.c
 /usr/src/sys/sun4v/sun4v/machdep.c
--- /usr/src/sys.old/sun4v/sun4v/machdep.c    2007-12-29
 03:01:01.000000000 -0600
+++ /usr/src/sys/sun4v/sun4v/machdep.c    2007-12-29 18:58:49.000000000
 -0600
@@ -999,3 +999,9 @@
     if (rdpr(pil) < PIL_TICK)
         hv_cpu_yield();
 }
+
+int
+detect_virtualmachine(void)
+{
+    return 0;
+}
diff -u -r /usr/src/sys.old/sys/systm.h /usr/src/sys/sys/systm.h
--- /usr/src/sys.old/sys/systm.h    2007-12-29 03:01:35.000000000 -0600
+++ /usr/src/sys/sys/systm.h    2007-12-29 03:50:59.000000000 -0600
@@ -245,6 +245,8 @@
 int    unsetenv(const char *name);
 int    testenv(const char *name);
 
+int    detect_virtualmachine(void);
+
 typedef uint64_t (cpu_tick_f)(void);
 void set_cputicker(cpu_tick_f *func, uint64_t freq, unsigned var);
 extern cpu_tick_f *cpu_ticks;



-----Inline Attachment Follows-----

_______________________________________________
freebsd-current at freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to
 "freebsd-current-unsubscribe at freebsd.org"





      ____________________________________________________________________________________
Looking for last minute shopping deals?  
Find them fast with Yahoo! Search.  http://tools.search.yahoo.com/newsearch/category.php?category=shopping


More information about the freebsd-current mailing list