home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / m68k / traps.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-09  |  15.1 KB  |  577 lines

  1. /*
  2.  *  linux/m68k/traps.c
  3.  *
  4.  *  Copyright (C) 1993, 1994 by Hamish Macdonald
  5.  *
  6.  *  68040 fixes by Michael Rausch
  7.  *
  8.  * This file is subject to the terms and conditions of the GNU General Public
  9.  * License.  See the file README.legal in the main directory of this archive
  10.  * for more details.
  11.  */
  12.  
  13. /*
  14.  * Sets up all exception vectors
  15.  */
  16.  
  17. #include <asm/system.h>
  18. #include <asm/segment.h>
  19. #include <linux/config.h>
  20. #include <linux/traps.h>
  21. #include <linux/sched.h>
  22. #include <linux/signal.h>
  23. #include <linux/kernel.h>
  24. #include <linux/mm.h>
  25. #include <linux/types.h>
  26. #include <linux/a.out.h>
  27. #include <linux/user.h>
  28. #include <linux/string.h>
  29. #include <linux/bootinfo.h>
  30.  
  31. /* assembler routines */
  32. asmlinkage void system_call(void);
  33. asmlinkage void buserr(void);
  34. asmlinkage void trap(void);
  35. asmlinkage void inthandler(void);
  36. asmlinkage void nmihandler(void);
  37.  
  38. e_vector vectors[256] = {
  39.     0, 0, buserr, trap, trap, trap, trap, trap,
  40.     trap, trap, trap, trap, trap, trap, trap, trap,
  41.     trap, trap, trap, trap, trap, trap, trap, trap,
  42.     inthandler, nmihandler, nmihandler, nmihandler,
  43.     inthandler, nmihandler, nmihandler, inthandler,
  44.     /* TRAP #0-15 */
  45.     system_call, trap, trap, trap, trap, trap, trap, trap,
  46.     trap, trap, trap, trap, trap, trap, trap, trap,
  47.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  48. };
  49.  
  50. /* nmi handler for the Amiga */
  51. asm(".text
  52.      _nmihandler: rte");
  53.  
  54. void trap_init (void)
  55. {
  56.     int i;
  57.  
  58.     /* setup the exception vector table */
  59.     __asm__ volatile ("movec %0,vbr" : : "r" ((void*)vectors));
  60.  
  61.     for (i = 112; i < 256; i++)
  62.         vectors[i] = trap; 
  63.  
  64.         /* if running on an amiga, make the NMI interrupt do nothing */
  65.         if (boot_info.machtype == MACH_AMIGA) {
  66.                 vectors[VEC_INT7] = nmihandler;
  67.         }
  68.                     
  69. #ifdef CONFIG_FPSP_040
  70.     if (boot_info.cputype & CPU_68040) {
  71.         /* set up FPSP entry points */
  72.         asmlinkage void dz_vec(void) asm ("dz");
  73.         asmlinkage void inex_vec(void) asm ("inex");
  74.         asmlinkage void ovfl_vec(void) asm ("ovfl");
  75.         asmlinkage void unfl_vec(void) asm ("unfl");
  76.         asmlinkage void snan_vec(void) asm ("snan");
  77.         asmlinkage void operr_vec(void) asm ("operr");
  78.         asmlinkage void bsun_vec(void) asm ("bsun");
  79.         asmlinkage void fline_vec(void) asm ("fline");
  80.         asmlinkage void unsupp_vec(void) asm ("unsupp");
  81.  
  82.         vectors[VEC_FPDIVZ] = dz_vec;
  83.         vectors[VEC_FPIR] = inex_vec;
  84.         vectors[VEC_FPOVER] = ovfl_vec;
  85.         vectors[VEC_FPUNDER] = unfl_vec;
  86.         vectors[VEC_FPNAN] = snan_vec;
  87.         vectors[VEC_FPOE] = operr_vec;
  88.         vectors[VEC_FPBRUC] = bsun_vec;
  89.         vectors[VEC_FPBRUC] = bsun_vec;
  90.         vectors[VEC_LINE11] = fline_vec;
  91.         vectors[VEC_FPUNSUP] = unsupp_vec;
  92.     }
  93. #endif
  94. }
  95.  
  96. char *vec_names[] = {
  97.     "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
  98.     "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
  99.     "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
  100.     "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
  101.     "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
  102.     "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
  103.     "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
  104.     "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
  105.     "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
  106.     "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
  107.     "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
  108.     "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
  109.     "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
  110.     "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
  111.     "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15"
  112.     };
  113.  
  114. char *space_names[] = {
  115.     "Space 0", "User Data", "User Program", "Space 3",
  116.     "Space 4", "Super Data", "Super Program", "CPU"
  117.     };
  118.  
  119.  
  120.  
  121. extern void die_if_kernel(char *,struct frame *,int);
  122. asmlinkage void do_page_fault(struct frame *fp, unsigned long address,
  123.                   unsigned long error_code);
  124.  
  125. asmlinkage void trap_c(struct frame *fp);
  126.  
  127. static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
  128. {
  129.     unsigned long mmusr;
  130.     unsigned short fs = get_fs();
  131.  
  132.     set_fs (fc);
  133.  
  134.       if (iswrite)
  135.           /* write */
  136.         asm volatile ("movel %1,a0\n\t"              
  137.                   ".word 0xf548\n\t"    /* ptestw (a0) */
  138.                   ".long 0x4e7a8805\n\t"    /* movec mmusr,a0 */
  139.                   "movel a0,%0"
  140.                   : "=g" (mmusr)
  141.                   : "g" (addr)
  142.                   : "a0");
  143.     else
  144.         asm volatile ("movel %1,a0\n\t"
  145.                   ".word 0xf568\n\t"    /* ptestr (a0) */
  146.                   ".long 0x4e7a8805\n\t"    /* movec mmusr,a0 */
  147.                   "movel a0,%0"
  148.                   : "=g" (mmusr)
  149.                   : "g" (addr)
  150.                   : "a0");
  151.  
  152.  
  153.     set_fs (fs);
  154.  
  155.     return mmusr;
  156. }
  157.  
  158. static void do_040writeback (unsigned short itsnotme,
  159.                   unsigned short ssw,
  160.                  unsigned short wbs,
  161.                  unsigned long wba,
  162.                  unsigned long wbd,
  163.                  struct frame *fp)
  164. {
  165.     unsigned short fs = get_fs ();
  166.     unsigned long mmusr;
  167.     unsigned long wba_2ndpage;
  168.  
  169.  
  170.     if(itsnotme)
  171.     {
  172.         /*
  173.          * to avoid another page fault, check the address we're going to,
  174.          * and map it in
  175.          */
  176.         mmusr = probe040 (1, wbs & WBTM_040,  wba);
  177.         if (mmusr & MMU_R_040)
  178.             do_page_fault (fp, wba, 1);
  179.         else
  180.             do_page_fault (fp, wba, 0);
  181.     }
  182.  
  183.     /*
  184.      * if the write spans a page, make sure that the extra page
  185.      * is mapped in.
  186.      * MR: information concerning this may be retrieved from the SSW;
  187.      * thus we can save us the page comparison
  188.      */
  189.     if(ssw & MA_040)
  190.     {
  191.         /* Added missing parentheses (MA) */
  192.         wba_2ndpage = wba + (((wbs & WBSIZ_040)==BA_SIZE_WORD)?1:3);
  193.         mmusr = probe040 (1, wbs & WBTM_040, wba_2ndpage);
  194.         if (mmusr & MMU_R_040)
  195.             do_page_fault (fp, wba_2ndpage, 1);
  196.         else
  197.             do_page_fault (fp, wba_2ndpage, 0);
  198.     }
  199.  
  200.     set_fs (wbs & WBTM_040);
  201.     switch (wbs & WBSIZ_040) {
  202.         case BA_SIZE_BYTE:
  203.         put_user_byte (wbd & 0xff, (char *)wba);
  204.         break;
  205.         case BA_SIZE_WORD:
  206.         put_user_word (wbd & 0xffff, (short *)wba);
  207.         break;
  208.         case BA_SIZE_LONG:
  209.         put_user_long (wbd, (int *)wba);
  210.         break;
  211.     }
  212.     set_fs (fs);
  213. }
  214.  
  215. static inline void access_error040 (struct frame *fp)
  216. {
  217.     unsigned short ssw = fp->un.fmt7.ssw;
  218.     unsigned long mmusr;
  219.  
  220. #ifdef DEBUG
  221.     printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
  222. #endif
  223.  
  224.     if (ssw & ATC_040) {
  225.         unsigned long addr = fp->un.fmt7.faddr;
  226.  
  227.         /* MMU error, get the MMUSR info for this access */
  228.         mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr);
  229.  
  230. #ifdef DEBUG
  231.         printk("mmusr = %lx\n", mmusr);
  232. #endif
  233.  
  234.         if (mmusr & MMU_R_040)
  235.             do_page_fault (fp, addr, 1);    /* we hit a resident page, so we want to write to it ?! */
  236.         else
  237.             do_page_fault (fp, addr, 0);    /* not resident */
  238.  
  239.     } else {
  240.         printk ("68040 access error, ssw=%x\n", ssw);
  241.         trap_c (fp);
  242.     }
  243.  
  244. #if 0
  245.     if (fp->un.fmt7.wb1s & WBV_040)
  246.         printk("access_error040: cannot handle 1st writeback. oops.\n");
  247. #endif
  248.  
  249.     /*
  250.      *  We may have to do a couple of writebacks here.
  251.      *
  252.      *  MR: we can speed up the thing a little bit and let do_040writeback()
  253.      *  not produce another page fault as wb2 corresponds to the address that
  254.      *  caused the fault. on write faults no second fault is generated, but
  255.      *  on read faults for security reasons (although per definitionem impossible)
  256.      */
  257.  
  258.     if (fp->un.fmt7.wb2s & WBV_040 && (fp->un.fmt7.wb2s & WBTT_040) != BA_TT_MOVE16)
  259.         do_040writeback (!(ssw & RW_040), ssw,
  260.                  fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d, fp);
  261.  
  262.     if (fp->un.fmt7.wb3s & WBV_040)
  263.         do_040writeback (1, ssw,
  264.                  fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d, fp);
  265. }
  266.  
  267. static inline void bus_error030 (struct frame *fp)
  268. {
  269.     volatile unsigned short temp;
  270.     unsigned short mmusr;
  271.     unsigned long addr, desc;
  272.     unsigned short ssw = fp->un.fmtb.ssw;
  273.  
  274. #ifdef DEBUG
  275.     printk ("SSW=%#06x  ", ssw);
  276.  
  277.     if (ssw & (FC | FB))
  278.         printk ("Instruction fault at %#010x\n",
  279.             ssw & FC ?
  280.             fp->format == 0xa ? fp->pc + 2 : fp->un.fmtb.baddr - 2
  281.             :
  282.             fp->format == 0xa ? fp->pc + 4 : fp->un.fmtb.baddr);
  283.     if (ssw & DF)
  284.         printk ("Data %s fault at %#010x in %s (pc=%#lx)\n",
  285.             ssw & RW ? "read" : "write",
  286.             fp->un.fmtb.daddr,
  287.             space_names[ssw & DFC], fp->pc);
  288. #endif
  289.  
  290.     if (fp->sr & PS_S) {
  291.         /* kernel fault must be a data fault to user space */
  292.         if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
  293.             /* instruction fault or kernel data fault! */
  294.             if (ssw & (FC | FB))
  295.                 printk ("Instruction fault at %#010lx\n",
  296.                     fp->pc);
  297.             if (ssw & DF) {
  298.                 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
  299.                     ssw & RW ? "read" : "write",
  300.                     fp->un.fmtb.daddr,
  301.                     space_names[ssw & DFC], fp->pc);
  302.             }
  303.             printk ("BAD KERNEL BUSERR");
  304.             trap_c (fp);
  305.         }
  306.     } else {
  307.         /* user fault */
  308.         if (!(ssw & (FC | FB)) && !(ssw & DF))
  309.             /* not an instruction fault or data fault! BAD */
  310.             panic ("USER BUSERR w/o instruction or data fault");
  311.     }
  312.  
  313.     /* get the fault address */
  314.     if (fp->format == 0xA )
  315.         if (ssw & FC)
  316.             addr = fp->pc + 2;
  317.         else if (ssw & FB)
  318.             addr = fp->pc + 4;
  319.         else /* data fault */
  320.             addr = fp->un.fmta.daddr;
  321.     else
  322.         if (ssw & FC)
  323.             addr = fp->un.fmtb.baddr - 2;
  324.         else if (ssw & FB)
  325.             addr = fp->un.fmtb.baddr;
  326.         else /* data fault */
  327.             addr = fp->un.fmtb.daddr;
  328.  
  329.     asm volatile ("ptestr #1,%2@,#7,%0\n\t"
  330.               "pmove psr,%1@"
  331.               : "=a&" (desc)
  332.               : "a" (&temp), "a" (addr));
  333.     mmusr = temp;
  334.               
  335. #ifdef DEBUG
  336.     printk ("mmusr is %#x for addr %#lx in task %p\n",
  337.         mmusr, addr, current);
  338.     printk ("descriptor address is %#lx, contents %#lx\n",
  339.         PTOV(desc), *(unsigned long *)PTOV(desc));
  340. #endif
  341.  
  342.     if (mmusr & MMU_I)
  343.         do_page_fault (fp, addr, 0);
  344.     else if ((mmusr & MMU_WP) && !(ssw & RW))
  345.         do_page_fault (fp, addr, 1);
  346.     else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
  347.         printk ("invalid %s access at %#lx from pc %#lx\n",
  348.             !(ssw & RW) ? "write" : "read", addr, fp->pc);
  349.         die_if_kernel("Oops",fp,mmusr);
  350.         send_sig(SIGSEGV, current, 1);
  351.         return;
  352.     } else {
  353. #ifdef DEBUG
  354.         static volatile long tlong;
  355. #endif
  356.  
  357.         printk ("wierd %s access at %#lx from pc %#lx (ssw is %#x)\n",
  358.             !(ssw & RW) ? "write" : "read", addr, fp->pc, ssw);
  359.         asm volatile ( /* "ptestr #1,%1@,#0\n\t" */
  360.                   "pmove psr,%0@"
  361.                   : 
  362.                   : "a" (&temp), "a" (addr));
  363.         mmusr = temp;
  364.               
  365.         printk ("level 0 mmusr is %#x\n", mmusr);
  366. #if defined(DEBUG) && 0
  367.         asm volatile ("pmove tt0,%0@"
  368.                   : /* no outputs */
  369.                   : "a" (&tlong));
  370.         printk ("tt0 is %#lx, ", tlong);
  371.         asm volatile ("pmove tt1,%0@"
  372.                   : /* no outputs */
  373.                   : "a" (&tlong));
  374.         printk ("tt1 is %#lx\n", tlong);
  375.  
  376. #endif
  377.         die_if_kernel("Oops",fp,mmusr);
  378.         send_sig(SIGSEGV, current, 1);
  379.         return;
  380.     }
  381.  
  382.     /* setup an ATC entry for the access about to be retried */
  383.     if (!(ssw & RW))
  384.         asm volatile ("ploadw #1,%0@" : /* no outputs */
  385.                   : "a" (addr));
  386.     else
  387.         asm volatile ("ploadr #1,%0@" : /* no outputs */
  388.                   : "a" (addr));
  389. }
  390.  
  391. asmlinkage void buserr_c(struct frame *fp)
  392. {
  393.  
  394. #ifdef DEBUG
  395.     printk ("*** Bus Error *** Format is %x\n", fp->format);
  396. #endif
  397.  
  398.     switch (fp->format) {
  399.         case 7:                /* 68040 access error */
  400.         access_error040 (fp);
  401.         break;
  402.         case 0xa:
  403.         case 0xb:
  404.         bus_error030 (fp);
  405.         break;
  406.         default:
  407.         panic ("bad frame format %d", fp->format);
  408.     }
  409. }
  410.  
  411.  
  412. void bad_super_trap (struct frame *fp)
  413. {
  414.     unsigned long isp;
  415.  
  416.     /* fetch interrupt stack pointer */
  417.     __asm__ __volatile__ ("movec isp,%0" : "=g" (isp));
  418.  
  419.     if (fp->vector < 48*4)
  420.         printk ("*** %s ***   FORMAT=%X\n",
  421.             vec_names[fp->vector >> 2], fp->format);
  422.     else
  423.         printk ("*** Exception %d ***   FORMAT=%X\n",
  424.             fp->vector >> 2, fp->format);
  425.  
  426.     printk ("PC=%#010lx   SR=%#06x       SP=%#010lx  ISP=%#010lx\n",
  427.         fp->pc, fp->sr, (ulong)fp, isp);
  428.     printk ("D0=%#010lx   D1=%#010lx   D2=%#010lx   D3=%#010lx\n",
  429.         fp->d0, fp->regs[0], fp->regs[1], fp->regs[2]);
  430.     printk ("D4=%#010lx   D5=%#010lx   D6=%#010lx   D7=%#010lx\n",
  431.         fp->regs[3], fp->regs[4], fp->regs[5], fp->regs[6]);
  432.     printk ("A0=%#010lx   A1=%#010lx   A2=%#010lx   A3=%#010lx\n",
  433.         fp->regs[7], fp->regs[8], fp->regs[9], fp->regs[10]);
  434.     printk ("A4=%#010lx   A5=%#010lx   A6=%#010lx  USP=%#010lx\n",
  435.         fp->regs[11], fp->regs[12], fp->regs[13], fp->usp);
  436.  
  437.     if ((fp->vector >> 2) == VEC_ADDRERR
  438.         && !(boot_info.cputype & CPU_68040)) {
  439.         unsigned short ssw = fp->un.fmtb.ssw;
  440.  
  441.         printk ("SSW=%#06x  ", ssw);
  442.  
  443.         if (ssw & RC)
  444.             printk ("Pipe stage C instruction fault at %#010lx\n",
  445.                 fp->format == 0xA ? fp->pc + 2 :
  446.                 fp->un.fmtb.baddr - 2);
  447.         if (ssw & RB)
  448.             printk ("Pipe stage B instruction fault at %#010lx\n",
  449.                 fp->format == 0xA ? fp->pc + 4 :
  450.                 fp->un.fmtb.baddr);
  451.         if (ssw & DF)
  452.             printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
  453.                 ssw & RW ? "read" : "write",
  454.                 fp->un.fmtb.daddr, space_names[ssw & DFC],
  455.                 fp->pc);
  456.  
  457.         printk ("Word at pc is %#x\n", *(ushort *)fp->pc);
  458.     }
  459.     panic ("BAD KERNEL TRAP");
  460. }
  461.  
  462. asmlinkage void trap_c(struct frame *fp)
  463. {
  464.     int sig;
  465.  
  466.     if ((fp->sr & PS_S) && (fp->vector >> 2) == VEC_TRACE
  467.         && !(fp->sr & PS_T)) {
  468.         /* traced a trapping instruction */
  469.         unsigned char *lp = ((unsigned char *)&fp->un.fmt2) + 4;
  470.         current->flags |= PF_DTRACE;
  471.         /* clear the trace bit */
  472.         (*(unsigned short *)lp) &= ~PS_T;
  473.         return;
  474.     } else if (fp->sr & PS_S)
  475.         bad_super_trap(fp);
  476.  
  477.     /* send the appropriate signal to the user program */
  478.     switch (fp->vector >> 2) {
  479.         case VEC_BUSERR:
  480.         case VEC_ADDRERR:
  481.         sig = SIGSEGV;
  482.         break;
  483.         case VEC_ILLEGAL:
  484.         case VEC_PRIV:
  485.         case VEC_LINE10:
  486.         case VEC_LINE11:
  487.         case VEC_COPROC:
  488.         case VEC_TRAP1:
  489.         case VEC_TRAP2:
  490.         case VEC_TRAP3:
  491.         case VEC_TRAP4:
  492.         case VEC_TRAP5:
  493.         case VEC_TRAP6:
  494.         case VEC_TRAP7:
  495.         case VEC_TRAP8:
  496.         case VEC_TRAP9:
  497.         case VEC_TRAP10:
  498.         case VEC_TRAP11:
  499.         case VEC_TRAP12:
  500.         case VEC_TRAP13:
  501.         case VEC_TRAP14:
  502.         sig = SIGILL;
  503.         break;
  504.         case VEC_ZERODIV:
  505.         case VEC_FPBRUC:
  506.         case VEC_FPIR:
  507.         case VEC_FPDIVZ:
  508.         case VEC_FPUNDER:
  509.         case VEC_FPOE:
  510.         case VEC_FPOVER:
  511.         case VEC_FPNAN:
  512.         sig = SIGFPE;
  513.         break;
  514.         case VEC_TRACE:        /* ptrace single step */
  515.         fp->sr &= ~PS_T;
  516.         case VEC_TRAP15:        /* breakpoint */
  517.         sig = SIGTRAP;
  518.         break;
  519.         default:
  520.         sig = SIGILL;
  521.         break;
  522.     }
  523.  
  524.     send_sig (sig, current, 1);
  525. }
  526.  
  527. void die_if_kernel (char *str, struct frame *fp, int nr)
  528. {
  529.     u_char *ssp = (u_char *)fp;
  530.     int i;
  531.  
  532.     if (!(fp->sr & PS_S))
  533.         return;
  534.  
  535.     printk("%s: %04x\n",str,nr&0xffff);
  536.     printk("PC:    %08lx\nSR: %04x\n", fp->pc,fp->sr);
  537.     printk("Pid: %d\n",current->pid);
  538.     for (i = 0; i < 10; i++)
  539.         printk ("%02x ", 0xff & ssp[i]);
  540.     printk ("\n");
  541.     do_exit(SIGSEGV);
  542. }
  543.  
  544. void arch_core_dump (struct user *up, long signr, struct pt_regs *regs)
  545. {
  546.     up->magic = CMAGIC;
  547.     up->start_code = 0;
  548.     up->start_stack = regs->usp & ~(PAGE_SIZE - 1);
  549.     up->u_tsize = ((unsigned long) current->end_code) >> 12;
  550.     up->u_dsize = ((unsigned long) (current->brk + (PAGE_SIZE-1))) >> 12;
  551.     up->u_dsize -= up->u_tsize;
  552.     up->u_ssize = 0;
  553.     if (up->start_stack < TASK_SIZE)
  554.         up->u_ssize = ((unsigned long) (TASK_SIZE - up->start_stack)) >> 12;
  555. /* If the size of the dump file exceeds the rlimit, then see what would happen
  556.    if we wrote the stack, but not the data area.  */
  557.     if ((up->u_dsize+up->u_ssize+1) * PAGE_SIZE >
  558.         current->rlim[RLIMIT_CORE].rlim_cur)
  559.         up->u_dsize = 0;
  560. /* Make sure we have enough room to write the stack and data areas. */
  561.     if ((up->u_ssize+1) * PAGE_SIZE >
  562.         current->rlim[RLIMIT_CORE].rlim_cur)
  563.         up->u_ssize = 0;
  564.     strncpy(up->u_comm, current->comm, sizeof(current->comm));
  565.     up->u_ar0 = (struct pt_regs *)(((int)(&up->regs)) -((int)(up)));
  566.     up->signal = signr;
  567.     up->regs = *regs;
  568.     /* floating point stuff valid */
  569.     up->u_fpvalid = 1;
  570.     /* save floating point registers */
  571.     asm volatile ("fmovem  fpcr/fpsr,%0@"
  572.               :: "a" (up->m68kfp.fpcntl));
  573.     asm volatile ("fmovemx fp0-fp7,%0@"
  574.               :: "a" (up->m68kfp.fpregs)
  575.               : "memory");
  576. }
  577.