Subject: port-mips/26959: mips mc_cpuspeed() returns wrong value on gcc3
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 09/16/2004 00:16:06
>Number: 26959
>Category: port-mips
>Synopsis: mips mc_cpuspeed() returns wrong value on gcc3
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: port-mips-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Sep 15 15:17:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: Izumi Tsutsui
>Release: NetBSD 1.6ZE and later
>Organization:
>Environment:
NetBSD 1.6ZE
Architecture: mips
Machine: pmax
>Description:
pmax (and maybe some other mips ports) use mc_cpuspeed() and
mips_mcclock_tickloop() in mips_mccloc.c to determine their CPU clock,
but after gcc3 import mips_mcclock_tickloop() returns smaller values
at least on DECstation 5000/125.
In article <031223212041.M0103669@mirage.ceres.dti.ne.jp> on port-pmax
I wrote:
> BTW, I think mc_cpuspeed() in arch/mips/mips/mips_mcclock.c also
> might have some problem with gcc3. Kernels compiled by gcc3
> detect machine clock incorrectly on my 3MIN (5000/125):
>
> >> NetBSD 1.6ZD (PROUDIA) #29: Sun Oct 26 15:12:26 JST 2003
> >> tsutsui@mirage:/usr/src/sys/arch/pmax/compile/PROUDIA
> >> DECstation 5000/125 (3MIN)
> >> total memory = 98304 KB
> >> avail memory = 87980 KB
>
> >> NetBSD 1.6ZE (PROUDIA) #30: Mon Oct 27 02:03:15 JST 2003
> >> tsutsui@mirage:/usr/src/sys/arch/pmax/compile/PROUDIA
> >> DECstation 5000/120 (3MIN)
> >> total memory = 98304 KB
> >> avail memory = 88068 KB
The following iteration code is used to measure CPU clock
in mips_mcclock_tickloop():
---
while ((mips_cp0_cause_read() & clockmask) == 0) {
__asm __volatile ("nop; nop; nop; nop");
iters++;
}
---
gcc-2.95.3 generates:
---
j 2f
nop
1: nop # __asm __volatile (nop; ...);
nop
nop
nop
addiu s0, s0, 1 # iters++;
2: jal _C_LABEL(mips_cp0_cause_read) # v0 = mips_cp0_cause_read();
nop
and v0, v0, s1 # v0 & clockmask
beqz v0, 1b # if zero then repeat
move v0, s0 # for return (iters);
j 3f
nop
[...]
3:
---
In this case each iteration contains 10 instructions.
but gcc-3.3.3 generates deferent code:
---
1: jal _C_LABEL(mips_cp0_cause_read) # v0 = mips_cp0_cause_read();
nop
and v0, v0, s0 # v0 & clockmask
bnez v0, 2f # if !zero then break
nop
nop # __asm __volatile (nop; ...);
nop
nop
nop
j 1b
addiu s1, s1, 1 # iters++;
2: [...]
---
Each loop contains 11 instructions so it returns different iters
from the previous one.
>How-To-Repeat:
boot kernel on DECstation 5000/125 (and other pmaxen)
then the kernel shows wrong machine model name like the above.
>Fix:
An easy fix is to remove one dummy nop from __asm lines (as attached),
but I guess such code should not depend on compiler and should be
written in asm.
Index: mips/mips/mips_mcclock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/mips_mcclock.c,v
retrieving revision 1.11
diff -u -r1.11 mips_mcclock.c
--- mips/mips/mips_mcclock.c 5 Mar 2002 15:54:33 -0000 1.11
+++ mips/mips/mips_mcclock.c 15 Sep 2004 15:01:27 -0000
@@ -166,12 +166,12 @@
/* Count loops until next tick-interrupt request occurs (4ms). */
if (MIPS_HAS_CLOCK) {
while ((mips_cp0_cause_read() & clockmask) == 0) {
- __asm __volatile ("nop; nop; nop; nop");
+ __asm __volatile ("nop; nop; nop");
iters++;
}
} else {
while ((mips_cp0_cause_read() & clockmask) == 0) {
- __asm __volatile ("nop; nop;");
+ __asm __volatile ("nop;");
iters++;
}
}
>Release-Note:
>Audit-Trail:
>Unformatted: