]> Zhao Yanbai Git Server - minix.git/commitdiff
Add vbox -- VirtualBox time sync driver
authorDavid van Moolenbroek <david@minix3.org>
Wed, 23 Nov 2011 17:15:43 +0000 (18:15 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 23 Nov 2011 17:15:43 +0000 (18:15 +0100)
Sets time forward to match the host time.

Started automatically if the corresponding device is present.

commands/profile/sprofalyze.pl
drivers/Makefile
drivers/pci/pci_table.c
drivers/vbox/Makefile [new file with mode: 0644]
drivers/vbox/vbox.c [new file with mode: 0644]
drivers/vbox/vbox.h [new file with mode: 0644]
etc/system.conf
etc/usr/rc

index d631c2bff1002e4c2377153493ca058499134767..1632d894e3ccabb56423c142ff4da9e5db524491 100755 (executable)
@@ -68,6 +68,7 @@ drivers/rtl8139/rtl8139
 drivers/rtl8169/rtl8169
 drivers/ti1225/ti1225
 drivers/tty/tty
+drivers/vbox/vbox
        );
 
 # 8< ----------- no user configurable parameters below this line ----------- >8
index 8183e910599d962dc8d96341215bc9dcdd2644da..ad932c7b5765f6765bb19bc5e5d4f6b05d4cdc5e 100644 (file)
@@ -13,7 +13,7 @@ SUBDIR=       at_wini bios_wini floppy log tty pci .WAIT ramdisk .WAIT memory
 # memory driver must be last for ramdisk image
 SUBDIR+= ahci amddev atl2 at_wini audio bios_wini dec21140A dp8390 dpeth \
        e1000 filter floppy fxp hello lance log orinoco pci printer \
-       random readclock rtl8139 rtl8169 ti1225 tty acpi \
+       random readclock rtl8139 rtl8169 ti1225 tty vbox acpi \
        .WAIT ramdisk .WAIT memory
 
 .endif
index 96668639395d5d617e6bc30e560a6d9673b85b89..06cbbb0e25200ed0e377252a8842b0b4e6540556 100644 (file)
@@ -47,6 +47,7 @@ struct pci_vendor pci_vendor_table[]=
        { 0x1969, "Atheros Communications" },
        { 0x5333, "S3" },
        { 0x8086, "Intel" },
+       { 0x80ee, "Oracle" },
        { 0x9004, "Adaptec" },
        { 0x9005, "Adaptec" },
        { 0x0000, NULL }
@@ -170,6 +171,7 @@ struct pci_device pci_device_table[]=
        { 0x8086, 0x7190, "Intel 82443BX" },
        { 0x8086, 0x7191, "Intel 82443BX (AGP bridge)" },
        { 0x8086, 0x7192, "Intel 82443BX (Host-to-PCI bridge)" },
+       { 0x80ee, 0xcafe, "Oracle VirtualBox backdoor device" },
        { 0x9004, 0x8178, "Adaptec AHA-2940U/2940UW Ultra/Ultra-Wide SCSI Ctrlr" },
        { 0x9005, 0x0080, "Adaptec AIC-7892A Ultra160/m PCI SCSI Controller" },
        { 0x0000, 0x0000, NULL }
