Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Dec 2014 04:12:39 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r276447 - stable/10/sys/amd64/vmm/io
Message-ID:  <201412310412.sBV4Cd1S082706@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Wed Dec 31 04:12:38 2014
New Revision: 276447
URL: https://svnweb.freebsd.org/changeset/base/276447

Log:
  MFC r276323
  Implement "special mask mode" in vatpic.

Modified:
  stable/10/sys/amd64/vmm/io/vatpic.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/amd64/vmm/io/vatpic.c
==============================================================================
--- stable/10/sys/amd64/vmm/io/vatpic.c	Wed Dec 31 04:11:29 2014	(r276446)
+++ stable/10/sys/amd64/vmm/io/vatpic.c	Wed Dec 31 04:12:38 2014	(r276447)
@@ -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?201412310412.sBV4Cd1S082706>