home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / unix / bsd / 11799 < prev    next >
Encoding:
Text File  |  1993-01-25  |  8.7 KB  |  257 lines

  1. Newsgroups: comp.unix.bsd
  2. Path: sparky!uunet!europa.asd.contel.com!emory!swrinde!cs.utexas.edu!news.uta.edu!utacfd.uta.edu!rwsys!sneaky!gordon
  3. From: gordon@sneaky.lonestar.org (Gordon Burditt)
  4. Subject: [386bsd] gdb and 386bsd vs. floating point problems (+gdb patches)
  5. Message-ID: <C1EH04.45M@sneaky.lonestar.org>
  6. Organization: Gordon Burditt
  7. Date: Mon, 25 Jan 1993 08:02:23 GMT
  8. Lines: 247
  9.  
  10. Is anyone else having terrible floating point problems on 386bsd?
  11. I'm running on a 486DX/33, so the coprocessor is built in.
  12. I seem to be getting npx stack-underflow faults, in contexts where it
  13. makes absolutely no sense to be getting them ( e.g. fldl 16(%ebp);
  14. faddl 44(%ebp); fstpl 24(%ebp), and I get a stack-empty fault on the
  15. fstpl instruction.  Breaking npxprobe() to make it not recognize
  16. the coprocessor and using the math emulator instead makes the program 
  17. run VERY slowly but it works.  The math emulator doesn't seem to 
  18. do stack underflow faults.
  19.  
  20. A certain program I'm trying to port keeps dying on SIGFPEs.  It's a
  21. client of a server program run on the same machine, and so far only the
  22. client gets the SIGFPEs, although both use floating-point, and there's
  23. a lot of context-switching going on also.  So I get out gdb, and the 
  24. first thing I discover is that gdb doesn't do anything useful when you 
  25. ask for a stack trace, and complains about "Operation not permitted".  
  26. I discover that the user virtual address for the stack end is not a 
  27. constant, so I fix gdb to properly access the stack in core dumps:
  28.  
  29. Index: /usr/src/usr.bin/gdb/config/i386bsd-dep.c
  30. ***************
  31. *** 942,947 ****
  32. --- 942,957 ----
  33.            */
  34.           reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
  35.   #else
  36. +         /*
  37. +          * 386bsd does not put the stack end in a fixed virtual
  38. +          * location, so we get the beginning and depend on the
  39. +          * MAXSSIZ constant for the full length of the stack to
  40. +          * find the end.
  41. +          * (See code & comments in kern_execve.c, search for USRSTACK)
  42. +          */
  43. +         stack_end = (CORE_ADDR) u.u_kproc.kp_eproc.e_vm.vm_maxsaddr 
  44. +             + MAXSSIZ;
  45.           data_end = data_start +
  46.               NBPG * u.u_kproc.kp_eproc.e_vm.vm_dsize;
  47.           stack_start = stack_end -
  48.  
  49. Ok, now I can get a stack trace.  The SIGFPEs seem to be coming at random
  50. places all over the code.  Further, getting an assembly file for the problem
  51. code, adding "fwait" instructions before and after every floating-point
  52. instruction, assembling it, and testing the new code doesn't change anything.
  53.  
  54. "info float" in gdb doesn't do anything.  The code is conditionalled out.
  55. So I fixed it.  Well, this is a bit kludgey, and I'd love to have someone 
  56. point out a mistake so that the problem really isn't as wierd as it seems,
  57. but it seems to work.  I couldn't figure out where to get an exception
  58. status value in addition to the stored one.  There are some fundamental
  59. disagreements between the original code and my reading of Intel manuals 
  60. regarding the order of floating-point registers saved by fsave/fnsave.
  61. Nothing but code in gdb seems to care, though.
  62.  
  63. Index: /usr/src/usr.bin/gdb/config/i386bsd-dep.c
  64. ***************
  65. *** 1758,1771 ****
  66.     
  67.     top = (ep->status >> 11) & 7;
  68.     
  69. !   printf ("regno  tag  msb              lsb  value\n");
  70. !   for (fpreg = 7; fpreg >= 0; fpreg--) 
  71.       {
  72.         double val;
  73.         
  74. !       printf ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
  75.         
  76. !       switch ((ep->tag >> (fpreg * 2)) & 3) 
  77.       {
  78.       case 0: printf ("valid "); break;
  79.       case 1: printf ("zero  "); break;
  80. --- 1758,1773 ----
  81.     
  82.     top = (ep->status >> 11) & 7;
  83.     
  84. !   printf ("regno    tag  msb              lsb  value\n");
  85. !   for (fpreg = 0; fpreg <= 7; fpreg++) 
  86.       {
  87.         double val;
  88.         
  89. !       printf ("%s ST%d: ", ((fpreg+top)&7) == 7 ? "=>" : "  ", fpreg);
  90.         
  91. !       /* according to Intel 486 documentation, the registers are stored */
  92. !       /* in LOGICAL order but the tag bits correspond to PHYSICAL registers */
  93. !       switch ((ep->tag >> (((top + fpreg)&7) * 2)) & 3) 
  94.       {
  95.       case 0: printf ("valid "); break;
  96.       case 1: printf ("zero  "); break;
  97. ***************
  98. *** 1787,1792 ****
  99. --- 1789,1804 ----
  100.     if (ep->r3)
  101.       printf ("warning: reserved3 is 0x%x\n", ep->r3);
  102.   }
  103. + #ifdef __386BSD__
  104. + /* 
  105. +  * 386BSD name for saved fpu state. This had better have the same
  106. +  * layout as the env387 struct.  Note that the size of struct fpacc87
  107. +  * in <machine/npx.h> is actually wrong, due to struct padding, but
  108. +  * the data layout seems to be correct anyway.
  109. +  */
  110. + #define U_FPSTATE(u) u.u_pcb.pcb_savefpu
  111. + #define fpstate save87
  112. + #endif
  113.   
  114.   #ifndef U_FPSTATE
  115.   #define U_FPSTATE(u) u.u_fpstate
  116. ***************
  117. *** 1798,1823 ****
  118. --- 1810,1851 ----
  119.     int i;
  120.   #ifndef __386BSD__
  121.     /* fpstate defined in <sys/user.h> */
  122. + #else
  123. +   /* save87 defined in <machine/npx.h> */
  124. + #endif
  125.     struct fpstate *fpstatep;
  126.     char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
  127.     unsigned int uaddr;
  128. + #ifndef __386BSD__
  129.     char fpvalid;
  130. + #else
  131. +   int fpvalid;
  132. + #endif
  133.     unsigned int rounded_addr;
  134.     unsigned int rounded_size;
  135.     extern int corechan;
  136.     int skip;
  137.     
  138. + #ifndef __386BSD__
  139.     uaddr = (char *)&u.u_fpvalid - (char *)&u;
  140. + #else
  141. +   uaddr = (char *)&u.u_pcb.pcb_flags - (char *)&u;
  142. + #endif
  143.     if (have_inferior_p()) 
  144.       {
  145.         unsigned int data;
  146.         unsigned int mask;
  147.         
  148. + #ifndef __386BSD__
  149.         rounded_addr = uaddr & -sizeof (int);
  150.         data = ptrace (3, inferior_pid, rounded_addr, 0);
  151.         mask = 0xff << ((uaddr - rounded_addr) * 8);
  152.         
  153.         fpvalid = ((data & mask) != 0);
  154. + #else
  155. +       data = ptrace(3, inferior_pid, (caddr_t)uaddr, 0);
  156. +       fpvalid = (data & FP_WASUSED) != 0;
  157. + #endif
  158.       } 
  159.     else 
  160.       {
  161. ***************
  162. *** 1825,1831 ****
  163.       perror ("seek on core file");
  164.         if (myread (corechan, &fpvalid, 1) < 0) 
  165.       perror ("read on core file");
  166. !       
  167.       }
  168.     
  169.     if (fpvalid == 0) 
  170. --- 1853,1861 ----
  171.       perror ("seek on core file");
  172.         if (myread (corechan, &fpvalid, 1) < 0) 
  173.       perror ("read on core file");
  174. ! #ifdef __386BSD__
  175. !     fpvalid = (fpvalid & FP_WASUSED) != 0;      
  176. ! #endif
  177.       }
  178.     
  179.     if (fpvalid == 0) 
  180. ***************
  181. *** 1847,1853 ****
  182.         ip = (int *)buf;
  183.         for (i = 0; i < rounded_size; i++) 
  184.       {
  185. !       *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
  186.         rounded_addr += sizeof (int);
  187.       }
  188.       } 
  189. --- 1877,1883 ----
  190.         ip = (int *)buf;
  191.         for (i = 0; i < rounded_size; i++) 
  192.       {
  193. !       *ip++ = ptrace (3, inferior_pid, (caddr_t)rounded_addr, 0);
  194.         rounded_addr += sizeof (int);
  195.       }
  196.       } 
  197. ***************
  198. *** 1861,1866 ****
  199. --- 1891,1900 ----
  200.       }
  201.     
  202.     fpstatep = (struct fpstate *)(buf + skip);
  203. + # ifdef __386BSD__
  204. +   /* not sure where to get exception status */
  205. +   print_387_status (0, (struct env387 *)fpstatep);
  206. + #else
  207.     print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
  208.   #endif
  209.   }
  210.  
  211. Ok, now I can see what happens when I get a SIGFPE.  Invariably the
  212. exceptions shown are INVALID, LOS, and FSTACK, and the stack is shown
  213. as empty.  The address of the last npx exception is often 0, but sometimes
  214. it shows the address of an instruction that's actually in my code.
  215.  
  216. Ok, so why am I getting these exceptions?  I can think of several
  217. reasons:
  218.  
  219. - Flakey hardware.  It's fairly new hardware, but there might be problems
  220.   with it.  It's a 486DX, though, so there's less a motherboard manufacturer
  221.   can goof up than if they were wiring a 386 and 387 together.
  222. - Flakey code generation by gcc.  Well, when I see code like:
  223.  
  224.     fldl 16(%ebp)
  225.     faddl 44(%ebp)
  226.     fstpl 24(%ebp)
  227.     fwait
  228.     ...
  229.  
  230. if I'm going to get an exception from the fstp (why? - the stack should
  231. have something on it), shouldn't I get the exception at the fwait
  232. or before (486 eip, not npx exception address), NOT dozens to hundreds 
  233. of instructions later?  And what's wrong with this code, anyway?  There 
  234. should be something on the stack.
  235.  
  236. - Flakey library code.  I suspected for a while that library code was
  237.   doing "fninit" instructions when it shouldn't, but I think I have
  238.   isolated the problem to exclude library code.
  239.  
  240. - Flakey OS floating point save/restore code.  I suspect this the most,
  241.   but I haven't been able to prove it.  I've tried putting fwait 
  242.   instructions around just about every floating-point instruction
  243.   in the kernel, and nothing makes much difference.  (If you do an
  244.   frstor, which starts saving the context, and yank the address space
  245.   out from under the npx by re-loading control register 3 or doing
  246.   a task switch, don't you NEED an fwait first?  There isn't one.  But 
  247.   fixing it doesn't change the problem.)  I tried setting the 486 NE 
  248.   bit in control register 0.  No change.  I'm still wondering what 
  249.   those outb calls for ports 0xb1 and 0xf0 do.
  250.  
  251. - Flakey debugger.  If my fixes to "info float" don't do what I think
  252.  they do, the problem might be something entirely different.
  253.  
  254.                         Gordon L. Burditt
  255.                         sneaky.lonestar.org!gordon
  256.