diff --git a/drivers/vbox/Makefile b/drivers/vbox/Makefile
new file mode 100644 (file)
index 0000000..abf3e77
--- /dev/null
@@ -0,0 +1,12 @@
+# Makefile for the VirtualBox backdoor driver (VBOX)
+PROG=  vbox
+SRCS=  vbox.c
+
+DPADD+=        ${LIBSYS}
+LDADD+=        -lsys
+
+MAN=
+
+BINDIR?= /usr/sbin
+
+.include <minix.service.mk>
diff --git a/drivers/vbox/vbox.c b/drivers/vbox/vbox.c
new file mode 100644 (file)
index 0000000..24c8351
--- /dev/null
@@ -0,0 +1,189 @@
+/* VirtualBox driver - only does regular time sync - by D.C. van Moolenbroek */
+#include <minix/drivers.h>
+#include <minix/driver.h>
+#include <minix/optset.h>
+#include <machine/pci.h>
+#include <sys/time.h>
+
+#include "vbox.h"
+
+#define DEFAULT_INTERVAL       1       /* check host time every second */
+#define DEFAULT_DRIFT          2       /* update time if delta is >= 2 secs */
+
+PRIVATE void *vir_ptr;
+PRIVATE phys_bytes phys_ptr;
+PRIVATE port_t port;
+PRIVATE u32_t ticks;
+PRIVATE int interval;
+PRIVATE int drift;
+
+PRIVATE struct optset optset_table[] = {
+       { "interval",   OPT_INT,        &interval,      10              },
+       { "drift",      OPT_INT,        &drift,         10              },
+       { NULL,         0,              NULL,           0               }
+};
+
+/*===========================================================================*
+ *                             vbox_request                                 *
+ *===========================================================================*/
+PRIVATE int vbox_request(int req_nr, size_t size)
+{
+       /* Perform a VirtualBox backdoor request. */
+       struct VMMDevRequestHeader *hdr;
+       int r;
+
+       hdr = (struct VMMDevRequestHeader *) vir_ptr;
+       hdr->size = size;
+       hdr->version = VMMDEV_BACKDOOR_VERSION;
+       hdr->type = req_nr;
+       hdr->rc = VMMDEV_ERR_PERM;
+
+       if ((r = sys_outl(port, phys_ptr)) != OK)
+               panic("device I/O failed: %d", r);
+
+       return hdr->rc;
+}
+
+/*===========================================================================*
+ *                             vbox_init                                    *
+ *===========================================================================*/
+PRIVATE int vbox_init(int UNUSED(type), sef_init_info_t *UNUSED(info))
+{
+       /* Initialize the device. */
+       int devind;
+       u16_t vid, did;
+       struct VMMDevReportGuestInfo *req;
+       int r;
+
+       interval = DEFAULT_INTERVAL;
+       drift = DEFAULT_DRIFT;
+
+       if (env_argc > 1)
+               optset_parse(optset_table, env_argv[1]);
+
+       pci_init();
+
+       r = pci_first_dev(&devind, &vid, &did);
+
+       for (;;) {
+               if (r != 1)
+                       panic("backdoor device not found");
+
+               if (vid == VBOX_PCI_VID && did == VBOX_PCI_DID)
+                       break;
+
+               r = pci_next_dev(&devind, &vid, &did);
+       }
+
+       port = pci_attr_r16(devind, PCI_BAR) & 0xfffc;
+
+       pci_reserve(devind);
+
+       if ((vir_ptr = alloc_contig(VMMDEV_BUF_SIZE, 0, &phys_ptr)) == NULL)
+               panic("unable to allocate memory");
+
+       req = (struct VMMDevReportGuestInfo *) vir_ptr;
+       req->guest_info.add_version = VMMDEV_GUEST_VERSION;
+       req->guest_info.os_type = VMMDEV_GUEST_OS_OTHER;
+
+       if ((r = vbox_request(VMMDEV_REQ_REPORTGUESTINFO, sizeof(*req))) !=
+                       VMMDEV_ERR_OK)
+               panic("backdoor device not functioning");
+
+       ticks = sys_hz() * interval;
+
+       sys_setalarm(ticks, 0);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             vbox_update_time                             *
+ *===========================================================================*/
+PRIVATE void vbox_update_time(void)
+{
+       /* Update the current time if it has drifted too far. */
+       struct VMMDevReqHostTime *req;
+       time_t otime, ntime;
+
+       req = (struct VMMDevReqHostTime *) vir_ptr;
+
+       if (vbox_request(VMMDEV_REQ_HOSTTIME, sizeof(*req)) == VMMDEV_ERR_OK) {
+               time(&otime);                           /* old time */
+
+               ntime = div64u(req->time, 1000);        /* new time */
+
+               /* Make time go forward, if the difference exceeds the drift
+                * threshold. Never make time go backward.
+                */
+               if ((int) (ntime - otime) >= drift)
+                       stime(&ntime);
+       }
+
+       sys_setalarm(ticks, 0);
+}
+
+/*===========================================================================*
+ *                             vbox_signal                                  *
+ *===========================================================================*/
+PRIVATE void vbox_signal(int signo)
+{
+       /* Process a signal. If it is a SIGTERM, terminate immediately. */
+
+       if (signo != SIGTERM) return;
+
+       exit(0);
+}
+
+/*===========================================================================*
+ *                             sef_local_startup                            *
+ *===========================================================================*/
+PRIVATE void sef_local_startup(void)
+{
+       /* Perform local SEF initialization. */
+
+       sef_setcb_init_fresh(vbox_init);
+       sef_setcb_init_restart(vbox_init);
+
+       sef_setcb_signal_handler(vbox_signal);
+
+       sef_startup();
+}
+
+/*===========================================================================*
+ *                             main                                         *
+ *===========================================================================*/
+PUBLIC int main(int argc, char **argv)
+{
+       /* The main message loop. */
+       message m;
+       int r, ipc_status;
+
+       env_setargs(argc, argv);
+       sef_local_startup();
+
+       while (TRUE) {
+               if ((r = driver_receive(ANY, &m, &ipc_status)) != OK)
+                       panic("driver_receive failed: %d", r);
+
+               if (is_ipc_notify(ipc_status)) {
+                       switch (m.m_source) {
+                       case CLOCK:
+                               vbox_update_time();
+
+                               break;
+
+                       default:
+                               printf("VBOX: received notify from %d\n",
+                                       m.m_source);
+                       }
+
+                       continue;
+               }
+
+               printf("VBOX: received message %d from %d\n",
+                       m.m_type, m.m_source);
+       }
+
+       return 0;
+}
diff --git a/drivers/vbox/vbox.h b/drivers/vbox/vbox.h
new file mode 100644 (file)
index 0000000..4e43673
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _VBOX_H
+#define _VBOX_H
+
+#define VBOX_PCI_VID 0x80ee
+#define VBOX_PCI_DID 0xcafe
+
+struct VMMDevRequestHeader {
+       u32_t size;
+       u32_t version;
+       u32_t type;
+       i32_t rc;
+       u32_t reserved[2];
+};
+
+struct VBoxGuestInfo {
+       u32_t add_version;
+       u32_t os_type;
+};
+
+struct VMMDevReportGuestInfo {
+       struct VMMDevRequestHeader header;
+       struct VBoxGuestInfo guest_info;
+};
+
+struct VMMDevReqHostTime {
+       struct VMMDevRequestHeader header;
+       u64_t time;
+};
+
+#define VMMDEV_MAKEWORD(m,n)   (((m) << 16) | (n))
+
+#define VMMDEV_BACKDOOR_VERSION        VMMDEV_MAKEWORD(1, 1)
+#define VMMDEV_GUEST_VERSION   VMMDEV_MAKEWORD(1, 4)
+#define VMMDEV_GUEST_OS_OTHER  0x90000         /* this is L4 - close enough */
+
+#define VMMDEV_REQ_REPORTGUESTINFO     50
+#define VMMDEV_REQ_HOSTTIME            10
+
+#define VMMDEV_ERR_OK          0
+#define VMMDEV_ERR_PERM                (-10)
+
+#define VMMDEV_BUF_SIZE                4096            /* just one page */
+
+#endif /* _VBOX_H */
index 5e147631b129861950e6afec900cf35a4db58ac6..ead66bbdf508f5efcc6e09f109659ade26a54607 100644 (file)
@@ -524,6 +524,19 @@ service devman
        uid 0;
 };
 
-
-
-
+service vbox
+{
+       system
+               UMAP            # 14
+               DEVIO           # 21
+       ;
+       pci device      80ee/cafe;
+       ipc
+               SYSTEM
+               PM
+               RS
+               VM
+               pci
+       ;
+       uid     0;
+};
index a985e22872cbe6231722ea647148caf0b361761c..69fe0c529c304e408f23fb33c1f36e59246b7005 100644 (file)
@@ -141,6 +141,10 @@ start)
     fi
     up -n printer -dev /dev/lp -period 10HZ
     up -n ipc
+    # start VirtualBox time sync driver if the device is there
+    if grep '^[^ ]* [^ ]* 80EE:CAFE ' /proc/pci >/dev/null; then
+      up -n vbox -period 10HZ
+    fi
     echo .
 
     # Network initialization.