NetBSD Problem Report #36578

From woods@building.weird.com  Fri Jun 29 19:28:28 2007
Return-Path: <woods@building.weird.com>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by narn.NetBSD.org (Postfix) with ESMTP id 230F963B882
	for <gnats-bugs@gnats.netbsd.org>; Fri, 29 Jun 2007 19:28:28 +0000 (UTC)
Message-Id: <m1I4M8p-002IwcC@building.weird.com>
Date: Fri, 29 Jun 2007 15:28:27 -0400 (EDT)
From: "Greg A. Woods" <woods@planix.com>
Sender: "Greg A. Woods" <woods@building.weird.com>
Reply-To: "Greg A. Woods" <woods@planix.com>
To: gnats-bugs@NetBSD.org
Subject: system may not actually halt if serial console is on a slow device
X-Send-Pr-Version: 3.95

>Number:         36578
>Category:       port-i386
>Synopsis:       system may not actually halt if serial console is on a slow device
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    port-i386-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jun 29 19:30:00 +0000 2007
>Last-Modified:  Sat Jun 30 00:20:01 +0000 2007
>Originator:     Greg A. Woods
>Release:        netbsd-4
>Organization:
Planix, Inc.; Toronto, Ontario; Canada
>Environment:


System: NetBSD 4.0BETA2
Architecture: i386
Machine: i386
>Description:

	If the system console is a serial console, and if the device it
	is connected to is using software flow control (XOFF) and that
	device is too slow to accept the ".... Please press any key to
	reoot." message then the system will read the the first XOFF
	character from the UART buffer and reboot instantly instead of
	staying halted as was requested.

>How-To-Repeat:

	See the thread starting here:

		http://mail-index.NetBSD.org/port-i386/2007/06/13/0000.html

	and in particular:

		http://mail-index.NetBSD.org/port-i386/2007/06/29/0003.html

>Fix:

Index: sys/arch/i386/i386/machdep.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.586.2.4
diff -u -r1.586.2.4 machdep.c
--- sys/arch/i386/i386/machdep.c	20 Apr 2007 20:31:25 -0000	1.586.2.4
+++ sys/arch/i386/i386/machdep.c	29 Jun 2007 19:20:14 -0000
@@ -870,6 +870,7 @@
 void
 cpu_reboot(int howto, char *bootstr)
 {
+	int keyval = 0;

 	if (cold) {
 		howto |= RB_HALT;
@@ -888,7 +889,7 @@
 			resettodr();
 	}

-	/* Disable interrupts. */
+	/* block interrupts. */
 	splhigh();

 	/* Do a dump if requested. */
@@ -927,11 +928,10 @@
 	}

 	if (howto & RB_HALT) {
-		printf("\n");
-		printf("The operating system has halted.\n");
-		printf("Please press any key to reboot.\n\n");
+		printf("\nThe operating system has halted.\n"
+		       "Please press any key to reboot.\n\n");

-#ifdef BEEP_ONHALT
+#ifdef BEEP_ONHALT /* XXX could be:  defined(BEEP_ONHALT_COUNT) && (BEEP_ONHALT_COUNT > 0) */
 		{
 			int c;
 			for (c = BEEP_ONHALT_COUNT; c > 0; c--) {
@@ -944,21 +944,49 @@
 		}
 #endif

-		cnpollc(1);	/* for proper keyboard command handling */
-		if (cngetc() == 0) {
-			/* no console attached, so just hlt */
-			for(;;) {
-				__asm volatile("hlt");
+		cnpollc(1);	/* for proper keyboard command handling without
+				 * interrupts */
+		/*
+		 * ACK!!!  The line discipline does _NOT_ get used from within
+		 * the kernel for console I/O (though it probably should be).
+		 *
+		 * If any output above went out too fast for the device
+		 * connected to a serial console then we'll read a <CTRL-S>
+		 * here, and we'll just have to ignore it.
+		 */
+#define ASCII_XOFF	0x13
+		while (keyval != ASCII_XOFF) {
+			if ((keyval = cngetc()) == 0) {
+				/* no console attached, so just hlt */
+				printf("\nCannot read from the console, calling the HLT instruction.\n\n");
+				for (;;) {
+					__asm volatile("hlt");
+				}
+				/*NOTREACHED*/
+			}
+#ifdef DEBUG
+			else if (keyval == ASCII_XOFF) {
+				printf("(ignoring XOFF keypress (DC3, aka 0x%x)\n", keyval);
+				/* XXX even this could trigger another XOFF, sigh... */
 			}
+#endif
 		}
 		cnpollc(0);
 	}

+#ifdef DEBUG
+	if (keyval)
+		printf("(read key value 0x%x)\n\n", keyval);
+#endif
 	printf("rebooting...\n");
 	if (cpureset_delay > 0)
 		delay(cpureset_delay * 1000);
 	cpu_reset();
-	for(;;) ;
+	printf("cpu_reset() returned, waiting for hardware to reset...\n\n");
+
+	for (;;) {
+		__asm volatile("hlt");
+	}
 	/*NOTREACHED*/
 }


>Audit-Trail:
From: "Greg A. Woods" <woods@planix.com>
To: NetBSD GNATS <gnats-bugs@NetBSD.org>
Cc: 
Subject: Re: port-i386/36578: system may not actually halt if serial console is on a slow device
Date: Fri, 29 Jun 2007 20:16:32 -0400

 Of course one must ignore XON too, as it's very likely to follow XOFF:

 Index: sys/arch/i386/i386/machdep.c
 ===================================================================
 RCS file: /cvs/master/m-NetBSD/main/src/sys/arch/i386/i386/machdep.c,v
 retrieving revision 1.586.2.4
 diff -u -r1.586.2.4 machdep.c
 --- sys/arch/i386/i386/machdep.c	20 Apr 2007 20:31:25 -0000	1.586.2.4
 +++ sys/arch/i386/i386/machdep.c	30 Jun 2007 00:13:32 -0000
 @@ -870,6 +870,7 @@
  void
  cpu_reboot(int howto, char *bootstr)
  {
 +	int keyval = 0;

  	if (cold) {
  		howto |= RB_HALT;
 @@ -888,7 +889,7 @@
  			resettodr();
  	}

 -	/* Disable interrupts. */
 +	/* block interrupts. */
  	splhigh();

  	/* Do a dump if requested. */
 @@ -921,17 +922,16 @@
  		apm_set_powstate(NULL, APM_DEV_ALLDEVS, APM_SYS_OFF);
  		printf("WARNING: APM powerdown failed!\n");
  		/*
 -		 * RB_POWERDOWN implies RB_HALT... fall into it...
 +		 * RB_POWERDOWN includes RB_HALT... fall into it...
  		 */
  #endif
  	}

  	if (howto & RB_HALT) {
 -		printf("\n");
 -		printf("The operating system has halted.\n");
 -		printf("Please press any key to reboot.\n\n");
 +		printf("\nThe operating system has halted.\n"
 +		       "Please press any key to reboot.\n\n");

 -#ifdef BEEP_ONHALT
 +#ifdef BEEP_ONHALT /* XXX could be:  defined(BEEP_ONHALT_COUNT) && (BEEP_ONHALT_COUNT > 0) */
  		{
  			int c;
  			for (c = BEEP_ONHALT_COUNT; c > 0; c--) {
 @@ -944,21 +944,51 @@
  		}
  #endif

 -		cnpollc(1);	/* for proper keyboard command handling */
 -		if (cngetc() == 0) {
 -			/* no console attached, so just hlt */
 -			for(;;) {
 -				__asm volatile("hlt");
 +		cnpollc(1);	/* for proper keyboard command handling without
 +				 * interrupts */
 +		/*
 +		 * ACK!!!  The line discipline does _NOT_ get used from within
 +		 * the kernel for console I/O (though it probably should be).
 +		 *
 +		 * If any output above went out too fast for the device
 +		 * connected to a serial console then we'll read a <CTRL-S>
 +		 * here, and/or perhaps a <CTRL-Q>, and we'll just have to
 +		 * ignore them.
 +		 */
 +#define ASCII_XON	0x11
 +#define ASCII_XOFF	0x13
 +		while (keyval != ASCII_XOFF && keyval != ASCII_XON) {
 +			if ((keyval = cngetc()) == 0) {
 +				/* no console attached, so just hlt */
 +				printf("\nCannot read from the console, calling the HLT instruction.\n\n");
 +				for (;;) {
 +					__asm volatile("hlt");
 +				}
 +				/*NOTREACHED*/
 +			}
 +#ifdef DEBUG
 +			else if (keyval == ASCII_XOFF && keyval != ASCII_XON) {
 +				printf("(ignoring flow control char (0x%x)\n", keyval);
 +				/* XXX even this could trigger another XOFF, sigh... */
  			}
 +#endif
  		}
  		cnpollc(0);
  	}

 +#ifdef DEBUG
 +	if (keyval)
 +		printf("(read key value 0x%x)\n\n", keyval);
 +#endif
  	printf("rebooting...\n");
  	if (cpureset_delay > 0)
  		delay(cpureset_delay * 1000);
  	cpu_reset();
 -	for(;;) ;
 +	printf("cpu_reset() returned, waiting for hardware to reset...\n\n");
 +
 +	for (;;) {
 +		__asm volatile("hlt");
 +	}
  	/*NOTREACHED*/
  }



 -- 
 						Greg A. Woods

 H:+1 416 218-0098 W:+1 416 489-5852 x122 VE3TCP RoboHack <woods@robohack.ca>
 Planix, Inc. <woods@planix.com>       Secrets of the Weird <woods@weird.com>

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.