Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Jan 2001 07:02:56 +0100
From:      Tor.Egge@fast.no
To:        sos@freebsd.dk
Cc:        jasone@canonware.com, current@FreeBSD.ORG
Subject:   Re: Debugging SMP instability (was Re: HEADS-UP: await/asleep removal imminent)
Message-ID:  <200101180602.HAA11429@midten.fast.no>
In-Reply-To: Your message of "Wed, 17 Jan 2001 20:35:24 %2B0100 (CET)"
References:  <200101171935.UAA25627@freebsd.dk>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Thu_Jan_18_07:01:01_2001)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

> Again I'll offer to run any and all code or patches to -current you
> guys can come up with, but I simply dont have the time to sit down
> and analyze into details what you have been doing...

The enclosed patch implements a virtual NMI pushbutton by programming
the IOAPIC to deliver an NMI when sio1 generates an interrupt.

DDB should be defined in the kernel config file.

getty should not run on ttyd1 when this patch is applied.

A serial console on sio0 is recommended.

If you still cannot break into the kernel debugger when the machine
locks up then a rogue device is probably blocking the system
(or the debugger is trying to obtain a mutex held by somebody else)

- Tor Egge



----Next_Part(Thu_Jan_18_07:01:01_2001)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Index: sys/i386/i386/mpapic.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/mpapic.c,v
retrieving revision 1.45
diff -u -r1.45 mpapic.c
--- sys/i386/i386/mpapic.c	2001/01/10 04:43:46	1.45
+++ sys/i386/i386/mpapic.c	2001/01/18 05:44:30
@@ -269,6 +269,41 @@
 	/* return GOOD status */
 	return 0;
 }
+
+
+void
+enable_sio_NMI(int irq) 
+{
+	u_char  select;      /* the select register is 8 bits */
+	u_int32_t flags;     /* the window register is 32 bits */
+	u_int32_t target;    /* the window register is 32 bits */
+	u_int32_t vector;    /* the window register is 32 bits */
+	int apic;
+	int pin;
+	
+	if (irq < 0 || irq > 15) {
+		printf("Could not enable NMI for irq %d\n", irq);
+		return;
+	}
+	apic = int_to_apicintpin[irq].ioapic; 
+	pin = int_to_apicintpin[irq].int_pin;
+
+	target = CPU_TO_ID(0) << 24;
+	select = IOAPIC_REDTBL0 + (2 * pin);
+	vector = TPR_FAST_INTS + irq;
+	flags =      ((u_int32_t)
+		      (IOART_INTMCLR |
+		       IOART_TRGREDG |
+		       IOART_INTAHI |
+		       IOART_DESTPHY |
+		       IOART_DELNMI));
+	
+	io_apic_write(apic, select, flags | vector);
+	io_apic_write(apic, select + 1, target);
+	printf("Enabled NMI for irq %d\n", irq);
+	printf("XXX IOAPIC #%d intpin %d ->irq %d vector 0x%x (Delivery mode NMI)\n",
+	       apic, pin, irq, vector);
+}
 #undef DEFAULT_ISA_FLAGS
 #undef DEFAULT_FLAGS
 
Index: sys/i386/i386/trap.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/trap.c,v
retrieving revision 1.164
diff -u -r1.164 trap.c
--- sys/i386/i386/trap.c	2001/01/10 04:43:46	1.164
+++ sys/i386/i386/trap.c	2001/01/18 05:44:30
@@ -248,7 +248,8 @@
 
 	atomic_add_int(&cnt.v_trap, 1);
 
