Subject: 1.5_ALPHA2 Division by zero trap while writing to lfs file system.
To: None <tech-kern@netbsd.org>
From: Bruce Anderson <brucea@spacestar.net>
List: tech-kern
Date: 10/12/2000 02:29:51
My i386 machine has a dead RTC battery and while moving files (with pax)
to a new RaidFrame lfs file system mounted on root, I stumbled over
a division by zero problem in qdivrem.c.
After that I was unable to boot the system. "Bad" vnode dates in the
file system?
Here's a failed boot attempt:
NetBSD 1.5_ALPHA2 (TINY) #8: Tue Oct 9 16:13:21 CDT 2000
bruce@leopard:/usr/src/sys/arch/i386/compile/TINY
cpu0: Cyrix 6x86MX (686-class)
kernel: integer divide fault trap, code=0
Stopped in swapper at __qdivrem+0x26: divl %ecx,%eax
db> trace
__qdivrem(b5f46e8,0,0,0,0) at __qdivrem+0x26
__divdi3(b5f46e8,0,0,0) at __divdi3+0x38
lfs_statfs(c0487200,c0487244,c02a1320,c027be80,c02a1320) at lfs_statfs+0x9d
lfs_mountroot(ffffffff,c02e5fa8,c0167b1e,c02e3010,2e3000) at
lfs_mountroot+0xfa
vfs_mountroot(c02e3010,2e3000,2ea000,90,200007ff) at vfs_mountroot+0x9d
main(0,0,0,0,0) at main+0x45a
db> show registers
es 0xc02e0010 end+0x2c41c
ds 0xc0100010 kernel_text+0x10
edi 0
esi 0
ebp 0xc02e5ed4 end+0x322e0
ebx 0xb5f46e8
edx 0
ecx 0
eax 0x1
eip 0xc024365a __qdivrem+0x26
cs 0xc02a0008 rf_DiskUnlockFunc
eflags 0x10246
esp 0xc02e5e4c end+0x32258
ss 0xc0290010 kernel_map_entry.126+0x3290
__qdivrem+0x26: divl %ecx,%eax
In sys/lib/libkern/qdivrem.c
/* $NetBSD: qdivrem.c,v 1.7 1999/09/10 13:21:14 drochner Exp $ */
and src/lib/libc/quad/qdivrem.c
/* $NetBSD: qdivrem.c,v 1.10 2000/01/22 23:02:19 mycroft Exp $ */
-------------------------------------------------
/*
* Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
* section 4.3.1, pp. 257--259.
*/
-------------------------------------------------
u_quad_t
__qdivrem(uq, vq, arq)
u_quad_t uq, vq, *arq;
{
union uu tmp;
digit *u, *v, *q;
digit v1, v2;
u_long qhat, rhat, t;
int m, n, d, j, i;
digit uspace[5], vspace[5], qspace[5];
/*
* Take care of special cases: divide by zero, and u < v.
*/
if (vq == 0) {
/* divide by zero. */
static volatile const unsigned int zero = 0;
tmp.ul[H] = tmp.ul[L] = 1 / zero;
if (arq)
*arq = uq;
return (tmp.q);
}
if (uq < vq) {
if (arq)
*arq = uq;
return (0);
}
u = &uspace[0];
v = &vspace[0];
q = &qspace[0];
-------------------------------------------------
Is this division by zero deliberate or pseudo-code?
/* divide by zero. */
static volatile const unsigned int zero = 0;
tmp.ul[H] = tmp.ul[L] = 1 / zero;
To get my system to boot I changed this code to return
all bits set, wich should work for most machines that
use unsigned long integers:
===================================================================
RCS file: RCS/qdivrem.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** qdivrem.c 2000/10/10 20:14:37 1.1
--- qdivrem.c 2000/10/12 06:16:54 1.2
***************
*** 91,99 ****
*/
if (vq == 0) {
/* divide by zero. */
- static volatile const unsigned int zero = 0;
! tmp.ul[H] = tmp.ul[L] = 1 / zero;
if (arq)
*arq = uq;
return (tmp.q);
--- 91,98 ----
*/
if (vq == 0) {
/* divide by zero. */
! tmp.ul[H] = tmp.ul[L] = ~0;
if (arq)
*arq = uq;
return (tmp.q);
" Stamp out root logins . . . . su " --Bruce Anderson
This message was created and sent using Cyberdog 2.0, MacOS 8.6,
awk, find, sed, sendmail, sh, and NetBSD a free Multi-Platform OS.