Add vbox -- VirtualBox time sync driver
Sets time forward to match the host time. Started automatically if the corresponding device is present.
This commit is contained in:
parent
b4d9ac91ba
commit
0aa01a2dce
@ -68,6 +68,7 @@ drivers/rtl8139/rtl8139
|
|||||||
drivers/rtl8169/rtl8169
|
drivers/rtl8169/rtl8169
|
||||||
drivers/ti1225/ti1225
|
drivers/ti1225/ti1225
|
||||||
drivers/tty/tty
|
drivers/tty/tty
|
||||||
|
drivers/vbox/vbox
|
||||||
);
|
);
|
||||||
|
|
||||||
# 8< ----------- no user configurable parameters below this line ----------- >8
|
# 8< ----------- no user configurable parameters below this line ----------- >8
|
||||||
|
@ -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
|
# memory driver must be last for ramdisk image
|
||||||
SUBDIR+= ahci amddev atl2 at_wini audio bios_wini dec21140A dp8390 dpeth \
|
SUBDIR+= ahci amddev atl2 at_wini audio bios_wini dec21140A dp8390 dpeth \
|
||||||
e1000 filter floppy fxp hello lance log orinoco pci printer \
|
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
|
.WAIT ramdisk .WAIT memory
|
||||||
|
|
||||||
.endif
|
.endif
|
||||||
|
@ -47,6 +47,7 @@ struct pci_vendor pci_vendor_table[]=
|
|||||||
{ 0x1969, "Atheros Communications" },
|
{ 0x1969, "Atheros Communications" },
|
||||||
{ 0x5333, "S3" },
|
{ 0x5333, "S3" },
|
||||||
{ 0x8086, "Intel" },
|
{ 0x8086, "Intel" },
|
||||||
|
{ 0x80ee, "Oracle" },
|
||||||
{ 0x9004, "Adaptec" },
|
{ 0x9004, "Adaptec" },
|
||||||
{ 0x9005, "Adaptec" },
|
{ 0x9005, "Adaptec" },
|
||||||
{ 0x0000, NULL }
|
{ 0x0000, NULL }
|
||||||
@ -170,6 +171,7 @@ struct pci_device pci_device_table[]=
|
|||||||
{ 0x8086, 0x7190, "Intel 82443BX" },
|
{ 0x8086, 0x7190, "Intel 82443BX" },
|
||||||
{ 0x8086, 0x7191, "Intel 82443BX (AGP bridge)" },
|
{ 0x8086, 0x7191, "Intel 82443BX (AGP bridge)" },
|
||||||
{ 0x8086, 0x7192, "Intel 82443BX (Host-to-PCI 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" },
|
{ 0x9004, 0x8178, "Adaptec AHA-2940U/2940UW Ultra/Ultra-Wide SCSI Ctrlr" },
|
||||||
{ 0x9005, 0x0080, "Adaptec AIC-7892A Ultra160/m PCI SCSI Controller" },
|
{ 0x9005, 0x0080, "Adaptec AIC-7892A Ultra160/m PCI SCSI Controller" },
|
||||||
{ 0x0000, 0x0000, NULL }
|
{ 0x0000, 0x0000, NULL }
|
||||||
|
12
drivers/vbox/Makefile
Normal file
12
drivers/vbox/Makefile
Normal file
@ -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>
|
189
drivers/vbox/vbox.c
Normal file
189
drivers/vbox/vbox.c
Normal file
@ -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;
|
||||||
|
}
|
44
drivers/vbox/vbox.h
Normal file
44
drivers/vbox/vbox.h
Normal file
@ -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 */
|
@ -524,6 +524,19 @@ service devman
|
|||||||
uid 0;
|
uid 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
service vbox
|
||||||
|
{
|
||||||
|
system
|
||||||
|
UMAP # 14
|
||||||
|
DEVIO # 21
|
||||||
|
;
|
||||||
|
pci device 80ee/cafe;
|
||||||
|
ipc
|
||||||
|
SYSTEM
|
||||||
|
PM
|
||||||
|
RS
|
||||||
|
VM
|
||||||
|
pci
|
||||||
|
;
|
||||||
|
uid 0;
|
||||||
|
};
|
||||||
|
@ -141,6 +141,10 @@ start)
|
|||||||
fi
|
fi
|
||||||
up -n printer -dev /dev/lp -period 10HZ
|
up -n printer -dev /dev/lp -period 10HZ
|
||||||
up -n ipc
|
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 .
|
echo .
|
||||||
|
|
||||||
# Network initialization.
|
# Network initialization.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user