-	if ((frame.tf_eflags & PSL_I) == 0) {
+	if ((frame.tf_eflags & PSL_I) == 0 &&
+		frame.tf_trapno != T_NMI) {
 		/*
 		 * Buggy application or kernel code has disabled
 		 * interrupts and then trapped.  Enabling interrupts
@@ -285,8 +286,38 @@
 		enable_intr();
 	}	
 
-	mtx_enter(&Giant, MTX_DEF);
+	if (frame.tf_trapno == T_NMI) {
+		/* If we can't get Giant then forward NMI to next CPU */
+		if (mtx_try_enter(&Giant, MTX_DEF) == 0) {
+			u_long	icr_lo;
+			u_long	icr_hi;
+			int target;
+
+			target = PCPU_GET(cpuid) + 1;
+			if (((1 << target) & PCPU_GET(other_cpus)) == 0)
+				target = 0;
+			
+			/* write the destination field for the target AP */
+			icr_hi = (lapic.icr_hi & ~APIC_ID_MASK) |
+				(cpu_num_to_apic_id[target] << 24);
+			lapic.icr_hi = icr_hi;
+			
+			/* write command */
+			icr_lo = (lapic.icr_lo & APIC_RESV2_MASK) |
+				APIC_DEST_DESTFLD | APIC_DELMODE_NMI | 0xff;
+			lapic.icr_lo = icr_lo;
+			
+			/* wait for pending status end */
+			while (lapic.icr_lo & APIC_DELSTAT_MASK)
+				/* spin */ ;
 
+			__asm __volatile("int $0xff");
+
+			return;
+		}
+	} else
+		mtx_enter(&Giant, MTX_DEF);
+
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
 restart:
 #endif
@@ -388,6 +419,9 @@
 				 */
 				if (ddb_on_nmi) {
 					printf ("NMI ... going to debugger\n");
+					sioEATintr();
+					__asm __volatile("int $0xff");
+					enable_intr();
 					kdb_trap (type, 0, &frame);
 				}
 #endif /* DDB */
@@ -617,6 +651,9 @@
 				 */
 				if (ddb_on_nmi) {
 					printf ("NMI ... going to debugger\n");
+					sioEATintr();
+					__asm __volatile("int $0xff");
+					enable_intr();
 					kdb_trap (type, 0, &frame);
 				}
 #endif /* DDB */
Index: sys/isa/sio.c
===================================================================
RCS file: /home/ncvs/src/sys/isa/sio.c,v
retrieving revision 1.321
diff -u -r1.321 sio.c
--- sys/isa/sio.c	2000/12/26 06:52:57	1.321
+++ sys/isa/sio.c	2001/01/18 05:44:30
@@ -439,6 +439,17 @@
 	{ -1,		-1 }
 };
 
+#define DDB_BREAK_MASK (IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC)
+#define DDB_NMI
+
+#ifdef TRIPLE_BREAK_TO_DEBUGGER
+#ifndef TRIPLE_BREAK_TIMEOUT
+#define TRIPLE_BREAK_TIMEOUT 10
+#endif
+int triple_break_count;		/* number of breaks detected */
+int triple_break_time;		/* time_second sampled at first break */
+#endif
+
 #ifdef COM_ESP
 /* XXX configure this properly. */
 static	Port_t	likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
@@ -1179,6 +1190,33 @@
 		com->lt_out.c_ispeed = com->lt_out.c_ospeed =
 		com->lt_in.c_ispeed = com->lt_in.c_ospeed =
 		com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
+#if defined(DDB) && defined(BREAK_TO_DEBUGGER) && defined(DDB_BREAK_MASK)
+		outb(iobase + com_ier, DDB_BREAK_MASK);
+#endif
+#if defined(DDB) && defined(DDB_BREAK_MASK) && defined(DDB_NMI)
+	} else if (unit == 1) {
+		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
+		com->it_in.c_iflag = TTYDEF_IFLAG;
+		com->it_in.c_oflag = TTYDEF_OFLAG;
+		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
+		com->it_in.c_lflag = TTYDEF_LFLAG;
+		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
+		com->lt_out.c_ispeed = com->lt_out.c_ospeed =
+			com->lt_in.c_ispeed = com->lt_in.c_ospeed =
+			com->it_in.c_ispeed = com->it_in.c_ospeed = 
+			comdefaultrate;
+		(void) inb(com->line_status_port);
+		(void) inb(com->data_port);
+		com->prev_modem_status = com->last_modem_status
+			= inb(com->modem_status_port);
+		if (COM_IIR_TXRDYBUG(com->flags)) {
+			outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
+			     | IER_EMSC);
+		} else {
+			outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
+			     | IER_ERLS | IER_EMSC);
+		}
+#endif
 	} else
 		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
 	if (siosetwater(com, com->it_in.c_ispeed) != 0) {
@@ -1355,10 +1393,56 @@
 		if (ret)
 			device_printf(dev, "could not activate interrupt\n");
 	}
