~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Minix Cross Reference
Minix/kernel/system.c


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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.