summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTycho Nightingale <tychon@FreeBSD.org>2014-04-18 00:02:06 +0000
committerTycho Nightingale <tychon@FreeBSD.org>2014-04-18 00:02:06 +0000
commit79d6ca331ec02d76c58383803148333576e6ddd8 (patch)
treec6778c6f71b49f2361785e89a6d662a3caa713c1
parent209579aeac0ac46349f9a1672a75df1eee1adf05 (diff)
downloadsrc-test2-79d6ca331ec02d76c58383803148333576e6ddd8.tar.gz
src-test2-79d6ca331ec02d76c58383803148333576e6ddd8.zip
Notes
-rw-r--r--sys/amd64/vmm/io/vatpit.c74
-rw-r--r--sys/amd64/vmm/io/vatpit.h3
-rw-r--r--sys/amd64/vmm/vmm_ioport.c1
-rw-r--r--usr.sbin/bhyve/pci_lpc.c18
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("}");
}