diff options
author | Tycho Nightingale <tychon@FreeBSD.org> | 2014-04-18 00:02:06 +0000 |
---|---|---|
committer | Tycho Nightingale <tychon@FreeBSD.org> | 2014-04-18 00:02:06 +0000 |
commit | 79d6ca331ec02d76c58383803148333576e6ddd8 (patch) | |
tree | c6778c6f71b49f2361785e89a6d662a3caa713c1 | |
parent | 209579aeac0ac46349f9a1672a75df1eee1adf05 (diff) | |
download | src-test2-79d6ca331ec02d76c58383803148333576e6ddd8.tar.gz src-test2-79d6ca331ec02d76c58383803148333576e6ddd8.zip |
Notes
-rw-r--r-- | sys/amd64/vmm/io/vatpit.c | 74 | ||||
-rw-r--r-- | sys/amd64/vmm/io/vatpit.h | 3 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_ioport.c | 1 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_lpc.c | 18 |
4 files changed, 78 insertions, 18 deletions
diff --git a/sys/amd64/vmm/io/vatpit.c b/sys/amd64/vmm/io/vatpit.c index faac9e160e71..23431127f5cc 100644 --- a/sys/amd64/vmm/io/vatpit.c +++ b/sys/amd64/vmm/io/vatpit.c @@ -56,6 +56,8 @@ static MALLOC_DEFINE(M_VATPIT, "atpit", "bhyve virtual atpit (8254)"); #define TIMER_MODE_MASK 0x0f #define TIMER_SEL_READBACK 0xc0 +#define TMR2_OUT_STS 0x20 + #define PIT_8254_FREQ 1193182 #define TIMER_DIV(freq, hz) (((freq) + (hz) / 2) / (hz)) @@ -88,22 +90,29 @@ struct vatpit { struct channel channel[3]; }; -#define VATPIT_CTR0(vatpit, fmt) \ - VM_CTR0((vatpit)->vm, fmt) - -#define VATPIT_CTR1(vatpit, fmt, a1) \ - VM_CTR1((vatpit)->vm, fmt, a1) - -#define VATPIT_CTR2(vatpit, fmt, a1, a2) \ - VM_CTR2((vatpit)->vm, fmt, a1, a2) - -#define VATPIT_CTR3(vatpit, fmt, a1, a2, a3) \ - VM_CTR3((vatpit)->vm, fmt, a1, a2, a3) +static void pit_timer_start_cntr0(struct vatpit *vatpit); -#define VATPIT_CTR4(vatpit, fmt, a1, a2, a3, a4) \ - VM_CTR4((vatpit)->vm, fmt, a1, a2, a3, a4) +static int +vatpit_get_out(struct vatpit *vatpit, int channel) +{ + struct channel *c; + sbintime_t delta_ticks; + int out; + + c = &vatpit->channel[channel]; + + switch (c->mode) { + case TIMER_INTTC: + delta_ticks = (sbinuptime() - c->now_sbt) / vatpit->freq_sbt; + out = ((c->initial - delta_ticks) <= 0); + break; + default: + out = 0; + break; + } -static void pit_timer_start_cntr0(struct vatpit *vatpit); + return (out); +} static void vatpit_callout_handler(void *a) @@ -117,7 +126,7 @@ vatpit_callout_handler(void *a) c = &vatpit->channel[arg->channel_num]; callout = &c->callout; - VATPIT_CTR1(vatpit, "atpit t%d fired", arg->channel_num); + VM_CTR1(vatpit->vm, "atpit t%d fired", arg->channel_num); VATPIT_LOCK(vatpit); @@ -145,7 +154,7 @@ static void pit_timer_start_cntr0(struct vatpit *vatpit) { struct channel *c; - sbintime_t delta, precision; + sbintime_t now, delta, precision; c = &vatpit->channel[0]; if (c->initial != 0) { @@ -153,6 +162,15 @@ pit_timer_start_cntr0(struct vatpit *vatpit) precision = delta >> tc_precexp; c->callout_sbt = c->callout_sbt + delta; + /* + * Reset 'callout_sbt' if the time that the callout + * was supposed to fire is more than 'c->initial' + * ticks in the past. + */ + now = sbinuptime(); + if (c->callout_sbt < now) + c->callout_sbt = now + delta; + callout_reset_sbt(&c->callout, c->callout_sbt, precision, vatpit_callout_handler, &c->callout_arg, C_ABSOLUTE); @@ -252,8 +270,8 @@ vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit) port = vmexit->u.inout.port; if (port == TIMER_MODE) { - if (vmexit->u.inout.in != 0) { - VATPIT_CTR0(vatpit, "vatpit attempt to read mode"); + if (vmexit->u.inout.in) { + VM_CTR0(vatpit->vm, "vatpit attempt to read mode"); return (-1); } @@ -310,6 +328,26 @@ vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit) return (0); } +int +vatpit_nmisc_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +{ + struct vatpit *vatpit; + + vatpit = vm_atpit(vm); + + if (vmexit->u.inout.in) { + VATPIT_LOCK(vatpit); + if (vatpit_get_out(vatpit, 2)) + vmexit->u.inout.eax = TMR2_OUT_STS; + else + vmexit->u.inout.eax = 0; + + VATPIT_UNLOCK(vatpit); + } + + return (0); +} + struct vatpit * vatpit_init(struct vm *vm) { diff --git a/sys/amd64/vmm/io/vatpit.h b/sys/amd64/vmm/io/vatpit.h index 4f30acf87b0e..ef89912936ed 100644 --- a/sys/amd64/vmm/io/vatpit.h +++ b/sys/amd64/vmm/io/vatpit.h @@ -32,9 +32,12 @@ #include <machine/timerreg.h> +#define NMISC_PORT 0x61 + struct vatpit *vatpit_init(struct vm *vm); void vatpit_cleanup(struct vatpit *vatpit); int vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit); +int vatpit_nmisc_handler(void *vm, int vcpuid, struct vm_exit *vmexit); #endif /* _VATPIT_H_ */ diff --git a/sys/amd64/vmm/vmm_ioport.c b/sys/amd64/vmm/vmm_ioport.c index 1df916a0b8b3..7a9de6fbcebe 100644 --- a/sys/amd64/vmm/vmm_ioport.c +++ b/sys/amd64/vmm/vmm_ioport.c @@ -46,6 +46,7 @@ ioport_handler_func_t ioport_handler[MAX_IOPORTS] = { [TIMER_CNTR0] = vatpit_handler, [TIMER_CNTR1] = vatpit_handler, [TIMER_CNTR2] = vatpit_handler, + [NMISC_PORT] = vatpit_nmisc_handler, [IO_ICU1] = vatpic_master_handler, [IO_ICU1 + ICU_IMR_OFFSET] = vatpic_master_handler, [IO_ICU2] = vatpic_slave_handler, diff --git a/usr.sbin/bhyve/pci_lpc.c b/usr.sbin/bhyve/pci_lpc.c index ddeb9bdc0c5b..d50ea89897ab 100644 --- a/usr.sbin/bhyve/pci_lpc.c +++ b/usr.sbin/bhyve/pci_lpc.c @@ -55,6 +55,11 @@ SET_DECLARE(lpc_sysres_set, struct lpc_sysres); #define ELCR_PORT 0x4d0 SYSRES_IO(ELCR_PORT, 2); +#define IO_TIMER1_PORT 0x40 + +#define NMISC_PORT 0x61 +SYSRES_IO(NMISC_PORT, 1); + static struct pci_devinst *lpc_bridge; #define LPC_UART_NUM 2 @@ -226,6 +231,19 @@ pci_lpc_write_dsdt(struct pci_devinst *pi) dsdt_line("}"); dsdt_unindent(1); + dsdt_line(""); + dsdt_line("Device (TIMR)"); + dsdt_line("{"); + dsdt_line(" Name (_HID, EisaId (\"PNP0100\"))"); + dsdt_line(" Name (_CRS, ResourceTemplate ()"); + dsdt_line(" {"); + dsdt_indent(2); + dsdt_fixed_ioport(IO_TIMER1_PORT, 4); + dsdt_fixed_irq(0); + dsdt_unindent(2); + dsdt_line(" })"); + dsdt_line("}"); + dsdt_line("}"); } |