[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