svn commit: r264631 - in head: sys/amd64/vmm sys/amd64/vmm/io usr.sbin/bhyve

Tycho Nightingale tychon at FreeBSD.org
Fri Apr 18 00:02:08 UTC 2014


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("}");
 }
 


More information about the svn-src-head mailing list