+#if defined(DDB) && defined(DDB_BREAK_MASK) && defined(DDB_NMI) && defined(APIC_IO)
+	if (unit == 1) {
+		u_long xirq;
+		if (bus_get_resource(dev, SYS_RES_IRQ, 0, &xirq, NULL) == 0) {
+			printf("XXX: sio1 irq is %lu\n", xirq);
+			enable_sio_NMI(xirq);
+		}
+	}
+#endif
 
 	return (0);
 }
 
+
+void 
+sioEATintr(void)
+{
+	struct com_s *com;
+	u_char line_status;
+	u_char modem_status;
+	u_char recv_data;
+	u_char int_ctl;
+	u_char int_id;
+	
+	com = com_addr(1);
+	if (com == NULL)
+		return;
+	
+	int_id = inb(com->int_id_port);
+	int_ctl = inb(com->intr_ctl_port);
+	while (1) {
+		line_status = inb(com->line_status_port);
+		while (line_status & LSR_RCV_MASK) {
+			if ((line_status & LSR_RXRDY) == 0)
+				recv_data = 0;
+			else
+				recv_data = inb(com->data_port);
+			if ((line_status &
+			     (LSR_BI | LSR_FE | LSR_PE)) != 0) {
+			}
+			line_status = inb(com->line_status_port);
+		}
+		modem_status = inb(com->modem_status_port);
+		int_id = inb(com->int_id_port);
+		if ((int_id & IIR_IMASK) == IIR_NOPEND)
+			break;
+	}
+}
+
+
 static int
 sioopen(dev, flag, mode, p)
 	dev_t		dev;
@@ -1596,7 +1680,12 @@
 	com->pps.ppsparam.mode = 0;
 	sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
 	{
-		sio_setreg(com, com_ier, 0);
+#if defined(DDB) && defined(BREAK_TO_DEBUGGER) && defined(DDB_BREAK_MASK)
+		if (com->unit == comconsole)
+			sio_setreg(com, com_ier, DDB_BREAK_MASK);
+		else
+#endif
+			sio_setreg(com, com_ier, 0);
 		tp = com->tp;
 		if (tp->t_cflag & HUPCL
 		    /*
@@ -1946,7 +2035,27 @@
 				if (line_status & LSR_BI) {
 #if defined(DDB) && defined(BREAK_TO_DEBUGGER)
 					if (com->unit == comconsole) {
+#ifdef TRIPLE_BREAK_TO_DEBUGGER
+						if (time_second > 
+						    triple_break_time + 
+						    TRIPLE_BREAK_TIMEOUT)
+							triple_break_count = 0;
+						triple_break_count++;
+						if (triple_break_count == 1)
+							triple_break_time = 
+								time_second;
+						else if (triple_break_count 
+							 == 3) {
+							triple_break_count = 0;
+							mtx_exit(&sio_lock, MTX_SPIN);
+							breakpoint();
+							mtx_enter(&sio_lock, MTX_SPIN);
+						}
+#else
+						mtx_exit(&sio_lock, MTX_SPIN);
 						breakpoint();
+						mtx_enter(&sio_lock, MTX_SPIN);
+#endif
 						goto cont;
 					}
 #endif

----Next_Part(Thu_Jan_18_07:01:01_2001)----


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




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