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.