i386/92977: virutal infinite loop in identcpu.c
Cy Schubert
cy at FreeBSD.org
Tue Feb 7 09:10:04 PST 2006
>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 at 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 at 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:
More information about the freebsd-i386
mailing list