Author: neel
Date: Sun Dec 28 00:53:52 2014
New Revision: 276323
URL: https://svnweb.freebsd.org/changeset/base/276323

Log:
  Implement "special mask mode" in vatpic.
  
  OpenBSD guests always enable "special mask mode" during boot. As a result of
  r275952 this is flagged as an error and the guest cannot boot.
  
  Reviewed by:  grehan
  Differential Revision:        https://reviews.freebsd.org/D1384
  MFC after:    1 week

Modified:
  head/sys/amd64/vmm/io/vatpic.c

Modified: head/sys/amd64/vmm/io/vatpic.c
==============================================================================
--- head/sys/amd64/vmm/io/vatpic.c      Sat Dec 27 23:19:08 2014        
(r276322)
+++ head/sys/amd64/vmm/io/vatpic.c      Sun Dec 28 00:53:52 2014        
(r276323)
@@ -73,6 +73,7 @@ struct atpic {
        uint8_t         request;        /* Interrupt Request Register (IIR) */
        uint8_t         service;        /* Interrupt Service (ISR) */
        uint8_t         mask;           /* Interrupt Mask Register (IMR) */
+       uint8_t         smm;            /* special mask mode */
 
        int             acnt[8];        /* sum of pin asserts and deasserts */
        int             lowprio;        /* lowest priority irq */
@@ -131,8 +132,16 @@ vatpic_get_highest_isrpin(struct atpic *
        ATPIC_PIN_FOREACH(pin, atpic, i) {
                 bit = (1 << pin);
 
-               if (atpic->service & bit)
-                       return (pin);
+               if (atpic->service & bit) {
+                       /*
+                        * An IS bit that is masked by an IMR bit will not be
+                        * cleared by a non-specific EOI in Special Mask Mode.
+                        */
+                       if (atpic->smm && (atpic->mask & bit) != 0)
+                               continue;
+                       else
+                               return (pin);
+               }
        }
 
        return (-1);
@@ -153,6 +162,15 @@ vatpic_get_highest_irrpin(struct atpic *
        if (atpic->sfn)
                serviced &= ~(1 << 2);
 
+       /*
+        * In 'Special Mask Mode', when a mask bit is set in OCW1 it inhibits
+        * further interrupts at that level and enables interrupts from all
+        * other levels that are not masked. In other words the ISR has no
+        * bearing on the levels that can generate interrupts.
+        */
+       if (atpic->smm)
+               serviced = 0;
+
        ATPIC_PIN_FOREACH(pin, atpic, tmp) {
                bit = 1 << pin;
 
@@ -261,6 +279,7 @@ vatpic_icw1(struct vatpic *vatpic, struc
        atpic->lowprio = 7;
        atpic->rd_cmd_reg = 0;
        atpic->poll = 0;
+       atpic->smm = 0;
 
        if ((val & ICW1_SNGL) != 0) {
                VATPIC_CTR0(vatpic, "vatpic cascade mode required");
@@ -375,8 +394,10 @@ vatpic_ocw3(struct vatpic *vatpic, struc
        VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val);
 
        if (val & OCW3_ESMM) {
-               VATPIC_CTR0(vatpic, "atpic special mask mode not implemented");
-               return (-1);
+               atpic->smm = val & OCW3_SMM ? 1 : 0;
+               VATPIC_CTR2(vatpic, "%s atpic special mask mode %s",
+                   master_atpic(vatpic, atpic) ? "master" : "slave",
+                   atpic->smm ?  "enabled" : "disabled");
        }
 
        if (val & OCW3_RR) {
_______________________________________________
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