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
8 changed files with 269 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
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.
|
||||
|
|
Loading…
Reference in a new issue