Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Feb 2006 09:02:49 -0800 (PST)
From:      Cy Schubert <cy@FreeBSD.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   i386/92977: virutal infinite loop in identcpu.c
Message-ID:  <200602071702.k17H2nVW048924@cwsys.cwsent.com>
Resent-Message-ID: <200602071710.k17HA3c2001299@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         92977
>Category:       i386
>Synopsis:       virutal infinite loop in identcpu.c
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-i386
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Feb 07 17:10:03 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Cy Schubert
>Release:        FreeBSD-2.0
>Organization:
FreeBSD
>Environment:
System: FreeBSD cwsys 7.0-CURRENT FreeBSD 7.0-CURRENT #0: Fri Jan 27 13:49:18 PST 2006 root@cwsys:/export/obj/opt/src/cvs-current/src/sys/GENERIC


>Description:
 I'm experiencing the following hang on my -CURRENT testbed (which also 
 serves as a 4.11, 5.4, and 6.0 testbed). Only under 7.0-CURRENT does it 
 hang during boot using a stock out of the box GENERIC kernel. The machine 
 is an old P120. Any ideas?
 
 OK include /boot/cwtest/foobar
 |
 
 cwtest.foobar loader file selected
 unload complete
 currdev set to disk2s1a:
 /boot/kernel/kernel text=0x4e15c4 data=0x84900+0xa026c 
 syms=[0x4+0x67ea0+0x4+0x7f4ff]
 new kernel has been loaded
 
 OK boot -s
 GDB: no debug ports present
 KDB: debugger backends: ddb
 KDB: current backend: ddb
 Copyright (c) 1992-2006 The FreeBSD Project.
 Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
         The Regents of the University of California. All rights reserved.
 FreeBSD 7.0-CURRENT #0: Fri Jan 27 13:49:18 PST 2006
     root@cwsys:/export/obj/opt/src/cvs-current/src/sys/GENERIC
 WARNING: WITNESS option enabled, expect reduced performance.
 
 At this point I need to reset the machine.
precise description of the problem (multiple lines)>
>How-To-Repeat:
 See description.
>Fix:

I identified the problem (see my original discussion about this in attached 
the email below).

On the Pentium P54C model (that's an old 120 MHz Pentium I use as a 4.x, 
5.x, and 7.x ports build testbed) the CPUID instruction when called with AL 
= 0x02, CPUID returns EAX = EBX = ECX = EDX = 0. The code fragment in 
identcpu.c below results in "rounds" becoming 0xffffffff.

	do_cpuid(0x2, regs);
	rounds = (regs[0] & 0xff) - 1;

The subsequent loop of the following will loop virtually for ever (it takes 
forever tor this machine to count down from 0xffffffff performing a very 
great many calls to get_INTEL_TLB in the process, virtually hanging the 
machine in the process.

	while (rounds > 0) {
		[... code ...]
		rounds--;
	}

To resolve my problem I cobbled up the following patch to identcpu.c:

--- sys/i386/i386/identcpu.c.orig	Thu Feb  2 04:44:09 2006
+++ sys/i386/i386/identcpu.c	Mon Feb  6 18:47:16 2006
@@ -1237,7 +1237,7 @@
 
 	do_cpuid(0x2, regs);
 
-	rounds = (regs[0] & 0xff) - 1;
+	rounds = (regs[0] & 0xff);
 
 	for (regnum = 0; regnum <= 3; ++regnum) {
 		if ((regs[regnum] & (1<<31)) == 0) {
@@ -1249,7 +1249,7 @@
 		}
 	}
 
-	while (rounds > 0) {
+	while (rounds > 1) {
 		do_cpuid(0x2, regs);
 
 		for (regnum = 0; regnum <= 3; ++regnum) {
@@ -1452,7 +1452,7 @@
 	u_int nwaycode;
 
 	do_cpuid(0x2, regs);
-	rounds = (regs[0] & 0xff) - 1;
+	rounds = (regs[0] & 0xff);
 
 	for (regnum = 0; regnum <= 3; ++regnum) {
 		if ((regs[regnum] & (1<<31)) == 0) {
@@ -1468,7 +1468,7 @@
 		}
 	}
 
-	while (rounds > 0) {
+	while (rounds > 1) {
 		do_cpuid(0x2, regs);
 
 		for (regnum = 0; regnum <= 3; ++regnum) {

It fixes the hang.



>Release-Note:
>Audit-Trail:
>Unformatted:



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