Date: Fri, 18 Apr 2014 00:02:07 +0000 (UTC) From: Tycho Nightingale <tychon@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264631 - in head: sys/amd64/vmm sys/amd64/vmm/io usr.sbin/bhyve Message-ID: <201404180002.s3I027GQ024622@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tychon Date: Fri Apr 18 00:02:06 2014 New Revision: 264631 URL: http://svnweb.freebsd.org/changeset/base/264631 Log: Add support for reading the PIT Counter 2 output signal via the NMI Status and Control register at port 0x61. Be more conservative about "catching up" callouts that were supposed to fire in the past by skipping an interrupt if it was scheduled too far in the past. Restore the PIT ACPI DSDT entries and add an entry for NMISC too. Approved by: neel (co-mentor) Modified: head/sys/amd64/vmm/io/vatpit.c head/sys/amd64/vmm/io/vatpit.h head/sys/amd64/vmm/vmm_ioport.c head/usr.sbin/bhyve/pci_lpc.c Modified: head/sys/amd64/vmm/io/vatpit.c ============================================================================== --- head/sys/amd64/vmm/io/vatpit.c Thu Apr 17 23:31:50 2014 (r264630) +++ head/sys/amd64/vmm/io/vatpit.c Fri Apr 18 00:02:06 2014 (r264631) @@ -56,6 +56,8 @@ static MALLOC_DEFINE(M_VATPIT, "atpit", #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) +static void pit_timer_start_cntr0(struct vatpit *vatpit); -#define VATPIT_CTR2(vatpit, fmt, a1, a2) \ - VM_CTR2((vatpit)->vm, fmt, a1, a2) +static int +vatpit_get_out(struct vatpit *vatpit, int channel) +{ + struct channel *c; + sbintime_t delta_ticks; + int out; -#define VATPIT_CTR3(vatpit, fmt, a1, a2, a3) \ - VM_CTR3((vatpit)->vm, fmt, a1, a2, a3) + c = &vatpit->channel[channel]; -#define VATPIT_CTR4(vatpit, fmt, a1, a2, a3, a4) \ - VM_CTR4((vatpit)->vm, fmt, a1, a2, a3, a4) + 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 *vat 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, str 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, str 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) { Modified: head/sys/amd64/vmm/io/vatpit.h ============================================================================== --- head/sys/amd64/vmm/io/vatpit.h Thu Apr 17 23:31:50 2014 (r264630) +++ head/sys/amd64/vmm/io/vatpit.h Fri Apr 18 00:02:06 2014 (r264631) @@ -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_ */ Modified: head/sys/amd64/vmm/vmm_ioport.c ============================================================================== --- head/sys/amd64/vmm/vmm_ioport.c Thu Apr 17 23:31:50 2014 (r264630) +++ head/sys/amd64/vmm/vmm_ioport.c Fri Apr 18 00:02:06 2014 (r264631) @@ -46,6 +46,7 @@ ioport_handler_func_t ioport_handler[MAX [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, Modified: head/usr.sbin/bhyve/pci_lpc.c ============================================================================== --- head/usr.sbin/bhyve/pci_lpc.c Thu Apr 17 23:31:50 2014 (r264630) +++ head/usr.sbin/bhyve/pci_lpc.c Fri Apr 18 00:02:06 2014 (r264631) @@ -55,6 +55,11 @@ SET_DECLARE(lpc_sysres_set, struct lpc_s #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 *p 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("}"); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404180002.s3I027GQ024622>