home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / bsdss4.tz / bsdss4 / bsdss / server / i386 / machdep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-25  |  13.3 KB  |  599 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1992 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon 
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    machdep.c,v $
  29.  * Revision 2.2  92/05/25  14:42:13  rwd
  30.  *     Added ptrace support from UX and additional to support
  31.  *          386BSD gdb.
  32.  *     [92/05/21            rwd]
  33.  * 
  34.  * Revision 2.1  92/04/21  17:19:12  rwd
  35.  * BSDSS
  36.  * 
  37.  *
  38.  */
  39.  
  40. /*
  41.  *    Machine-dependent routines evicted from rest of BSD
  42.  *    files.
  43.  */
  44.  
  45. #include <i386/reg.h>
  46. #include <i386/eflags.h>
  47.  
  48. #include <sys/param.h>
  49.  
  50. #include <sys/proc.h>
  51. #include <sys/user.h>
  52. #include <sys/wait.h>
  53. #include <sys/uio.h>
  54. #include <sys/exec.h>
  55. #include <sys/systm.h>        /* boothowto */
  56. #include <sys/parallel.h>
  57. #include <sys/syscall.h>
  58.  
  59. #include <ufs/quota.h>
  60. #include <ufs/inode.h>
  61.  
  62. #include <uxkern/import_mach.h>
  63.  
  64. set_arg_addr(arg_size,
  65.          arg_start_p,
  66.          arg_size_p)
  67.     u_int        arg_size;
  68.     vm_offset_t    *arg_start_p;
  69.     vm_size_t    *arg_size_p;
  70. {
  71.     /*
  72.      * Round arg size to fullwords
  73.      */
  74.     arg_size = (arg_size + NBPW-1) & ~(NBPW - 1);
  75.  
  76.     /*
  77.      * Put argument list at top of stack.
  78.      */
  79.     *arg_start_p = USRSTACK - arg_size;
  80.     *arg_size_p = arg_size;
  81. }
  82.  
  83. extern boolean_t    first_exec;
  84.  
  85. set_entry_address(ep, entry, entry_count)
  86.     struct exec    *ep;
  87.     int        *entry;        /* pointer to OUT array */
  88.     unsigned int    *entry_count;    /* out */
  89. {
  90.     entry[0] = ep->a_entry;
  91.     *entry_count = 1;
  92. }
  93.  
  94. /*
  95.  * Set up the process' registers to start the emulator - duplicate
  96.  * what execve() in the emulator would do.
  97.  */
  98. set_emulator_state(entry, entry_count, arg_addr)
  99.     int entry[];
  100.     int entry_count;
  101.     vm_offset_t    arg_addr;
  102. {
  103.     struct i386_thread_state    ts;
  104.     unsigned int            count;
  105.     register struct proc *p = (struct proc *)cthread_data(cthread_self());
  106.     kern_return_t ret;
  107.  
  108.     /*
  109.      * Read the registers first, to get the correct
  110.      * segments.
  111.      */
  112.     count = i386_THREAD_STATE_COUNT;
  113.     if ((ret=thread_get_state(p->p_thread,
  114.                   i386_THREAD_STATE,
  115.                   (thread_state_t)&ts,
  116.                   &count)) != KERN_SUCCESS)
  117.     panic("set_emulator_state",ret);
  118.     ts.eip = (int)entry[0];
  119.     ts.uesp = (int)arg_addr;
  120.     ts.efl = EFL_USER_SET;
  121.  
  122.     if ((ret=thread_set_state(p->p_thread,
  123.                   i386_THREAD_STATE,
  124.                   (thread_state_t)&ts,
  125.                   i386_THREAD_STATE_COUNT)) != KERN_SUCCESS)
  126.     panic("set_emulator_state",ret);
  127. }
  128.  
  129. /*
  130.  * Do weird things to the first process' address space before loading
  131.  * the emulator.
  132.  */
  133. void
  134. emul_init_process(p)
  135.     struct proc    *p;
  136. {
  137.     /*
  138.      * Clear out the entire address space.
  139.      */
  140.     (void) vm_deallocate(p->p_task,
  141.             VM_MIN_ADDRESS,
  142.             (vm_size_t)(VM_MAX_ADDRESS - VM_MIN_ADDRESS));
  143.  
  144. }
  145.  
  146.  
  147. #if 0
  148. machine_core(p, ip)
  149.     register struct proc    *p;
  150.     register struct inode    *ip;
  151. {
  152.     vm_offset_t    stack_addr;
  153.     vm_size_t    stack_size;
  154.     off_t        offset = 0;
  155.     int        error;
  156.  
  157.     struct i386_thread_state    ts;
  158.     unsigned int        count;
  159.  
  160.     /*
  161.      * Get the registers for the thread.
  162.      */
  163.  
  164.     count = i386_THREAD_STATE_COUNT;
  165.     (void) thread_get_state(p->p_thread,
  166.                 i386_THREAD_STATE,
  167.                 (thread_state_t)&ts,
  168.                 &count);
  169.  
  170.     /*
  171.      * Fake the stack segment size from the current
  172.      * stack pointer value.
  173.      */
  174.     stack_addr = trunc_page(ts.uesp);
  175.     stack_size = round_page(USRSTACK - stack_addr);
  176.     p->p_utask.uu_ssize = btoc(stack_size);
  177.  
  178.     /*
  179.      * Build a fake U-area for the bottom of the
  180.      * 'kernel-stack' in the core file.
  181.      */
  182.     {
  183.         struct user fake_uarea;
  184.  
  185.         fake_u(&fake_uarea, p, p->p_thread);
  186.  
  187.         error = RDWRI(UIO_WRITE, ip,
  188.         (caddr_t)&fake_uarea, sizeof(struct user),
  189.         offset, UIO_SYSSPACE, (int *)0);
  190.     }
  191.     if (error)
  192.         goto out;
  193.  
  194.     /*
  195.      * Build a fake register save area for the top of
  196.      * the 'kernel-stack' in the core file.
  197.      */
  198.     {
  199.         int        regs[21];
  200. #define    LOCR0_OFFSET    21
  201.  
  202.         bzero((caddr_t)regs, sizeof(regs));
  203.  
  204.         regs[EAX + LOCR0_OFFSET] = ts.eax;
  205.         regs[EBX + LOCR0_OFFSET] = ts.ebx;
  206.         regs[ECX + LOCR0_OFFSET] = ts.ecx;
  207.         regs[EDX + LOCR0_OFFSET] = ts.edx;
  208.         regs[ESP + LOCR0_OFFSET] = ts.esp;
  209.         regs[EBP + LOCR0_OFFSET] = ts.ebp;
  210.         regs[ESI + LOCR0_OFFSET] = ts.esi;
  211.         regs[EDI + LOCR0_OFFSET] = ts.edi;
  212.         regs[EIP + LOCR0_OFFSET] = ts.eip;
  213.         regs[EFL + LOCR0_OFFSET] = ts.efl;
  214.         regs[UESP+ LOCR0_OFFSET] = ts.uesp;
  215.         regs[CS  + LOCR0_OFFSET] = ts.cs;
  216.         regs[SS  + LOCR0_OFFSET] = ts.ss;
  217.         regs[DS  + LOCR0_OFFSET] = ts.ds;
  218.         regs[ES  + LOCR0_OFFSET] = ts.es;
  219.         regs[FS  + LOCR0_OFFSET] = ts.fs;
  220.         regs[GS  + LOCR0_OFFSET] = ts.gs;
  221.  
  222.         offset = ctob(UPAGES);
  223.         error = RDWRI(UIO_WRITE, ip,
  224.         (caddr_t)regs, (int) sizeof(regs),
  225.         offset - sizeof(regs),
  226.         UIO_SYSSPACE, (int *)0);
  227.     }
  228.     if (error)
  229.         goto out;
  230.  
  231.     /*
  232.      * Write the data segment.
  233.      */
  234.     error = core_file_write(ip, &offset, p->p_task,
  235.             p->p_utask.uu_data_start,
  236.             (int)ctob(p->p_utask.uu_dsize));
  237.     if (error)
  238.         goto out;
  239.  
  240.     /*
  241.      * Write the stack.
  242.      */
  243.     error = core_file_write(ip, &offset, p->p_task,
  244.             stack_addr, stack_size);
  245.  
  246.     out:
  247.     return (error);
  248.  
  249. #undef    LOCR0_OFFSET
  250. }
  251.  
  252. #endif 0
  253.  
  254. struct reg_offsets {
  255.     int    reg_offset;
  256.     int    state_offset;
  257. };
  258. #define    state_off(s)    (int)&(((struct i386_thread_state *)0)->s)
  259. #define    reg_off(r)    sizeof(int)*(r)+ctob(UPAGES)
  260. #define regs(r,s)    { reg_off(r), state_off(s) }
  261.  
  262. struct reg_offsets ipcregs[] = {
  263.         regs(tES, es),
  264.         regs(tDS, ds),
  265.     regs(tEDI, edi),
  266.     regs(tESI, esi),
  267.     regs(tEBP, ebp),
  268.     regs(tEBX, ebx),
  269.     regs(tEDX, edx),
  270.     regs(tECX, ecx),
  271.     regs(tEAX, eax),
  272.     regs(tEIP, eip),
  273.     regs(tCS, cs),
  274.     regs(tEFLAGS, efl),
  275.     regs(tESP, uesp),
  276.     regs(tSS, ss)
  277. };
  278.  
  279. #undef    regs
  280. #undef    reg_off
  281. #undef    state_off
  282.  
  283. int ptrace_get_u_word(p, offset, value)
  284.     struct proc *p;
  285.     register int    offset;
  286.     int    *value;    /* out */
  287. {
  288.     if (offset < 0 || offset > ctob(UPAGES) + NIPCREG*sizeof(int))
  289.         return (EIO);
  290.  
  291.     if (offset < sizeof(struct user)) {
  292.         int *addr;
  293.  
  294.         addr = (int *)(((caddr_t)p->p_addr) + offset);
  295.         if (addr == (int *)&p->p_addr->u_pcb.pcb_flags) {
  296.         *value = -1;
  297.         } else if (addr == (int *)&p->p_addr->u_kproc.kp_proc.p_regs) {
  298.         *value = ctob(UPAGES) + 0xFDBFE000; /*XXX old USRSTACK */
  299.         } else {
  300.         *value = *addr;
  301.         }
  302.     } else {
  303.         struct i386_thread_state    thread_state;
  304.         unsigned int        count;
  305.         register int        j;
  306.  
  307.         count = i386_THREAD_STATE_COUNT;
  308.         if (thread_get_state(p->p_thread,
  309.                  i386_THREAD_STATE,
  310.                  (thread_state_t)&thread_state,
  311.                  &count) != KERN_SUCCESS)
  312.         return EIO;
  313.  
  314.         *value = 0;
  315.  
  316.         for (j = 0; j < NIPCREG; j++) {
  317.         if (ipcregs[j].reg_offset == offset) {
  318.             *value = *(int *)(((caddr_t)&thread_state)
  319.                     + ipcregs[j].state_offset);
  320.             break;
  321.         }
  322.         }
  323.  
  324.     }
  325.     return (0);
  326. }
  327.  
  328. int ptrace_set_u_word(p, offset, value, old)
  329.     struct proc *p;
  330.     register int offset;
  331.     int    value;
  332.     int    *old;
  333. {
  334.     /*
  335.      *    Write victim's registers.
  336.      *    Offsets are into BSD kernel stack, and must
  337.      *    be faked to match MACH.
  338.      */
  339.     struct i386_thread_state    thread_state;
  340.     unsigned int    count;
  341.     register int    j;
  342.  
  343.     count = i386_THREAD_STATE_COUNT;
  344.     if (thread_get_state(p->p_thread,
  345.                  i386_THREAD_STATE,
  346.                  (thread_state_t)&thread_state,
  347.                  &count)!= KERN_SUCCESS)
  348.         return EIO;
  349.  
  350.     for (j = 0; j < NIPCREG; j++)
  351.         if (ipcregs[j].reg_offset == offset)
  352.         break;
  353.  
  354.     if (j == NIPCREG) {
  355.         /* wrong register */
  356.         return (EIO);
  357.     }
  358.  
  359.     /* thread_set_state handles checking PSL for valid values */
  360.     *(int *)(((caddr_t)&thread_state)
  361.             + ipcregs[j].state_offset)
  362.               = value;
  363.     if (thread_set_state(p->p_thread,
  364.                  i386_THREAD_STATE,
  365.                  (thread_state_t)&thread_state,
  366.                  count) != KERN_SUCCESS)
  367.         return EIO;
  368.     return (0);
  369. }
  370.  
  371. ptrace_set_trace(p, new_addr, trace_on)
  372.     struct proc *p;
  373.     int    new_addr;
  374.     int    trace_on;
  375. {
  376.     struct i386_thread_state    thread_state;
  377.     unsigned int        count;
  378.  
  379.     count = i386_THREAD_STATE_COUNT;
  380.     if (thread_get_state(p->p_thread,
  381.                  i386_THREAD_STATE,
  382.                  (thread_state_t)&thread_state,
  383.                  &count) != KERN_SUCCESS)
  384.         return EIO;
  385.  
  386.     if (new_addr != 1)
  387.         thread_state.eip = new_addr;
  388.  
  389.     if (trace_on)
  390.         thread_state.efl   |= EFL_TF;
  391.  
  392.     if (thread_set_state(p->p_thread,
  393.                  i386_THREAD_STATE,
  394.                  (thread_state_t)&thread_state,
  395.                  count) != KERN_SUCCESS)
  396.         return EIO;
  397.     return 0;
  398. }
  399.  
  400. ptrace_get_regs(p, regs)
  401.     struct proc *p;
  402.     int regs[NIPCREG];
  403. {
  404.     struct i386_thread_state    thread_state;
  405.     unsigned int        count;
  406.     int j;
  407.  
  408.     count = i386_THREAD_STATE_COUNT;
  409.     if (thread_get_state(p->p_thread,
  410.                  i386_THREAD_STATE,
  411.                  (thread_state_t)&thread_state,
  412.                  &count) != KERN_SUCCESS)
  413.         return EIO;
  414.  
  415.     for (j = 0; j < NIPCREG; j++) {
  416.         regs[ipcregs[j].reg_offset] = *(int *)(((caddr_t)&thread_state)
  417.                            + ipcregs[j].state_offset);
  418.     }
  419. }
  420.  
  421. ptrace_set_regs(p, regs)
  422.     struct proc *p;
  423.     int regs[NIPCREG];
  424. {
  425.     struct i386_thread_state    thread_state;
  426.     unsigned int        count;
  427.     int j;
  428.  
  429.     for (j = 0; j < NIPCREG; j++) {
  430.         *(int *)(((caddr_t)&thread_state) + ipcregs[j].state_offset) =
  431.          regs[ipcregs[j].reg_offset];
  432.     }
  433.  
  434.     /* thread_set_state handles checking PSL for valid values */
  435.     count = i386_THREAD_STATE_COUNT;
  436.     if (thread_set_state(p->p_thread,
  437.                  i386_THREAD_STATE,
  438.                  (thread_state_t)&thread_state,
  439.                  count) != KERN_SUCCESS)
  440.         return EIO;
  441.     return 0;
  442. }
  443.  
  444. /*
  445.  * Send an interrupt to process.
  446.  *
  447.  * Stack is set up to allow sigcode stored in u. to call routine,
  448.  * followed by chmk to sigreturn routine below.  After sigreturn
  449.  * resets the signal mask, the stack, the frame pointer, and the
  450.  * argument pointer, it returns to the user-specified pc/psl.
  451.  */
  452. void
  453. sendsig(p, thread, sig_hdlr, sig, code, mask)
  454.     struct proc    *p;
  455.     thread_t    thread;
  456.         int sig, code, mask;
  457.     void(*sig_hdlr)();
  458. {
  459.     struct sigframe {
  460.         int    sf_signum;
  461.         int    sf_code;
  462.         struct    sigcontext *sf_scp;
  463.         sig_t    sf_handler;
  464.         int    sf_eax;    
  465.         int    sf_edx;    
  466.         int    sf_ecx;    
  467.         struct    sigcontext sf_sc;
  468.     } *fp;
  469.     int    oonstack;
  470.  
  471.     struct i386_thread_state regs;
  472.     unsigned int        reg_size;
  473.  
  474.     vm_offset_t    user_start_addr, user_end_addr, kern_addr;
  475.     vm_size_t    user_size;
  476.  
  477.     register struct sigframe   *kfp;
  478.     register struct sigacts *ps = p->p_sigacts;
  479.  
  480.     /*
  481.      * Get the registers for the thread.
  482.      */
  483.     reg_size = i386_THREAD_STATE_COUNT;
  484.     (void) thread_get_state(thread, i386_THREAD_STATE,
  485.                 (thread_state_t)®s, ®_size);
  486.  
  487.     oonstack = ps->ps_onstack;
  488.  
  489.     if (!oonstack && (ps->ps_sigonstack & sigmask(sig))) {
  490.         fp = (struct sigframe *)ps->ps_sigstack.ss_sp - 1;
  491.         ps->ps_sigstack.ss_onstack = 1;
  492.     }
  493.     else {
  494.         fp = (struct sigframe *)regs.uesp - 1;
  495.     }
  496.  
  497.     /*
  498.      * Copy the signal frame from the user into the kernel,
  499.      * to modify it.
  500.      */
  501.     user_start_addr = trunc_page((vm_offset_t)fp);
  502.     user_end_addr   = round_page((vm_offset_t)fp
  503.                     + sizeof(*fp));
  504.     user_size = user_end_addr - user_start_addr;
  505.  
  506.     if (vm_read(p->p_task, user_start_addr, user_size,
  507.             &kern_addr, &user_size) != KERN_SUCCESS)
  508.         goto error;
  509.  
  510.     kfp = (struct sigframe *)((vm_offset_t)fp - user_start_addr
  511.                     + kern_addr);
  512.  
  513.     /*
  514.      * Build the argument list for the signal handler.
  515.      */
  516.     kfp->sf_signum = sig;
  517.     kfp->sf_code = code;
  518.     kfp->sf_scp = &fp->sf_sc;
  519.     kfp->sf_handler = sig_hdlr;
  520.  
  521.     kfp->sf_eax = regs.eax;
  522.     kfp->sf_edx = regs.edx;
  523.     kfp->sf_ecx = regs.ecx;
  524.  
  525.     /*
  526.      * Build the signal context to be used by sigreturn.
  527.      */
  528.     kfp->sf_sc.sc_onstack = oonstack;
  529.     kfp->sf_sc.sc_mask = mask;
  530.  
  531.     kfp->sf_sc.sc_fp = regs.ebp;
  532.     kfp->sf_sc.sc_pc = regs.eip;
  533.     kfp->sf_sc.sc_ps = regs.efl;
  534.     kfp->sf_sc.sc_sp = regs.uesp;
  535.  
  536.     /*
  537.      * Set up the new stack and handler address.
  538.      */
  539.     regs.uesp = (int)fp;
  540.     regs.eip = USRSTACK-TRAMPOLINE_MAX_SIZE;
  541.  
  542.     /*
  543.      * Write signal frame and context back to user.
  544.      */
  545.     if (vm_write(p->p_task, user_start_addr, kern_addr, user_size)
  546.         != KERN_SUCCESS) {
  547.         (void)vm_deallocate(mach_task_self(), kern_addr, user_size);
  548.         goto error;
  549.     }
  550.  
  551.     /*
  552.      * Write changed registers back to thread.
  553.      */
  554.     (void) thread_set_state(thread, i386_THREAD_STATE,
  555.                 (thread_state_t)®s, reg_size);
  556.  
  557.     (void)vm_deallocate(mach_task_self(), kern_addr, user_size);
  558.     return;
  559.  
  560.     error:
  561.     /*
  562.      * Process has trashed its stack; kill it and core dump it.
  563.      * The idea is to imitate the default action for a SIGILL.
  564.      */
  565.     exit(p, SIGILL);
  566. }
  567.  
  568. sigreturn()
  569. {
  570.     panic("sigreturn - MiG interface");
  571. }
  572. osigcleanup()
  573. {
  574.     panic("osigcleanup - MiG interface");
  575. }
  576.     
  577. /*
  578.  * Clone the parent's registers into the child thread for fork.
  579.  */
  580. boolean_t
  581. thread_dup(child_thread, new_state, new_state_count, parent_pid, rc)
  582.     thread_t    child_thread;
  583.     thread_state_t    new_state;
  584.     unsigned int    new_state_count;
  585.     int        parent_pid, rc;
  586. {
  587.     struct i386_thread_state *regs = (struct i386_thread_state *)new_state;
  588.  
  589.     if (new_state_count != i386_THREAD_STATE_COUNT)
  590.         return (FALSE);
  591.  
  592.     regs->eax = parent_pid;
  593.     regs->edx = rc;
  594.  
  595.     (void) thread_set_state(child_thread, i386_THREAD_STATE,
  596.                 new_state, new_state_count);
  597.     return (TRUE);
  598. }
  599.