diff options
-rw-r--r-- | usr.sbin/vmd/i8253.c | 47 | ||||
-rw-r--r-- | usr.sbin/vmd/i8253.h | 4 | ||||
-rw-r--r-- | usr.sbin/vmd/vm.c | 3 |
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); |