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("}");
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to