summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authormlarkin <mlarkin@openbsd.org>2018-04-26 17:10:09 +0000
committermlarkin <mlarkin@openbsd.org>2018-04-26 17:10:09 +0000
commit03fd2d06315b8fe113fbada40c57be256a4fe9d4 (patch)
tree715c7fc73d7ca7f6774b67175fddec3170e5c5e6 /usr.sbin
parentAdd error handling to unconfuse myself when playing with pledgepath(). (diff)
downloadwireguard-openbsd-03fd2d06315b8fe113fbada40c57be256a4fe9d4.tar.xz
wireguard-openbsd-03fd2d06315b8fe113fbada40c57be256a4fe9d4.zip
vmd(8): handle PIT channel 2 status readback via port 0x61
Allow PIT channel 2 status (fired/counting) readback via port 0x61 bit 5. ok guenther@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/vmd/i8253.c47
-rw-r--r--usr.sbin/vmd/i8253.h4
-rw-r--r--usr.sbin/vmd/vm.c3
3 files changed, 49 insertions, 5 deletions
diff --git a/usr.sbin/vmd/i8253.c b/usr.sbin/vmd/i8253.c
index 8515d4d7508..5493c564b8b 100644
--- a/usr.sbin/vmd/i8253.c
+++ b/usr.sbin/vmd/i8253.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i8253.c,v 1.19 2018/04/26 16:56:13 mlarkin Exp $ */
+/* $OpenBSD: i8253.c,v 1.20 2018/04/26 17:10:09 mlarkin Exp $ */
/*
* Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
*
@@ -37,8 +37,9 @@ extern char *__progname;
/*
* Channel 0 is used to generate the legacy hardclock interrupt (HZ).
- * Channels 1 and 2 are not connected to any output (although someone
- * could hook channel 2 up to an emulated pcppi(4) at some point).
+ * Channels 1 and 2 can be used by the guest OS as regular timers,
+ * but channel 2 is not connected to any pcppi(4)-like device. Like
+ * a regular PC, channel 2 status can also be read from port 0x61.
*/
struct i8253_channel i8253_channel[3];
@@ -59,16 +60,19 @@ i8253_init(uint32_t vm_id)
i8253_channel[0].mode = TIMER_INTTC;
i8253_channel[0].last_r = 1;
i8253_channel[0].vm_id = vm_id;
+ i8253_channel[0].state = 0;
i8253_channel[1].start = 0xFFFF;
i8253_channel[1].mode = TIMER_INTTC;
i8253_channel[1].last_r = 1;
i8253_channel[1].vm_id = vm_id;
+ i8253_channel[1].state = 0;
i8253_channel[2].start = 0xFFFF;
i8253_channel[2].mode = TIMER_INTTC;
i8253_channel[2].last_r = 1;
i8253_channel[2].vm_id = vm_id;
+ i8253_channel[2].state = 0;
evtimer_set(&i8253_channel[0].timer, i8253_fire, &i8253_channel[0]);
evtimer_set(&i8253_channel[1].timer, i8253_fire, &i8253_channel[1]);
@@ -119,6 +123,40 @@ i8253_do_readback(uint32_t data)
}
/*
+ * vcpu_exit_i8253_misc
+ *
+ * Handles the 0x61 misc i8253 PIT register in/out exits.
+ *
+ * Parameters:
+ * vrp: vm run parameters containing exit information for the I/O
+ * instruction being performed
+ *
+ * Return value:
+ * Always 0xFF (no interrupt should be injected)
+ */
+uint8_t
+vcpu_exit_i8253_misc(struct vm_run_params *vrp)
+{
+ union vm_exit *vei = vrp->vrp_exit;
+
+ if (vei->vei.vei_dir == VEI_DIR_IN) {
+ /* Port 0x61[5] = counter channel 2 state */
+ if (i8253_channel[2].state) {
+ set_return_data(vei, (1 << 5));
+ log_debug("%s: counter 2 fired, returning 0x20", __func__);
+ } else {
+ set_return_data(vei, 0);
+ log_debug("%s: counter 2 clear, returning 0x0", __func__);
+ }
+ } else {
+ log_debug("%s: discarding data written to PIT misc port\n",
+ __func__);
+ }
+
+ return 0xFF;
+}
+
+/*
* vcpu_exit_i8253
*
* Handles emulated i8253 PIT access (in/out instruction to PIT ports).
@@ -254,6 +292,7 @@ i8253_reset(uint8_t chn)
timerclear(&tv);
i8253_channel[chn].in_use = 1;
+ i8253_channel[chn].state = 0;
tv.tv_usec = (i8253_channel[chn].start * NS_PER_TICK) / 1000;
evtimer_add(&i8253_channel[chn].timer, &tv);
}
@@ -282,6 +321,8 @@ i8253_fire(int fd, short type, void *arg)
if (ctr->mode != TIMER_INTTC)
evtimer_add(&ctr->timer, &tv);
+ else
+ ctr->state = 1;
}
int
diff --git a/usr.sbin/vmd/i8253.h b/usr.sbin/vmd/i8253.h
index b6eebefbb56..e72fbe40bac 100644
--- a/usr.sbin/vmd/i8253.h
+++ b/usr.sbin/vmd/i8253.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i8253.h,v 1.8 2018/04/17 14:34:09 cheloha Exp $ */
+/* $OpenBSD: i8253.h,v 1.9 2018/04/26 17:10:10 mlarkin Exp $ */
/*
* Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
*
@@ -40,6 +40,7 @@ struct i8253_channel {
struct event timer; /* timer event for this counter */
uint32_t vm_id; /* owning VM id */
int in_use; /* denotes if this counter was ever used */
+ uint8_t state; /* 0 if channel is counting, 1 if fired */
};
void i8253_init(uint32_t);
@@ -48,6 +49,7 @@ void i8253_fire(int, short, void *);
int i8253_dump(int);
int i8253_restore(int, uint32_t);
uint8_t vcpu_exit_i8253(struct vm_run_params *);
+uint8_t vcpu_exit_i8253_misc(struct vm_run_params *);
void i8253_do_readback(uint32_t);
void i8253_stop(void);
void i8253_start(void);
diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c
index 32c5c52454d..18327eb3cdb 100644
--- a/usr.sbin/vmd/vm.c
+++ b/usr.sbin/vmd/vm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm.c,v 1.31 2018/01/03 05:39:56 ccardenas Exp $ */
+/* $OpenBSD: vm.c,v 1.32 2018/04/26 17:10:10 mlarkin Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -922,6 +922,7 @@ init_emulated_hw(struct vmop_create_params *vmc, int child_cdrom,
ioports_map[TIMER_BASE + TIMER_CNTR0] = vcpu_exit_i8253;
ioports_map[TIMER_BASE + TIMER_CNTR1] = vcpu_exit_i8253;
ioports_map[TIMER_BASE + TIMER_CNTR2] = vcpu_exit_i8253;
+ ioports_map[PCKBC_AUX] = vcpu_exit_i8253_misc;
/* Init mc146818 RTC */
mc146818_init(vcp->vcp_id, memlo, memhi);