Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Dec 2014 03:04:44 +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: r275850 - head/sys/amd64/vmm/io
Message-ID:  <201412170304.sBH34iD1085896@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Wed Dec 17 03:04:43 2014
New Revision: 275850
URL: https://svnweb.freebsd.org/changeset/base/275850

Log:
  Fix 8259 IRQ priority resolver.
  Initialize the 8259 such that IRQ7 is the lowest priority.
  
  Reviewed by:		tychon
  Differential Revision:	https://reviews.freebsd.org/D1322
  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	Wed Dec 17 01:48:32 2014	(r275849)
+++ head/sys/amd64/vmm/io/vatpic.c	Wed Dec 17 03:04:43 2014	(r275850)
@@ -75,7 +75,7 @@ struct atpic {
 	uint8_t		mask;		/* Interrupt Mask Register (IMR) */
 
 	int		acnt[8];	/* sum of pin asserts and deasserts */
-	int		priority;	/* current pin priority */
+	int		lowprio;	/* lowest priority irq */
 
 	bool		intr_raised;
 };
@@ -102,6 +102,14 @@ struct vatpic {
 #define	VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4)			\
 	VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4)
 
+/*
+ * Loop over all the pins in priority order from highest to lowest.
+ */
+#define	ATPIC_PIN_FOREACH(pinvar, atpic, tmpvar)			\
+	for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7;		\
+	    tmpvar < 8;							\
+	    tmpvar++, pinvar = (pinvar + 1) & 0x7)
+
 static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate);
 
 static __inline int
@@ -110,8 +118,7 @@ vatpic_get_highest_isrpin(struct atpic *
 	int bit, pin;
 	int i;
 
-	for (i = 0; i <= 7; i++) {
-		pin = ((i + 7 - atpic->priority) & 0x7);
+	ATPIC_PIN_FOREACH(pin, atpic, i) {
                 bit = (1 << pin);
 
 		if (atpic->service & bit)
@@ -125,8 +132,7 @@ static __inline int
 vatpic_get_highest_irrpin(struct atpic *atpic)
 {
 	int serviced;
-	int bit, pin;
-	int i, j;
+	int bit, pin, tmp;
 
 	/*
 	 * In 'Special Fully-Nested Mode' when an interrupt request from
@@ -137,17 +143,21 @@ vatpic_get_highest_irrpin(struct atpic *
 	if (atpic->sfn)
 		serviced &= ~(1 << 2);
 
-	for (i = 0; i <= 7; i++) {
-		pin = ((i + 7 - atpic->priority) & 0x7);
-		bit = (1 << pin);
-		if (serviced & bit)
+	ATPIC_PIN_FOREACH(pin, atpic, tmp) {
+		bit = 1 << pin;
+
+		/*
+		 * If there is already an interrupt in service at the same
+		 * or higher priority then bail.
+		 */
+		if ((serviced & bit) != 0)
 			break;
-	}
 
-	for (j = 0; j < i; j++) {
-		pin = ((j + 7 - atpic->priority) & 0x7);
-		bit = (1 << pin);
-		if (atpic->request & bit && (~atpic->mask & bit))
+		/*
+		 * If an interrupt is asserted and not masked then return
+		 * the corresponding 'pin' to the caller.
+		 */
+		if ((atpic->request & bit) != 0 && (atpic->mask & bit) == 0)
 			return (pin);
 	}
 
@@ -238,7 +248,7 @@ vatpic_icw1(struct vatpic *vatpic, struc
 
 	atpic->icw_num = 1;
 	atpic->mask = 0;
-	atpic->priority = 0;
+	atpic->lowprio = 7;
 	atpic->rd_cmd_reg = 0;
 
 	if ((val & ICW1_SNGL) != 0) {
@@ -329,11 +339,11 @@ vatpic_ocw2(struct vatpic *vatpic, struc
 			atpic->service &= ~(1 << isr_bit);
 
 			if (atpic->rotate)
-				atpic->priority = isr_bit;
+				atpic->lowprio = isr_bit;
 		}
 	} else if ((val & OCW2_SL) != 0 && atpic->rotate == true) {
 		/* specific priority */
-		atpic->priority = val & 0x7;
+		atpic->lowprio = val & 0x7;
 	}
 
 	return (0);
@@ -530,7 +540,7 @@ vatpic_pin_accepted(struct atpic *atpic,
 
 	if (atpic->aeoi == true) {
 		if (atpic->rotate == true)
-			atpic->priority = pin;
+			atpic->lowprio = pin;
 	} else {
 		atpic->service |= (1 << pin);
 	}



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