Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Dec 2014 00:53:53 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r276323 - head/sys/amd64/vmm/io
Message-ID:  <201412280053.sBS0rrEI009562@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412280053.sBS0rrEI009562>