1: /* This task handles the interface between file system and kernel as well as
   2:  * between memory manager and kernel.  System services are obtained by sending
   3:  * sys_task() a message specifying what is needed.  To make life easier for
   4:  * MM and FS, a library is provided with routines whose names are of the
   5:  * form sys_xxx, e.g. sys_xit sends the SYS_XIT message to sys_task.  The
   6:  * message types and parameters are:
   7:  *
   8:  *   SYS_FORK    informs kernel that a process has forked
   9:  *   SYS_NEWMAP  allows MM to set up a process memory map
  10:  *   SYS_GETMAP  allows MM to get a process' memory map
  11:  *   SYS_EXEC    sets program counter and stack pointer after EXEC
  12:  *   SYS_XIT     informs kernel that a process has exited
  13:  *   SYS_GETSP   caller wants to read out some process' stack pointer
  14:  *   SYS_TIMES   caller wants to get accounting times for a process
  15:  *   SYS_ABORT   MM or FS cannot go on; abort MINIX
  16:  *   SYS_FRESH   start with a fresh process image during EXEC (68000 only)
  17:  *   SYS_SENDSIG send a signal to a process (POSIX style)
  18:  *   SYS_SIGRETURN complete POSIX-style signalling
  19:  *   SYS_KILL    cause a signal to be sent via MM
  20:  *   SYS_ENDSIG  finish up after SYS_KILL-type signal
  21:  *   SYS_COPY    request a block of data to be copied between processes
  22:  *   SYS_VCOPY   request a series of data blocks to be copied between procs
  23:  *   SYS_GBOOT   copies the boot parameters to a process
  24:  *   SYS_MEM     returns the next free chunk of physical memory
  25:  *   SYS_UMAP    compute the physical address for a given virtual address
  26:  *   SYS_TRACE   request a trace operation
  27:  *   SYS_SYSCTL  handles miscelleneous kernel control functions
  28:  *   SYS_PUTS    a server (MM, FS, ...) wants to issue a diagnostic
  29:  *   SYS_FINDPROC find a process' task number given it's names
  30:  *
  31:  * Message types and parameters:
  32:  *
  33:  *    m_type       PROC1     PROC2      PID     MEM_PTR
  34:  * ------------------------------------------------------
  35:  * | SYS_FORK   | parent  |  child  |   pid   |         |
  36:  * |------------+---------+---------+---------+---------|
  37:  * | SYS_NEWMAP | proc nr |         |         | map ptr |
  38:  * |------------+---------+---------+---------+---------|
  39:  * | SYS_EXEC   | proc nr | traced  | new sp  |         |
  40:  * |------------+---------+---------+---------+---------|
  41:  * | SYS_XIT    | parent  | exitee  |         |         |
  42:  * |------------+---------+---------+---------+---------|
  43:  * | SYS_GETSP  | proc nr |         |         |         |
  44:  * |------------+---------+---------+---------+---------|
  45:  * | SYS_TIMES  | proc nr |         | buf ptr |         |
  46:  * |------------+---------+---------+---------+---------|
  47:  * | SYS_ABORT  |         |         |         |         |
  48:  * |------------+---------+---------+---------+---------|
  49:  * | SYS_FRESH  | proc nr | data_cl |         |         |
  50:  * |------------+---------+---------+---------+---------|
  51:  * | SYS_GBOOT  | proc nr |         |         | bootptr |
  52:  * |------------+---------+---------+---------+---------|
  53:  * | SYS_GETMAP | proc nr |         |         | map ptr |
  54:  * ------------------------------------------------------
  55:  *
  56:  *    m_type          m1_i1     m1_i2     m1_i3       m1_p1
  57:  * ----------------+---------+---------+---------+--------------
  58:  * | SYS_VCOPY     |  src p  |  dst p  | vec siz | vc addr     |
  59:  * |---------------+---------+---------+---------+-------------|
  60:  * | SYS_SENDSIG   | proc nr |         |         | smp         |
  61:  * |---------------+---------+---------+---------+-------------|
  62:  * | SYS_SIGRETURN | proc nr |         |         | scp         |
  63:  * |---------------+---------+---------+---------+-------------|
  64:  * | SYS_ENDSIG    | proc nr |         |         |             |
  65:  * |---------------+---------+---------+---------+-------------|
  66:  * | SYS_PUTS      |  count  |         |         | buf         |
  67:  * -------------------------------------------------------------
  68:  *
  69:  *    m_type       m2_i1     m2_i2     m2_l1     m2_l2     m2_p1
  70:  * ---------------------------------------------------------------
  71:  * | SYS_TRACE  | proc_nr | request |  addr   |  data   |        |
  72:  * |------------+---------+---------+---------+---------|---------
  73:  * | SYS_SYSCTL | proc_nr | request |         |         |  argp  |
  74:  * ---------------------------------------------------------------
  75:  *
  76:  *    m_type       m6_i1     m6_i2     m6_i3     m6_f1
  77:  * ------------------------------------------------------
  78:  * | SYS_KILL   | proc_nr  |  sig    |         |         |
  79:  * ------------------------------------------------------
  80:  *
  81:  *    m_type        m3_i1   m3_i2    m3_p1   m3_ca1
  82:  * --------------------------------------------------
  83:  * | SYS_FINDPROC | flags |        |       | name   |
  84:  * --------------------------------------------------
  85:  *
  86:  *    m_type      m5_c1   m5_i1    m5_l1   m5_c2   m5_i2    m5_l2   m5_l3
  87:  * --------------------------------------------------------------------------
  88:  * | SYS_COPY   |src seg|src proc|src vir|dst seg|dst proc|dst vir| byte ct |
  89:  * --------------------------------------------------------------------------
  90:  * | SYS_UMAP   |  seg  |proc nr |vir adr|       |        |       | byte ct |
  91:  * --------------------------------------------------------------------------
  92:  *
  93:  *    m_type      m1_i1      m1_i2      m1_i3
  94:  * |------------+----------+----------+----------
  95:  * | SYS_MEM    | mem base | mem size | tot mem |
  96:  * ----------------------------------------------
  97:  *
  98:  * In addition to the main sys_task() entry point, there are 5 other minor
  99:  * entry points:
 100:  *   cause_sig: take action to cause a signal to occur, sooner or later
 101:  *   inform:    tell MM about pending signals
 102:  *   numap:     umap D segment starting from process number instead of pointer
 103:  *   umap:      compute the physical address for a given virtual address
 104:  *   alloc_segments: allocate segments for 8088 or higher processor
 105:  */
 106: 
 107: #include "kernel.h"
 108: #include <stdlib.h>
 109: #include <signal.h>
 110: #include <unistd.h>
 111: #include <sys/sigcontext.h>
 112: #include <sys/ptrace.h>
 113: #include <sys/svrctl.h>
 114: #include <minix/callnr.h>
 115: #include <minix/com.h>
 116: #include "proc.h"
 117: #if (CHIP == INTEL)
 118: #include "protect.h"
 119: #endif
 120: #include "assert.h"
 121: INIT_ASSERT
 122: 
 123: /* PSW masks. */
 124: #define IF_MASK 0x00000200
 125: #define IOPL_MASK 0x003000
 126: 
 127: PRIVATE message m;
 128: 
 129: FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
 130: FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
 131: FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
 132: FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
 133: FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
 134: FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
 135: FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
 136: FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
 137: FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
 138: FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
 139: FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
 140: FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
 141: FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
 142: FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
 143: FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
 144: FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
 145: FORWARD _PROTOTYPE( int do_getmap, (message *m_ptr) );
 146: FORWARD _PROTOTYPE( int do_sysctl, (message *m_ptr) );
 147: FORWARD _PROTOTYPE( int do_puts, (message *m_ptr) );
 148: FORWARD _PROTOTYPE( int do_findproc, (message *m_ptr) );
 149: 
 150: 
 151: /*===========================================================================*
 152:  *                              sys_task                                     *
 153:  *===========================================================================*/
 154: PUBLIC void sys_task()
 155: {
 156: /* Main entry point of sys_task.  Get the message and dispatch on type. */
 157: 
 158:   register int r;
 159: 
 160:   while (TRUE) {
 161:         receive(ANY, &m);
 162: 
 163:         switch (m.m_type) {     /* which system call */
 164:             case SYS_FORK:      r = do_fork(&m); break;
 165:             case SYS_NEWMAP:    r = do_newmap(&m);       break;
 166:             case SYS_GETMAP:    r = do_getmap(&m);       break;
 167:             case SYS_EXEC:      r = do_exec(&m); break;
 168:             case SYS_XIT:       r = do_xit(&m);          break;
 169:             case SYS_GETSP:     r = do_getsp(&m);        break;
 170:             case SYS_TIMES:     r = do_times(&m);        break;
 171:             case SYS_ABORT:     r = do_abort(&m);        break;
 172:             case SYS_SENDSIG:   r = do_sendsig(&m);      break;
 173:             case SYS_SIGRETURN: r = do_sigreturn(&m);    break;
 174:             case SYS_KILL:      r = do_kill(&m); break;
 175:             case SYS_ENDSIG:    r = do_endsig(&m);       break;
 176:             case SYS_COPY:      r = do_copy(&m); break;
 177:             case SYS_VCOPY:     r = do_vcopy(&m);        break;
 178:             case SYS_MEM:       r = do_mem(&m);          break;
 179:             case SYS_UMAP:      r = do_umap(&m); break;
 180:             case SYS_TRACE:     r = do_trace(&m);        break;
 181:             case SYS_SYSCTL:    r = do_sysctl(&m);       break;
 182:             case SYS_PUTS:      r = do_puts(&m); break;
 183:             case SYS_FINDPROC:  r = do_findproc(&m);     break;
 184:             default:            r = E_BAD_FCN;
 185:         }
 186: 
 187:         m.m_type = r;           /* 'r' reports status of call */
 188:         send(m.m_source, &m);    /* send reply to caller */
 189:   }
 190: }
 191: 
 192: 
 193: /*===========================================================================*
 194:  *                              do_fork                                      *
 195:  *===========================================================================*/
 196: PRIVATE int do_fork(m_ptr)
 197: register message *m_ptr;        /* pointer to request message */
 198: {
 199: /* Handle sys_fork().  m_ptr->PROC1 has forked.  The child is m_ptr->PROC2. */
 200: 
 201: #if (CHIP == INTEL)
 202:   reg_t old_ldt_sel;
 203: #endif
 204:   register struct proc *rpc;
 205:   struct proc *rpp;
 206: 
 207:   rpp = proc_addr(m_ptr->PROC1);
 208:   assert(isuserp(rpp));
 209:   rpc = proc_addr(m_ptr->PROC2);
 210:   assert(isemptyp(rpc));
 211: 
 212:   /* Copy parent 'proc' struct to child. */
 213: #if (CHIP == INTEL)
 214:   old_ldt_sel = rpc->p_ldt_sel;  /* stop this being obliterated by copy */
 215: #endif
 216: 
 217:   *rpc = *rpp;                  /* copy 'proc' struct */
 218: 
 219: #if (CHIP == INTEL)
 220:   rpc->p_ldt_sel = old_ldt_sel;
 221: #endif
 222:   rpc->p_nr = m_ptr->PROC2;       /* this was obliterated by copy */
 223: 
 224:   rpc->p_flags |= NO_MAP;        /* inhibit the process from running */
 225: 
 226:   rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
 227: 
 228:   /* Only 1 in group should have PENDING, child does not inherit trace status*/
 229:   sigemptyset(&rpc->p_pending);
 230:   rpc->p_pendcount = 0;
 231:   rpc->p_pid = m_ptr->PID;        /* install child's pid */
 232:   rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
 233: 
 234:   rpc->user_time = 0;            /* set all the accounting times to 0 */
 235:   rpc->sys_time = 0;
 236:   rpc->child_utime = 0;
 237:   rpc->child_stime = 0;
 238: 
 239:   return(OK);
 240: }
 241: 
 242: 
 243: /*===========================================================================*
 244:  *                              do_newmap                                    *
 245:  *===========================================================================*/
 246: PRIVATE int do_newmap(m_ptr)
 247: message *m_ptr;                 /* pointer to request message */
 248: {
 249: /* Handle sys_newmap().  Fetch the memory map from MM. */
 250: 
 251:   register struct proc *rp;
 252:   phys_bytes src_phys;
 253:   int caller;                   /* whose space has the new map (usually MM) */
 254:   int k;                        /* process whose map is to be loaded */
 255:   int old_flags;                /* value of flags before modification */
 256:   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
 257: 
 258:   /* Extract message parameters and copy new memory map from MM. */
 259:   caller = m_ptr->m_source;
 260:   k = m_ptr->PROC1;
 261:   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
 262:   if (!isokprocn(k)) return(E_BAD_PROC);
 263:   rp = proc_addr(k);            /* ptr to entry of user getting new map */
 264: 
 265:   /* Copy the map from MM. */
 266:   src_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
 267:   assert(src_phys != 0);
 268:   phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
 269: 
 270: #if (CHIP != M68000)
 271:   alloc_segments(rp);
 272: #else
 273:   pmmu_init_proc(rp);
 274: #endif
 275:   old_flags = rp->p_flags;       /* save the previous value of the flags */
 276:   rp->p_flags &= ~NO_MAP;
 277:   if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
 278: 
 279:   return(OK);
 280: }
 281: 
 282: 
 283: /*===========================================================================*
 284:  *                              do_getmap                                    *
 285:  *===========================================================================*/
 286: PRIVATE int do_getmap(m_ptr)
 287: message *m_ptr;                 /* pointer to request message */
 288: {
 289: /* Handle sys_getmap().  Report the memory map to MM. */
 290: 
 291:   register struct proc *rp;
 292:   phys_bytes dst_phys;
 293:   int caller;                   /* where the map has to be stored */
 294:   int k;                        /* process whose map is to be loaded */
 295:   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
 296: 
 297:   /* Extract message parameters and copy new memory map to MM. */
 298:   caller = m_ptr->m_source;
 299:   k = m_ptr->PROC1;
 300:   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
 301: 
 302:   assert(isokprocn(k));         /* unlikely: MM sends a bad proc nr. */
 303: 
 304:   rp = proc_addr(k);            /* ptr to entry of the map */
 305: 
 306:   /* Copy the map to MM. */
 307:   dst_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
 308:   assert(dst_phys != 0);
 309:   phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
 310: 
 311:   return(OK);
 312: }
 313: 
 314: 
 315: /*===========================================================================*
 316:  *                              do_exec                                      *
 317:  *===========================================================================*/
 318: PRIVATE int do_exec(m_ptr)
 319: register message *m_ptr;        /* pointer to request message */
 320: {
 321: /* Handle sys_exec().  A process has done a successful EXEC. Patch it up. */
 322: 
 323:   register struct proc *rp;
 324:   reg_t sp;                     /* new sp */
 325:   phys_bytes phys_name;
 326:   char *np;
 327: #define NLEN (sizeof(rp->p_name)-1)
 328: 
 329:   rp = proc_addr(m_ptr->PROC1);
 330:   assert(isuserp(rp));
 331:   /* PROC2 field is used as flag to indicate process is being traced */
 332:   if (m_ptr->PROC2) cause_sig(m_ptr->PROC1, SIGTRAP);
 333:   sp = (reg_t) m_ptr->STACK_PTR;
 334:   rp->p_reg.sp = sp;             /* set the stack pointer */
 335: #if (CHIP == M68000)
 336:   rp->p_splow = sp;              /* set the stack pointer low water */
 337: #ifdef FPP
 338:   /* Initialize fpp for this process */
 339:   fpp_new_state(rp);
 340: #endif
 341: #endif
 342: #if (CHIP == INTEL)             /* wipe extra LDT entries */
 343:   memset(&rp->p_ldt[EXTRA_LDT_INDEX], 0,
 344:         (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
 345: #endif
 346:   rp->p_reg.pc = (reg_t) m_ptr->IP_PTR;   /* set pc */
 347:   rp->p_flags &= ~RECEIVING;      /* MM does not reply to EXEC call */
 348:   if (rp->p_flags == 0) lock_ready(rp);
 349: 
 350:   /* Save command name for debugging, ps(1) output, etc. */
 351:   phys_name = numap(m_ptr->m_source, (vir_bytes) m_ptr->NAME_PTR,
 352:                                                         (vir_bytes) NLEN);
 353:   if (phys_name != 0) {
 354:         phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
 355:         for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
 356:         *np = 0;
 357:   }
 358:   return(OK);
 359: }
 360: 
 361: 
 362: /*===========================================================================*
 363:  *                              do_xit                                       *
 364:  *===========================================================================*/
 365: PRIVATE int do_xit(m_ptr)
 366: message *m_ptr;                 /* pointer to request message */
 367: {
 368: /* Handle sys_xit().  A process has exited. */
 369: 
 370:   register struct proc *rp, *rc;
 371:   struct proc *np, *xp;
 372:   int parent;                   /* number of exiting proc's parent */
 373:   int proc_nr;                  /* number of process doing the exit */
 374:   phys_clicks base, size;
 375: 
 376:   parent = m_ptr->PROC1; /* slot number of parent process */
 377:   proc_nr = m_ptr->PROC2;        /* slot number of exiting process */
 378:   rp = proc_addr(parent);
 379:   assert(isuserp(rp));
 380:   rc = proc_addr(proc_nr);
 381:   assert(isuserp(rc));
 382:   lock();
 383:   rp->child_utime += rc->user_time + rc->child_utime;      /* accum child times */
 384:   rp->child_stime += rc->sys_time + rc->child_stime;
 385:   unlock();
 386:   cancel_alarm(proc_nr);                /* turn off alarm timer */
 387:   if (rc->p_flags == 0) lock_unready(rc);
 388: 
 389:   strcpy(rc->p_name, "<noname>");    /* process no longer has a name */
 390: 
 391:   /* If the process being terminated happens to be queued trying to send a
 392:    * message (i.e., the process was killed by a signal, rather than it doing an
 393:    * EXIT), then it must be removed from the message queues.
 394:    */
 395:   if (rc->p_flags & SENDING) {
 396:         /* Check all proc slots to see if the exiting process is queued. */
 397:         for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
 398:                 if (rp->p_callerq == NIL_PROC) continue;
 399:                 if (rp->p_callerq == rc) {
 400:                         /* Exiting process is on front of this queue. */
 401:                         rp->p_callerq = rc->p_sendlink;
 402:                         break;
 403:                 } else {
 404:                         /* See if exiting process is in middle of queue. */
 405:                         np = rp->p_callerq;
 406:                         while ( ( xp = np->p_sendlink) != NIL_PROC)
 407:                                 if (xp == rc) {
 408:                                         np->p_sendlink = xp->p_sendlink;
 409:                                         break;
 410:                                 } else {
 411:                                         np = xp;
 412:                                 }
 413:                 }
 414:         }
 415:   }
 416: #if (CHIP == M68000)
 417:   pmmu_delete(rc);      /* we're done remove tables */
 418: #endif
 419: 
 420:   if (rc->p_flags & PENDING) --sig_procs;
 421:   sigemptyset(&rc->p_pending);
 422:   rc->p_pendcount = 0;
 423:   rc->p_flags = 0;
 424:   rc->p_priority = PPRI_NONE;
 425:   return(OK);
 426: }
 427: 
 428: 
 429: /*===========================================================================*
 430:  *                              do_getsp                                     *
 431:  *===========================================================================*/
 432: PRIVATE int do_getsp(m_ptr)
 433: register message *m_ptr;        /* pointer to request message */
 434: {
 435: /* Handle sys_getsp().  MM wants to know what sp is. */
 436: 
 437:   register struct proc *rp;
 438: 
 439:   rp = proc_addr(m_ptr->PROC1);
 440:   assert(isuserp(rp));
 441:   m_ptr->STACK_PTR = (char *) rp->p_reg.sp;       /* return sp here (bad type) */
 442:   return(OK);
 443: }
 444: 
 445: 
 446: /*===========================================================================*
 447:  *                              do_times                                     *
 448:  *===========================================================================*/
 449: PRIVATE int do_times(m_ptr)
 450: register message *m_ptr;        /* pointer to request message */
 451: {
 452: /* Handle sys_times().  Retrieve the accounting information. */
 453: 
 454:   register struct proc *rp;
 455: 
 456:   rp = proc_addr(m_ptr->PROC1);
 457: 
 458:   /* Insert the times needed by the TIMES system call in the message. */
 459:   lock();                       /* halt the volatile time counters in rp */
 460:   m_ptr->USER_TIME   = rp->user_time;
 461:   m_ptr->SYSTEM_TIME = rp->sys_time;
 462:   unlock();
 463:   m_ptr->CHILD_UTIME = rp->child_utime;
 464:   m_ptr->CHILD_STIME = rp->child_stime;
 465:   m_ptr->BOOT_TICKS  = get_uptime();
 466:   return(OK);
 467: }
 468: 
 469: 
 470: /*===========================================================================*
 471:  *                              do_abort                                     *
 472:  *===========================================================================*/
 473: PRIVATE int do_abort(m_ptr)
 474: message *m_ptr;                 /* pointer to request message */
 475: {
 476: /* Handle sys_abort.  MINIX is unable to continue.  Terminate operation. */
 477:   phys_bytes src_phys;
 478:   vir_bytes len;
 479: 
 480:   if (m_ptr->m1_i1 == RBT_MONITOR) {
 481:         /* The monitor is to run user specified instructions. */
 482:         len = m_ptr->m1_i3 + 1;
 483:         assert(len <= mon_parmsize);
 484:         src_phys = numap(m_ptr->m1_i2, (vir_bytes) m_ptr->m1_p1, len);
 485:         assert(src_phys != 0);
 486:         phys_copy(src_phys, mon_params, (phys_bytes) len);
 487:   }
 488:   wreboot(m_ptr->m1_i1);
 489:   return(OK);                   /* pro-forma (really EDISASTER) */
 490: }
 491: 
 492: 
 493: /*===========================================================================*
 494:  *                            do_sendsig                                     *
 495:  *===========================================================================*/
 496: PRIVATE int do_sendsig(m_ptr)
 497: message *m_ptr;                 /* pointer to request message */
 498: {
 499: /* Handle sys_sendsig, POSIX-style signal */
 500: 
 501:   struct sigmsg smsg;
 502:   register struct proc *rp;
 503:   phys_bytes src_phys, dst_phys;
 504:   struct sigcontext sc, *scp;
 505:   struct sigframe fr, *frp;
 506: 
 507:   rp = proc_addr(m_ptr->PROC1);
 508:   assert(isuserp(rp));
 509: 
 510:   /* Get the sigmsg structure into our address space.  */
 511:   src_phys = umap(proc_addr(MM_PROC_NR), D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
 512:                   (vir_bytes) sizeof(struct sigmsg));
 513:   assert(src_phys != 0);
 514:   phys_copy(src_phys, vir2phys(&smsg), (phys_bytes) sizeof(struct sigmsg));
 515: 
 516:   /* Compute the usr stack pointer value where sigcontext will be stored. */
 517:   scp = (struct sigcontext *) smsg.sm_stkptr - 1;
 518: 
 519:   /* Copy the registers to the sigcontext structure. */
 520:   memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
 521: 
 522:   /* Finish the sigcontext initialization. */
 523:   sc.sc_flags = SC_SIGCONTEXT;
 524: 
 525:   sc.sc_mask = smsg.sm_mask;
 526: 
 527:   /* Copy the sigcontext structure to the user's stack. */
 528:   dst_phys = umap(rp, D, (vir_bytes) scp,
 529:                   (vir_bytes) sizeof(struct sigcontext));
 530:   if (dst_phys == 0) return(EFAULT);
 531:   phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
 532: 
 533:   /* Initialize the sigframe structure. */
 534:   frp = (struct sigframe *) scp - 1;
 535:   fr.sf_scpcopy = scp;
 536:   fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
 537:   fr.sf_fp = rp->p_reg.fp;
 538:   rp->p_reg.fp = (reg_t) &frp->sf_fp;
 539:   fr.sf_scp = scp;
 540:   fr.sf_code = 0;       /* XXX - should be used for type of FP exception */
 541:   fr.sf_signo = smsg.sm_signo;
 542:   fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
 543: 
 544:   /* Copy the sigframe structure to the user's stack. */
 545:   dst_phys = umap(rp, D, (vir_bytes) frp, (vir_bytes) sizeof(struct sigframe));
 546:   if (dst_phys == 0) return(EFAULT);
 547:   phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
 548: 
 549:   /* Reset user registers to execute the signal handler. */
 550:   rp->p_reg.sp = (reg_t) frp;
 551:   rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
 552: 
 553:   return(OK);
 554: }
 555: 
 556: /*===========================================================================*
 557:  *                            do_sigreturn                                   *
 558:  *===========================================================================*/
 559: PRIVATE int do_sigreturn(m_ptr)
 560: register message *m_ptr;
 561: {
 562: /* POSIX style signals require sys_sigreturn to put things in order before the
 563:  * signalled process can resume execution
 564:  */
 565: 
 566:   struct sigcontext sc;
 567:   register struct proc *rp;
 568:   phys_bytes src_phys;
 569: 
 570:   rp = proc_addr(m_ptr->PROC1);
 571:   assert(isuserp(rp));
 572: 
 573:   /* Copy in the sigcontext structure. */
 574:   src_phys = umap(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
 575:                   (vir_bytes) sizeof(struct sigcontext));
 576:   if (src_phys == 0) return(EFAULT);
 577:   phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
 578: 
 579:   /* Make sure that this is not just a jmp_buf. */
 580:   if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
 581: 
 582:   /* Fix up only certain key registers if the compiler doesn't use
 583:    * register variables within functions containing setjmp.
 584:    */
 585:   if (sc.sc_flags & SC_NOREGLOCALS) {
 586:         rp->p_reg.retreg = sc.sc_retreg;
 587:         rp->p_reg.fp = sc.sc_fp;
 588:         rp->p_reg.pc = sc.sc_pc;
 589:         rp->p_reg.sp = sc.sc_sp;
 590:         return (OK);
 591:   }
 592:   sc.sc_psw  = rp->p_reg.psw;
 593: 
 594: #if (CHIP == INTEL)
 595:   /* Don't panic kernel if user gave bad selectors. */
 596:   sc.sc_cs = rp->p_reg.cs;
 597:   sc.sc_ds = rp->p_reg.ds;
 598:   sc.sc_es = rp->p_reg.es;
 599: #if _WORD_SIZE == 4
 600:   sc.sc_fs = rp->p_reg.fs;
 601:   sc.sc_gs = rp->p_reg.gs;
 602: #endif
 603: #endif
 604: 
 605:   /* Restore the registers. */
 606:   memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
 607: 
 608:   return(OK);
 609: }
 610: 
 611: /*===========================================================================*
 612:  *                              do_kill                                      *
 613:  *===========================================================================*/
 614: PRIVATE int do_kill(m_ptr)
 615: register message *m_ptr;        /* pointer to request message */
 616: {
 617: /* Handle sys_kill(). Cause a signal to be sent to a process via MM.
 618:  * Note that this has nothing to do with the kill (2) system call, this
 619:  * is how the FS (and possibly other servers) get access to cause_sig to
 620:  * send a KSIG message to MM
 621:  */
 622: 
 623:   assert(isuserp(proc_addr(m_ptr->PR)));
 624:   cause_sig(m_ptr->PR, m_ptr->SIGNUM);
 625:   return(OK);
 626: }
 627: 
 628: 
 629: /*===========================================================================*
 630:  *                            do_endsig                                      *
 631:  *===========================================================================*/
 632: PRIVATE int do_endsig(m_ptr)
 633: register message *m_ptr;        /* pointer to request message */
 634: {
 635: /* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a call
 636:  * to cause_sig by a task
 637:  */
 638: 
 639:   register struct proc *rp;
 640: 
 641:   rp = proc_addr(m_ptr->PROC1);
 642:   if (isemptyp(rp)) return(E_BAD_PROC);         /* process already dead? */
 643:   assert(isuserp(rp));
 644: 
 645:   /* MM has finished one KSIG. */
 646:   if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
 647:       && (rp->p_flags &= ~SIG_PENDING) == 0)
 648:         lock_ready(rp);
 649:   return(OK);
 650: }
 651: 
 652: /*===========================================================================*
 653:  *                              do_copy                                      *
 654:  *===========================================================================*/
 655: PRIVATE int do_copy(m_ptr)
 656: register message *m_ptr;        /* pointer to request message */
 657: {
 658: /* Handle sys_copy().  Copy data for MM or FS. */
 659: 
 660:   int src_proc, dst_proc, src_space, dst_space;
 661:   vir_bytes src_vir, dst_vir;
 662:   phys_bytes src_phys, dst_phys, bytes;
 663: 
 664:   /* Dismember the command message. */
 665:   src_proc = m_ptr->SRC_PROC_NR;
 666:   dst_proc = m_ptr->DST_PROC_NR;
 667:   src_space = m_ptr->SRC_SPACE;
 668:   dst_space = m_ptr->DST_SPACE;
 669:   src_vir = (vir_bytes) m_ptr->SRC_BUFFER;
 670:   dst_vir = (vir_bytes) m_ptr->DST_BUFFER;
 671:   bytes = (phys_bytes) m_ptr->COPY_BYTES;
 672: 
 673:   /* Compute the source and destination addresses and do the copy. */
 674:   if (src_proc == ABS) {
 675:         src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
 676:   } else {
 677:         if (bytes != (vir_bytes) bytes) {
 678:                 /* This would happen for 64K segments and 16-bit vir_bytes.
 679:                  * It would happen a lot for do_fork except MM uses ABS
 680:                  * copies for that case.
 681:                  */
 682:                 panic("overflow in count in do_copy", NO_NUM);
 683:         }
 684:         src_phys = umap(proc_addr(src_proc), src_space, src_vir,
 685:                         (vir_bytes) bytes);
 686:   }
 687: 
 688:   if (dst_proc == ABS) {
 689:         dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
 690:   } else {
 691:         dst_phys = umap(proc_addr(dst_proc), dst_space, dst_vir,
 692:                         (vir_bytes) bytes);
 693:   }
 694: 
 695:   if (src_phys == 0 || dst_phys == 0) return(EFAULT);
 696:   phys_copy(src_phys, dst_phys, bytes);
 697:   return(OK);
 698: }
 699: 
 700: 
 701: /*===========================================================================*
 702:  *                              do_vcopy                                     *
 703:  *===========================================================================*/
 704: PRIVATE int do_vcopy(m_ptr)
 705: register message *m_ptr;        /* pointer to request message */
 706: {
 707: /* Handle sys_vcopy(). Copy multiple blocks of memory */
 708: 
 709:   int src_proc, dst_proc, vect_s, i;
 710:   vir_bytes src_vir, dst_vir, vect_addr;
 711:   phys_bytes src_phys, dst_phys, bytes;
 712:   cpvec_t cpvec_table[CPVEC_NR];
 713: 
 714:   /* Dismember the command message. */
 715:   src_proc = m_ptr->m1_i1;
 716:   dst_proc = m_ptr->m1_i2;
 717:   vect_s = m_ptr->m1_i3;
 718:   vect_addr = (vir_bytes)m_ptr->m1_p1;
 719: 
 720:   if (vect_s > CPVEC_NR) return EDOM;
 721: 
 722:   src_phys= numap (m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
 723:   if (!src_phys) return EFAULT;
 724:   phys_copy(src_phys, vir2phys(cpvec_table),
 725:                                 (phys_bytes) (vect_s * sizeof(cpvec_t)));
 726: 
 727:   for (i = 0; i < vect_s; i++) {
 728:         src_vir= cpvec_table[i].cpv_src;
 729:         dst_vir= cpvec_table[i].cpv_dst;
 730:         bytes= cpvec_table[i].cpv_size;
 731:         src_phys = numap(src_proc,src_vir,(vir_bytes)bytes);
 732:         dst_phys = numap(dst_proc,dst_vir,(vir_bytes)bytes);
 733:         if (src_phys == 0 || dst_phys == 0) return(EFAULT);
 734:         phys_copy(src_phys, dst_phys, bytes);
 735:   }
 736:   return(OK);
 737: }
 738: 
 739: 
 740: /*===========================================================================*
 741:  *                              do_mem                                       *
 742:  *===========================================================================*/
 743: PRIVATE int do_mem(m_ptr)
 744: register message *m_ptr;        /* pointer to request message */
 745: {
 746: /* Return the base and size of the next chunk of memory. */
 747: 
 748:   struct memory *memp;
 749: 
 750:   for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
 751:         m_ptr->m1_i1 = memp->base;
 752:         m_ptr->m1_i2 = memp->size;
 753:         m_ptr->m1_i3 = tot_mem_size;
 754:         memp->size = 0;
 755:         if (m_ptr->m1_i2 != 0) break;            /* found a chunk */
 756:   }
 757:   return(OK);
 758: }
 759: 
 760: 
 761: /*==========================================================================*
 762:  *                              do_umap                                     *
 763:  *==========================================================================*/
 764: PRIVATE int do_umap(m_ptr)
 765: register message *m_ptr;        /* pointer to request message */
 766: {
 767: /* Same as umap(), for non-kernel processes. */
 768: 
 769:   m_ptr->SRC_BUFFER = umap(proc_addr((int) m_ptr->SRC_PROC_NR),
 770:                            (int) m_ptr->SRC_SPACE,
 771:                            (vir_bytes) m_ptr->SRC_BUFFER,
 772:                            (vir_bytes) m_ptr->COPY_BYTES);
 773:   return(OK);
 774: }
 775: 
 776: 
 777: /*==========================================================================*
 778:  *                              do_trace                                    *
 779:  *==========================================================================*/
 780: #define TR_PROCNR       (m_ptr->m2_i1)
 781: #define TR_REQUEST      (m_ptr->m2_i2)
 782: #define TR_ADDR         ((vir_bytes) m_ptr->m2_l1)
 783: #define TR_DATA         (m_ptr->m2_l2)
 784: #define TR_VLSIZE       ((vir_bytes) sizeof(long))
 785: 
 786: PRIVATE int do_trace(m_ptr)
 787: register message *m_ptr;
 788: {
 789: /* Handle the debugging commands supported by the ptrace system call
 790:  * The commands are:
 791:  * T_STOP       stop the process
 792:  * T_OK         enable tracing by parent for this process
 793:  * T_GETINS     return value from instruction space
 794:  * T_GETDATA    return value from data space
 795:  * T_GETUSER    return value from user process table
 796:  * T_SETINS     set value from instruction space
 797:  * T_SETDATA    set value from data space
 798:  * T_SETUSER    set value in user process table
 799:  * T_RESUME     resume execution
 800:  * T_EXIT       exit
 801:  * T_STEP       set trace bit
 802:  *
 803:  * The T_OK and T_EXIT commands are handled completely by the memory manager,
 804:  * all others come here.
 805:  */
 806: 
 807:   register struct proc *rp;
 808:   phys_bytes src, dst;
 809:   int i;
 810: 
 811:   rp = proc_addr(TR_PROCNR);
 812:   if (isemptyp(rp)) return(EIO);
 813:   switch (TR_REQUEST) {
 814:   case T_STOP:                  /* stop process */
 815:         if (rp->p_flags == 0) lock_unready(rp);
 816:         rp->p_flags |= P_STOP;
 817:         rp->p_reg.psw &= ~TRACEBIT;       /* clear trace bit */
 818:         return(OK);
 819: 
 820:   case T_GETINS:                /* return value from instruction space */
 821:         if (rp->p_map[T].mem_len != 0) {
 822:                 if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
 823:                 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
 824:                 break;
 825:         }
 826:         /* Text space is actually data space - fall through. */
 827: 
 828:   case T_GETDATA:               /* return value from data space */
 829:         if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
 830:         phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
 831:         break;
 832: 
 833:   case T_GETUSER:               /* return value from process table */
 834:         if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
 835:             TR_ADDR > sizeof(struct proc) - sizeof(long))
 836:                 return(EIO);
 837:         TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
 838:         break;
 839: 
 840:   case T_SETINS:                /* set value in instruction space */
 841:         if (rp->p_map[T].mem_len != 0) {
 842:                 if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
 843:                 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
 844:                 TR_DATA = 0;
 845:                 break;
 846:         }
 847:         /* Text space is actually data space - fall through. */
 848: 
 849:   case T_SETDATA:                       /* set value in data space */
 850:         if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
 851:         phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
 852:         TR_DATA = 0;
 853:         break;
 854: 
 855:   case T_SETUSER:                       /* set value in process table */
 856:         if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
 857:              TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
 858:                 return(EIO);
 859:         i = (int) TR_ADDR;
 860: #if (CHIP == INTEL)
 861:         /* Altering segment registers might crash the kernel when it
 862:          * tries to load them prior to restarting a process, so do
 863:          * not allow it.
 864:          */
 865:         if (i == (int) &((struct proc *) 0)->p_reg.cs ||
 866:             i == (int) &((struct proc *) 0)->p_reg.ds ||
 867:             i == (int) &((struct proc *) 0)->p_reg.es ||
 868: #if _WORD_SIZE == 4
 869:             i == (int) &((struct proc *) 0)->p_reg.gs ||
 870:             i == (int) &((struct proc *) 0)->p_reg.fs ||
 871: #endif
 872:             i == (int) &((struct proc *) 0)->p_reg.ss)
 873:                 return(EIO);
 874: #endif
 875:         if (i == (int) &((struct proc *) 0)->p_reg.psw)
 876:                 /* only selected bits are changeable */
 877:                 SETPSW(rp, TR_DATA);
 878:         else
 879:                 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
 880:         TR_DATA = 0;
 881:         break;
 882: 
 883:   case T_RESUME:                /* resume execution */
 884:         rp->p_flags &= ~P_STOP;
 885:         if (rp->p_flags == 0) lock_ready(rp);
 886:         TR_DATA = 0;
 887:         break;
 888: 
 889:   case T_STEP:                  /* set trace bit */
 890:         rp->p_reg.psw |= TRACEBIT;
 891:         rp->p_flags &= ~P_STOP;
 892:         if (rp->p_flags == 0) lock_ready(rp);
 893:         TR_DATA = 0;
 894:         break;
 895: 
 896:   default:
 897:         return(EIO);
 898:   }
 899:   return(OK);
 900: }
 901: 
 902: /*===========================================================================*
 903:  *                              do_sysctl                                    *
 904:  *===========================================================================*/
 905: PRIVATE int do_sysctl(m_ptr)
 906: message *m_ptr;                 /* pointer to request message */
 907: {
 908:   int proc_nr, priv;
 909:   struct proc *pp;
 910:   int request;
 911:   vir_bytes argp;
 912: 
 913:   proc_nr = m_ptr->m2_i1;
 914:   pp = proc_addr(proc_nr);
 915:   request = m_ptr->m2_i2;
 916:   priv = m_ptr->m2_i3;
 917:   argp = (vir_bytes) m_ptr->m2_p1;
 918: 
 919:   switch (request) {
 920:   case SYSSIGNON: {
 921:         struct systaskinfo info;
 922: 
 923:         /* Make this process a server. */
 924:         if (!priv || !isuserp(pp)) return(EPERM);
 925:         info.proc_nr = proc_nr;
 926:         if (vir_copy(SYSTASK, (vir_bytes) &info,
 927:                 proc_nr, argp, sizeof(info)) != OK) return(EFAULT);
 928: 
 929:         pp->p_priority = PPRI_SERVER;
 930:         pp->p_pid = 0;
 931:         return(OK); }
 932: 
 933:   case SYSGETENV: {
 934:         /* Obtain a kernel environment string, or simply all of it. */
 935:         struct sysgetenv sysgetenv;
 936:         phys_bytes src, dst;
 937:         char key[32];
 938:         char *val;
 939:         size_t len;
 940: 
 941:         if (vir_copy(proc_nr, argp, SYSTASK, (vir_bytes) &sysgetenv,
 942:                 sizeof(sysgetenv)) != OK) return(EFAULT);
 943: 
 944:         if (sysgetenv.keylen != 0) {
 945:                 /* Only one string by name. */
 946:                 if (sysgetenv.keylen > sizeof(key)) return(EINVAL);
 947: 
 948:                 if (vir_copy(proc_nr, (vir_bytes) sysgetenv.key,
 949:                         SYSTASK, (vir_bytes) key,
 950:                         sysgetenv.keylen) != OK) return(EFAULT);
 951: 
 952:                 if ((val = getenv(key)) == NULL) return(ESRCH);
 953:                 src = vir2phys(val);
 954:                 len = strlen(val) + 1;
 955:         } else {
 956:                 /* Whole environment please. */
 957:                 src = mon_params;
 958:                 len = mon_parmsize;
 959:         }
 960:         dst = umap(pp, D, (vir_bytes) sysgetenv.val, sysgetenv.vallen);
 961:         if (dst == 0) return(EFAULT);
 962:         if (len > sysgetenv.vallen) return(E2BIG);
 963:         phys_copy(src, dst, len);
 964:         return(OK); }
 965: 
 966:   default:
 967:         return(EINVAL);
 968:   }
 969: }
 970: 
 971: /*==========================================================================*
 972:  *                              do_puts                                     *
 973:  *==========================================================================*/
 974: PRIVATE int do_puts(m_ptr)
 975: message *m_ptr;                 /* pointer to request message */
 976: {
 977: /* Print a string for a server. */
 978:   char c;
 979:   vir_bytes src;
 980:   int count;
 981: 
 982:   src = (vir_bytes) m_ptr->m1_p1;
 983:   for (count = m_ptr->m1_i1; count > 0; count--) {
 984:         if (vir_copy(m_ptr->m_source, src++,
 985:                 SYSTASK, (vir_bytes) &c, 1) != OK) return(EFAULT);
 986:         putk(c);
 987:   }
 988:   putk(0);
 989:   return(OK);
 990: }
 991: 
 992: /*===========================================================================*
 993:  *                              do_findproc                                  *
 994:  *===========================================================================*/
 995: PRIVATE int do_findproc(m_ptr)
 996: message *m_ptr;                 /* pointer to request message */
 997: {
 998:   /* Determine the task number of a task given its name.  This allows a late
 999:    * started server such as inet to not know any task numbers, so it can be
1000:    * used with a kernel whose precise configuration (what task is where?) is
1001:    * unknown.
1002:    */
1003:   struct proc *pp;
1004: 
1005:   for (pp= BEG_PROC_ADDR; pp<END_PROC_ADDR; pp++) {
1006:         if (!istaskp(pp) && !isservp(pp)) continue;
1007: 
1008:         if (strncmp(pp->p_name, m_ptr->m3_ca1, M3_STRING) == 0) {
1009:                 m_ptr->m3_i1 = proc_number(pp);
1010:                 return(OK);
1011:         }
1012:   }
1013:   return(ESRCH);
1014: }
1015: 
1016: /*===========================================================================*
1017:  *                              cause_sig                                    *
1018:  *===========================================================================*/
1019: PUBLIC void cause_sig(proc_nr, sig_nr)
1020: int proc_nr;                    /* process to be signalled */
1021: int sig_nr;                     /* signal to be sent, 1 to _NSIG */
1022: {
1023: /* A task wants to send a signal to a process.   Examples of such tasks are:
1024:  *   TTY wanting to cause SIGINT upon getting a DEL
1025:  *   CLOCK wanting to cause SIGALRM when timer expires
1026:  * FS also uses this to send a signal, via the SYS_KILL message.
1027:  * Signals are handled by sending a message to MM.  The tasks don't dare do
1028:  * that directly, for fear of what would happen if MM were busy.  Instead they
1029:  * call cause_sig, which sets bits in p_pending, and then carefully checks to
1030:  * see if MM is free.  If so, a message is sent to it.  If not, when it becomes
1031:  * free, a message is sent.  The process being signaled is blocked while MM
1032:  * has not seen or finished with all signals for it.  These signals are
1033:  * counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
1034:  * there are some.  It is not sufficient to ready the process when MM is
1035:  * informed, because MM can block waiting for FS to do a core dump.
1036:  */
1037: 
1038:   register struct proc *rp, *mmp;
1039: 
1040:   rp = proc_addr(proc_nr);
1041:   if (sigismember(&rp->p_pending, sig_nr))
1042:         return;                 /* this signal already pending */
1043:   sigaddset(&rp->p_pending, sig_nr);
1044:   ++rp->p_pendcount;             /* count new signal pending */
1045:   if (rp->p_flags & PENDING)
1046:         return;                 /* another signal already pending */
1047:   if (rp->p_flags == 0) lock_unready(rp);
1048:   rp->p_flags |= PENDING | SIG_PENDING;
1049:   ++sig_procs;                  /* count new process pending */
1050: 
1051:   mmp = proc_addr(MM_PROC_NR);
1052:   if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
1053:   inform();
1054: }
1055: 
1056: 
1057: /*===========================================================================*
1058:  *                              inform                                       *
1059:  *===========================================================================*/
1060: PUBLIC void inform()
1061: {
1062: /* When a signal is detected by the kernel (e.g., DEL), or generated by a task
1063:  * (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
1064:  * p_pending field of the process to signal.  Then inform() is called to see
1065:  * if MM is idle and can be told about it.  Whenever MM blocks, a check is
1066:  * made to see if 'sig_procs' is nonzero; if so, inform() is called.
1067:  */
1068: 
1069:   register struct proc *rp;
1070: 
1071:   /* MM is waiting for new input.  Find a process with pending signals. */
1072:   for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
1073:         if (rp->p_flags & PENDING) {
1074:                 m.m_type = KSIG;
1075:                 m.SIG_PROC = proc_number(rp);
1076:                 m.SIG_MAP = rp->p_pending;
1077:                 sig_procs--;
1078:                 if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
1079:                         panic("can't inform MM", NO_NUM);
1080:                 sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
1081:                 rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
1082:                 lock_pick_proc();       /* avoid delay in scheduling MM */
1083:                 return;
1084:         }
1085: }
1086: 
1087: 
1088: /*===========================================================================*
1089:  *                              umap                                         *
1090:  *===========================================================================*/
1091: PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
1092: register struct proc *rp;       /* pointer to proc table entry for process */
1093: int seg;                        /* T, D, or S segment */
1094: vir_bytes vir_addr;             /* virtual address in bytes within the seg */
1095: vir_bytes bytes;                /* # of bytes to be copied */
1096: {
1097: /* Calculate the physical memory address for a given virtual address. */
1098: 
1099:   vir_clicks vc;                /* the virtual address in clicks */
1100:   phys_bytes pa;                /* intermediate variables as phys_bytes */
1101: #if (CHIP == INTEL)
1102:   phys_bytes seg_base;
1103: #endif
1104: 
1105:   /* If 'seg' is D it could really be S and vice versa.  T really means T.
1106:    * If the virtual address falls in the gap,  it causes a problem. On the
1107:    * 8088 it is probably a legal stack reference, since "stackfaults" are
1108:    * not detected by the hardware.  On 8088s, the gap is called S and
1109:    * accepted, but on other machines it is called D and rejected.
1110:    * The Atari ST behaves like the 8088 in this respect.
1111:    */
1112: 
1113:   if (bytes <= 0) return( (phys_bytes) 0);
1114:   vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;     /* last click of data */
1115: 
1116: #if (CHIP == INTEL) || (CHIP == M68000)
1117:   if (seg != T)
1118:         seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
1119: #else
1120:   if (seg != T)
1121:         seg = (vc < rp->p_map[S].mem_vir ? D : S);
1122: #endif
1123: 
1124:   if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
1125:         return( (phys_bytes) 0 );
1126: #if (CHIP == INTEL)
1127:   seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
1128:   seg_base = seg_base << CLICK_SHIFT;     /* segment origin in bytes */
1129: #endif
1130:   pa = (phys_bytes) vir_addr;
1131: #if (CHIP != M68000)
1132:   pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
1133:   return(seg_base + pa);
1134: #endif
1135: #if (CHIP == M68000)
1136:   pa -= (phys_bytes)rp->p_map[seg].mem_vir << CLICK_SHIFT;
1137:   pa += (phys_bytes)rp->p_map[seg].mem_phys << CLICK_SHIFT;
1138:   return(pa);
1139: #endif
1140: }
1141: 
1142: 
1143: /*==========================================================================*
1144:  *                              numap                                       *
1145:  *==========================================================================*/
1146: PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
1147: int proc_nr;                    /* process number to be mapped */
1148: vir_bytes vir_addr;             /* virtual address in bytes within D seg */
1149: vir_bytes bytes;                /* # of bytes required in segment  */
1150: {
1151: /* Do umap() starting from a process number instead of a pointer.  This
1152:  * function is used by device drivers, so they need not know about the
1153:  * process table.  To save time, there is no 'seg' parameter. The segment
1154:  * is always D.
1155:  */
1156: 
1157:   return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
1158: }
1159: 
1160: 
1161: /*==========================================================================*
1162:  *                              vir_copy                                            *
1163:  *==========================================================================*/
1164: PUBLIC int vir_copy(src_proc, src_vir, dst_proc, dst_vir, bytes)
1165: int src_proc;                   /* source process */
1166: vir_bytes src_vir;              /* source virtual address within D seg */
1167: int dst_proc;                   /* destination process */
1168: vir_bytes dst_vir;              /* destination virtual address within D seg */
1169: vir_bytes bytes;                /* # of bytes to copy  */
1170: {
1171: /* Copy bytes from one process to another.  Meant for the easy cases, where
1172:  * speed isn't required.  (One can normally do without one of the umaps.)
1173:  */
1174:   phys_bytes src_phys, dst_phys;
1175: 
1176:   src_phys = umap(proc_addr(src_proc), D, src_vir, bytes);
1177:   dst_phys = umap(proc_addr(dst_proc), D, dst_vir, bytes);
1178:   if (src_phys == 0 || dst_phys == 0) return(EFAULT);
1179:   phys_copy(src_phys, dst_phys, (phys_bytes) bytes);
1180:   return(OK);
1181: }
1182: 
1183: 
1184: #if (CHIP == INTEL)
1185: /*==========================================================================*
1186:  *                              alloc_segments                              *
1187:  *==========================================================================*/
1188: PUBLIC void alloc_segments(rp)
1189: register struct proc *rp;
1190: {
1191: /* This is called only by do_newmap, but is broken out as a separate function
1192:  * because so much is hardware-dependent.
1193:  */
1194: 
1195:   phys_bytes code_bytes;
1196:   phys_bytes data_bytes;
1197:   int privilege;
1198: 
1199:   if (protected_mode) {
1200:         data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
1201:                      << CLICK_SHIFT;
1202:         if (rp->p_map[T].mem_len == 0)
1203:                 code_bytes = data_bytes;        /* common I&D, poor protect */
1204:         else
1205:                 code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
1206:         privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
1207:         init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
1208:                      (phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
1209:                      code_bytes, privilege);
1210:         init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
1211:                      (phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
1212:                      data_bytes, privilege);
1213:         rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
1214: #if _WORD_SIZE == 4
1215:         rp->p_reg.gs =
1216:         rp->p_reg.fs =
1217: #endif
1218:         rp->p_reg.ss =
1219:         rp->p_reg.es =
1220:         rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
1221:   } else {
1222:         rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
1223:         rp->p_reg.ss =
1224:         rp->p_reg.es =
1225:         rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
1226:   }
1227: }
1228: #endif /* (CHIP == INTEL) */