NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

port-mac68k/60722: mac68k: enable_nubus_intr() tests six bits where the rest of via.c uses seven



>Number:         60722
>Category:       port-mac68k
>Synopsis:       mac68k: enable_nubus_intr() tests six bits where the rest of via.c uses seven
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-mac68k-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Sep 13 05:00:01 +0000 2026
>Originator:     Ray Tran
>Release:        11.0
>Organization:
Diamond Creek Digital
>Environment:
Centris 650 running NetBSD 11.0 / current kernel with no NuBus cards
>Description:
sys/arch/mac68k/mac68k/via.c keeps seven NuBus slot handlers, for slots
9 through 15.  Slot 15 is not a real slot: the file's own header says so,

	 * Nubus slot interrupt routines and parameters for slots 9-15.
	 * Note that for simplicity of code, "v2IRQ0" for internal video
	 * is treated as a slot 15 interrupt; this slot is quite
	 * fictitious in real-world Macs.

and slotitab[]'s seventh and last entry carries the comment
"int_video_intr" to say what it is for.

Everything that walks those tables is seven bits wide.  add_nubus_intr()
sets bit (slot - 9), so slot 15 is bit 6.  via2_nubus_intr() and
rbv_nubus_intr() both start at i = 6 and count down.  oss_intr() masks
intbits with 0x7f.  enable_nubus_intr() is the exception:

	if ((nubus_intr_mask & 0x3f) == 0)
		return;

	if (VIA2 == VIA2OFF)
		via2_reg(vIER) = 0x80 | V2IF_SLOTINT;
	else
		via2_reg(rIER) = 0x80 | V2IF_SLOTINT;

0x3f is bits 0 through 5, slots 9 through 14, the six physical slots.
Bit 6 is missing, so a kernel whose only registered slot is 15 returns
without ever unmasking V2IF_SLOTINT.  The device asserts its line on
VIA2 port A bit 6 and holds it there; via2_nubus_intr() is never
entered, and the interrupt is silently lost forever.

Any NuBus card in a real slot hides this completely.  That driver's own
enable_nubus_intr() call has a bit inside 0x3f, unmasks the shared
V2IF_SLOTINT, and the slot 15 handler is dispatched along with it, since
via2_nubus_intr() loops over every bit in nubus_intr_mask.  The fault is
therefore visible only on a machine with an empty NuBus, and it looks
like a hardware or driver problem rather than a missing register write.

Nothing else takes a slot on such a machine.  Under the A/UX interrupt
scheme, which machdep.c selects for the Quadra and Centris class,
if_sn_obio.c attaches the built-in SONIC with intr_establish(..., 3) and
calls add_nubus_intr(SONIC_SLOTNO, ...) only on the other path.

The second caller of slot 15 in the tree meets the same wall from the
other side: wdc_obio.c registers add_nubus_intr(0xf, ...) for the
Quadra/Performa IDE interface and never calls enable_nubus_intr() at
all, so that interrupt likewise depends on some other driver having
unmasked the bit.  This change does not touch it; it is reported here
because it is the same assumption and someone with that hardware should
judge it.
>How-To-Repeat:
On a Quadra or Centris with nothing in the NuBus slots, register a
handler on slot 15, call enable_nubus_intr(), enable a source that
raises the internal-video interrupt, and count.  The count stays at
zero.  Add the one register write enable_nubus_intr() declined to make,

	via2_reg(vIER) = 0x80 | V2IF_SLOTINT;

and the same code counts the interrupt at its real rate.
>Fix:
One expression, and a comment saying why the width matters.  With it,
sys/arch/mac68k/mac68k/via.c reads

	if ((nubus_intr_mask & 0x7f) == 0)
		return;

nubus_intr_mask only ever holds bits 0 through 6, so testing the mask
against zero would do as well; 0x7f is written to match oss_intr() and
to keep the seven-bit intent visible at the point of the test.

The same patch applies to -current.

Applies with "patch -p1" from the top of usr/src; verified with -F0
(no fuzz) against NetBSD-current 11.99.8 (20260911135556Z) and 11.0.

--- a/sys/arch/mac68k/mac68k/via.c
+++ b/sys/arch/mac68k/mac68k/via.c
@@ -397,7 +397,18 @@
 void
 enable_nubus_intr(void)
 {
-	if ((nubus_intr_mask & 0x3f) == 0)
+	if ((nubus_intr_mask & 0x7f) == 0)
 		return;
 
 	if (VIA2 == VIA2OFF)




Home | Main Index | Thread Index | Old Index