1: /*
   2:  * Copyright (c) 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)machdep.c	2.4 (2.11BSD) 1999/9/13
   7:  */
   8: 
   9: #include "param.h"
  10: #include "../machine/psl.h"
  11: #include "../machine/reg.h"
  12: 
  13: #include "signalvar.h"
  14: #include "user.h"
  15: #include "proc.h"
  16: #include "buf.h"
  17: #include "map.h"
  18: #include "uba.h"
  19: #include "syslog.h"
  20: 
  21: #ifdef CURRENTLY_EXPANDED_INLINE
  22: /*
  23:  * Clear registers on exec
  24:  */
  25: setregs(entry)
  26:     u_int entry;
  27: {
  28:     u.u_ar0[PC] = entry & ~01;
  29:     u.u_fps.u_fpsr = 0;
  30: }
  31: #endif
  32: 
  33: /*
  34:  * Send an interrupt to process.
  35:  *
  36:  * Stack is set up to allow trampoline code stored at u.u_pcb.pcb_sigc (as
  37:  * specified by the user process) to call the user's real signal catch
  38:  * routine, followed by sys sigreturn to the sigreturn routine below (see
  39:  * /usr/src/lib/libc/pdp/sys/sigvec.s).  After sigreturn resets the signal
  40:  * mask, the stack, and the frame pointer, it returns to the user specified
  41:  * pc, ps.
  42:  */
  43: sendsig(p, sig, mask)
  44:     int (*p)(), sig;
  45:     long mask;
  46: {
  47:     struct sigframe {
  48:         int sf_signum;
  49:         int sf_code;
  50:         struct  sigcontext *sf_scp;
  51:         struct  sigcontext sf_sc;
  52:     };
  53:     struct sigframe sf;
  54:     register struct sigframe *sfp = &sf;
  55:     register struct sigcontext *scp = &sf.sf_sc;
  56:     register int *regs;
  57:     int oonstack;
  58:     caddr_t n;
  59: 
  60: #ifdef  DIAGNOSTIC
  61:     printf("sendsig %d to %d mask=%O action=%o\n", sig, u.u_procp->p_pid,
  62:         mask, p);
  63: #endif
  64:     regs = u.u_ar0;
  65:     oonstack = u.u_sigstk.ss_flags & SA_ONSTACK;
  66:     /*
  67: 	 * Allocate and validate space for the signal frame.
  68: 	 */
  69:     if  ((u.u_psflags & SAS_ALTSTACK) &&
  70:          !(u.u_sigstk.ss_flags & SA_ONSTACK) &&
  71:          (u.u_sigonstack & sigmask(sig)))
  72:         {
  73:         n = u.u_sigstk.ss_base + u.u_sigstk.ss_size - sizeof (sf);
  74:         u.u_sigstk.ss_flags |= SA_ONSTACK;
  75:         }
  76:     else
  77:         n = (caddr_t)regs[R6] - sizeof (sf);
  78:     if  (!(u.u_sigstk.ss_flags & SA_ONSTACK) &&
  79:          n < (caddr_t)-ctob(u.u_ssize) &&
  80:          !grow(n))
  81:         {
  82:         /*
  83: 		 * Process has trashed its stack; give it an illegal
  84: 		 * instruction violation to halt it in its tracks.
  85: 		 */
  86:         fatalsig(SIGILL);
  87:         return;
  88:         }
  89:     /*
  90: 	 * Build the argument list for the signal handler.
  91: 	 */
  92:     sfp->sf_signum = sig;
  93:     if (sig == SIGILL || sig == SIGFPE) {
  94:         sfp->sf_code = u.u_code;
  95:         u.u_code = 0;
  96:     } else
  97:         sfp->sf_code = 0;
  98:     sfp->sf_scp = (struct sigcontext *)
  99:             (n + (u_int)&((struct sigframe *)0)->sf_sc);
 100:     /*
 101: 	 * Build the signal context to be used by sigreturn.
 102: 	 */
 103:     scp->sc_onstack = oonstack;
 104:     scp->sc_mask = mask;
 105:     scp->sc_sp = regs[R6];
 106:     scp->sc_fp = regs[R5];
 107:     scp->sc_r1 = regs[R1];
 108:     scp->sc_r0 = regs[R0];
 109:     scp->sc_pc = regs[R7];
 110:     scp->sc_ps = regs[RPS];
 111:     scp->sc_ovno = u.u_ovdata.uo_ovbase ? u.u_ovdata.uo_curov : 0;
 112:     copyout((caddr_t)sfp, n, sizeof(*sfp));
 113:     regs[R0] = (int)p;
 114:     regs[R6] = (int)n;
 115:     regs[R7] = (int)u.u_pcb.pcb_sigc;
 116:     regs[RPS] &= ~PSL_T;
 117: }
 118: 
 119: /*
 120:  * System call to cleanup state after a signal
 121:  * has been taken.  Reset signal mask and
 122:  * stack state from context left by sendsig (above).
 123:  * Return to previous pc and ps as specified by
 124:  * context left by sendsig. Check carefully to
 125:  * make sure that the user has not modified the
 126:  * ps to gain improper priviledges or to cause
 127:  * a machine fault.
 128:  */
 129: sigreturn()
 130: {
 131:     struct a {
 132:         struct sigcontext *scp;
 133:     };
 134:     struct sigcontext sc;
 135:     register struct sigcontext *scp = &sc;
 136:     register int *regs = u.u_ar0;
 137: 
 138:     u.u_error = copyin((caddr_t)((struct a *)u.u_ap)->scp, (caddr_t *)scp, sizeof(*scp));
 139:     if (u.u_error)
 140:         return;
 141:     if ((scp->sc_ps & PSL_USERCLR) != 0 || !USERMODE(scp->sc_ps)) {
 142:         u.u_error = EINVAL;
 143:         return;
 144:     }
 145:     u.u_error = EJUSTRETURN;
 146:     if  (scp->sc_onstack & SA_ONSTACK)
 147:         u.u_sigstk.ss_flags |= SA_ONSTACK;
 148:     else
 149:         u.u_sigstk.ss_flags &= ~SA_ONSTACK;
 150:     u.u_procp->p_sigmask = scp->sc_mask & ~sigcantmask;
 151:     regs[R6] = scp->sc_sp;
 152:     regs[R5] = scp->sc_fp;
 153:     regs[R1] = scp->sc_r1;
 154:     regs[R0] = scp->sc_r0;
 155:     regs[R7] = scp->sc_pc;
 156:     regs[RPS] = scp->sc_ps;
 157: }
 158: 
 159: #define UMAPSIZ 10
 160: 
 161: struct  mapent _ubmap[UMAPSIZ];
 162: struct  map ub_map[1] = {
 163:     &_ubmap[0], &_ubmap[UMAPSIZ], "ub_map"
 164: };
 165: int ub_wantmr;
 166: 
 167: #ifdef UCB_METER
 168: struct ubmeter  ub_meter;
 169: #endif
 170: 
 171: /*
 172:  * Routine to allocate the UNIBUS map and initialize for a UNIBUS device.
 173:  * For buffers already mapped by the UNIBUS map, perform the physical to
 174:  * UNIBUS-virtual address translation.
 175:  */
 176: mapalloc(bp)
 177:     register struct buf *bp;
 178: {
 179:     register struct ubmap *ubp;
 180:     register int ub_nregs;
 181:     ubadr_t ubaddr;
 182:     long paddr;
 183:     int s, ub_first;
 184: 
 185:     if (!ubmap)
 186:         return;
 187: #ifdef UCB_METER
 188:     ++ub_meter.ub_calls;
 189: #endif
 190:     paddr = ((long)((u_int)bp->b_xmem)) << 16
 191:         | ((long)((u_int)bp->b_un.b_addr));
 192:     if (!(bp->b_flags & B_PHYS)) {
 193:         /*
 194: 		 * Transfer in the buffer cache.
 195: 		 * Change the buffer's physical address
 196: 		 * into a UNIBUS address for the driver.
 197: 		 */
 198: #ifdef UCB_METER
 199:         ++ub_meter.ub_remaps;
 200: #endif
 201:         ubaddr = paddr - (((ubadr_t)bpaddr) << 6) + BUF_UBADDR;
 202:         bp->b_un.b_addr = (caddr_t)loint(ubaddr);
 203:         bp->b_xmem = hiint(ubaddr);
 204:         bp->b_flags |= B_UBAREMAP;
 205:     }
 206:     else {
 207:         /*
 208: 		 * Physical I/O.
 209: 		 * Allocate a section of the UNIBUS map.
 210: 		 */
 211:         ub_nregs = (int)btoub(bp->b_bcount);
 212: #ifdef UCB_METER
 213:         ub_meter.ub_pages += ub_nregs;
 214: #endif
 215:         s = splclock();
 216:         while (!(ub_first = malloc(ub_map,ub_nregs))) {
 217: #ifdef UCB_METER
 218:             ++ub_meter.ub_fails;
 219: #endif
 220:             ub_wantmr = 1;
 221:             sleep(ub_map, PSWP + 1);
 222:         }
 223:         splx(s);
 224: 
 225:         ubp = &UBMAP[ub_first];
 226:         bp->b_xmem = ub_first >> 3;
 227:         bp->b_un.b_addr = (caddr_t)((ub_first & 07) << 13);
 228:         bp->b_flags |= B_MAP;
 229: 
 230:         while (ub_nregs--) {
 231:             ubp->ub_lo = loint(paddr);
 232:             ubp->ub_hi = hiint(paddr);
 233:             ubp++;
 234:             paddr += (ubadr_t)UBPAGE;
 235:         }
 236:     }
 237: }
 238: 
 239: mapfree(bp)
 240:     register struct buf *bp;
 241: {
 242:     register int s;
 243:     ubadr_t ubaddr;
 244:     long paddr;
 245: 
 246:     if (bp->b_flags & B_MAP) {
 247:         /*
 248: 		 * Free the UNIBUS map registers
 249: 		 * allocated to this buffer.
 250: 		 */
 251:         s = splclock();
 252:         mfree(ub_map, (size_t)btoub(bp->b_bcount), (bp->b_xmem << 3) |
 253:             (((u_int)bp->b_un.b_addr >> 13) & 07));
 254:         splx(s);
 255:         bp->b_flags &= ~B_MAP;
 256:         if (ub_wantmr)
 257:             wakeup((caddr_t) ub_map);
 258:         ub_wantmr = 0;
 259:     }
 260:     else if (bp->b_flags & B_UBAREMAP) {
 261:         /*
 262: 		 * Translate the UNIBUS virtual address of this buffer
 263: 		 * back to a physical memory address.
 264: 		 */
 265:         ubaddr = ((long)((u_int) bp->b_xmem)) << 16
 266:             | ((long)((u_int)bp->b_un.b_addr));
 267:         paddr = ubaddr - (long)BUF_UBADDR + (((long)bpaddr) << 6);
 268:         bp->b_un.b_addr = (caddr_t)loint(paddr);
 269:         bp->b_xmem = hiint(paddr);
 270:         bp->b_flags &= ~B_UBAREMAP;
 271:     }
 272: }
 273: 
 274: #define SOFUB_DEBUG
 275: 
 276: #ifdef  SOFUB_MAP
 277: /*
 278:  * Implement soft unibus map for 18 bit controllers present in a
 279:  * 22-bit q-bus systems.  Initially only used by the tape driver
 280:  * (for tar and dump) but when this was integrated into 2.11BSD changes
 281:  * were made to support the RX02 driver as well.
 282:  *
 283:  * Adapted to 2.11BSD and rather heavily revised by:
 284:  *
 285:  *		steven schultz (sms)
 286:  *		GTE Government Systems
 287:  *
 288:  *	from the original by:
 289:  *
 290:  *		matt jacob
 291:  *		University of California at Davis
 292:  *		22-Nov-84
 293: */
 294: 
 295: #define QMEG    ((long)(256L*1024L))
 296: #define exad(x,y)   ((long)((long)x<<16|(unsigned)y))
 297: #define B_UBUF      exad(bp->b_xmem,(u_int)bp->b_un.b_addr)
 298: #define E_UBUF      (B_UBUF + (long) bp->b_bcount)
 299: 
 300:     size_t  sofub_addr, sofub_off;
 301:     memaddr sofub_base;
 302:     unsigned sofub_size;
 303: 
 304: static  int bpxm, bpadd;
 305: static  int sofub_flags;
 306: #define BUSY    1
 307: #define WANTED  2
 308: 
 309: /*
 310:  * sofub_alloc - allocate usage of soft unibus map
 311:  *
 312:  *	called from strategy routine of device drivers.
 313:  *
 314:  *	returns 0 if not okay, else returns 1.
 315:  *	expects a buffer pointer as an argument
 316:  *	expects all addresses in bp already validated (by physio)
 317:  *	sets appropriate bits and calls iodone if error
 318: */
 319: 
 320: int
 321: sofub_alloc(bp)
 322: register struct buf *bp;
 323:     {
 324:     register int s;
 325:     register int count;
 326:     size_t uaddr;
 327:     memaddr sbase;
 328: 
 329:     if  (E_UBUF < QMEG)
 330:         return(1);  /* okay, < 256kb	*/
 331:     else if (bp->b_bcount > sofub_size)
 332:         {
 333:         log(LOG_ERR, "I/O >10kb on %d,%d\n",
 334:             major(bp->b_dev),minor(bp->b_dev));
 335:         bp->b_flags |= B_ERROR;
 336:         bp->b_error = EFAULT;
 337:         iodone(bp);
 338:         return(0);
 339:         }
 340: 
 341:     s = splbio();
 342: 
 343:     while   (sofub_flags & BUSY)
 344:         {
 345: #ifdef SOFUB_DEBUG
 346:         printf("sofub_alloc sleep\n");
 347: #endif
 348:         sofub_flags |= WANTED;
 349:         sleep((caddr_t) &sofub_flags,PSWP+2);
 350:         }
 351: 
 352:     sofub_flags |= BUSY;
 353:     splx(s);
 354: 
 355:     /*
 356: 	 * now calculate virtual address of user buffer...
 357: 	 */
 358: 
 359:     sofub_off = (size_t)((u_int)bp->b_un.b_addr & 077);
 360:     sofub_addr = (size_t)(((u_int)bp->b_un.b_addr>>6)&01777) | (((int) bp->b_xmem) << 10);
 361: 
 362:     bpadd = (u_int)bp->b_un.b_addr;
 363:     bpxm = bp->b_xmem;
 364: 
 365:     /*
 366: 	 * if this is a write, we have to fetch data from user buffer first
 367: 	 */
 368: 
 369:     if  ((bp->b_flags & B_READ) == 0)
 370:         {
 371:         count = bp->b_bcount;
 372:         uaddr = sofub_addr;
 373:         sbase = sofub_base;
 374: 
 375:         /* first, copy all 8kb-1click segments.. */
 376: 
 377:         s = spl5();
 378: 
 379:         while   (count > (8192-64))
 380:             {
 381:             copyv(uaddr,sofub_off,sbase,0,(8192-64));
 382:             count -= (8192-64);
 383:             uaddr += 0177;  /* add 8192-64 bytes */
 384:             sbase += 0177;
 385:             }
 386:         /* copy last residual segment */
 387: 
 388:         copyv(uaddr,sofub_off,sbase,0,count);
 389:         splx(s);
 390:         }
 391:     /* put in new 18 bit address */
 392: 
 393:     bp->b_un.b_addr = (caddr_t)ctob((long)sofub_base);
 394: 
 395:     /*
 396: 	 * don't turn sofub_base to clicks here
 397: 	 * because half the work is done by
 398: 	 * having it in click form here, i.e.,
 399: 	 * bp->b_xmem would equal
 400: 	 * ctob(x)>>16 (hi six bits of 18)
 401: 	 */
 402: 
 403:     bp->b_xmem = (sofub_base >> 10)&3;
 404:     return(1);
 405:     }
 406: 
 407: /*
 408:  * sofub_relse	- release sofub_map
 409:  *
 410:  *	passed a buffer pointer and a transfer byte count...
 411:  *	(for use if was a read)
 412:  *
 413:  *	note, we are called from the driver's interrupt service routine.
 414: */
 415: 
 416: sofub_relse(bp,count)
 417: register struct buf *bp;
 418: register unsigned count;
 419:     {
 420:     register int s;
 421:     size_t uaddr;
 422:     memaddr sbase;
 423:     long    ebuf = E_UBUF;
 424:     caddr_t newaddr;
 425:     u_int   newxmem;
 426: 
 427: /*
 428:  * If the transfer was entirely below or above the 'bounce buffer' then
 429:  * this I/O request was done without the soft map being allocated.
 430: */
 431:     if  (ebuf < ctob((long)sofub_base) ||
 432:          ebuf > ctob((long)sofub_base) + sofub_size)
 433:         return;
 434: #ifdef  SOFUB_DEBUG
 435:     if  (ebuf > QMEG)       /* Can't happen, transfer over 256kb */
 436:         panic("sofub_relse");
 437: #endif
 438: 
 439: /*
 440:  * Next make sure that the I/O request is the one which currently has the
 441:  * map allocated to it.
 442: */
 443:     newaddr = (caddr_t)((sofub_addr << 6) | sofub_off);
 444:     newxmem = ((u_int)sofub_addr >> 10) & 077;
 445: 
 446:     if  (newaddr != bpadd ||  newxmem != bpxm)
 447:         {
 448: #ifdef  SOFUB_DEBUG
 449:         printf("sofub_relse: new %o:%o, old %o:%o\n",
 450:             newxmem, newaddr, bpxm, bpadd);
 451: #endif
 452:         bp->b_flags |= B_ERROR;
 453:         bp->b_error = EFAULT;
 454:         return;
 455:         }
 456: 
 457:     if  (bp->b_flags & B_READ)
 458:         {
 459:         uaddr = sofub_addr;
 460:         sbase = sofub_base;
 461: 
 462:         /*
 463: 		 * first, copy all 8kb-1click segments..
 464: 		 */
 465:         s = spl5();
 466:         while   (count > (8192-64))
 467:             {
 468:             copyv(sbase,0,uaddr,sofub_off,(8192-64));
 469:             count -= (8192-64);
 470:             uaddr += 0177;  /* add 8192-64 bytes */
 471:             sbase += 0177;
 472:             }
 473:         /*
 474: 		 * copy last residual segment
 475: 		 */
 476:         copyv(sbase,0,uaddr,sofub_off,count);
 477:         splx(s);
 478:         }
 479: 
 480:     bp->b_un.b_addr = newaddr;
 481:     bp->b_xmem = newxmem;
 482: 
 483:     sofub_flags &= ~BUSY;
 484: 
 485:     if  (sofub_flags & WANTED)
 486:         {
 487: #ifdef  SOFUB_DEBUG
 488:         printf("sofub_relse: wakeup\n");
 489: #endif
 490:         sofub_flags &= ~WANTED;
 491:         wakeup((caddr_t) &sofub_flags);
 492:         }
 493:     }
 494: #endif	/* SOFUB_MAP */

Defined functions

mapfree defined in line 239; used 1 times
sendsig defined in line 43; used 1 times
setregs defined in line 25; never used
sigreturn defined in line 129; used 2 times

Defined variables

_ubmap defined in line 161; used 2 times
  • in line 163(2)
bpadd defined in line 304; used 3 times
bpxm defined in line 304; used 3 times
sofub_addr defined in line 300; used 6 times
sofub_base defined in line 301; used 12 times
sofub_flags defined in line 305; used 8 times
sofub_off defined in line 300; used 7 times
sofub_size defined in line 302; used 3 times
ub_map defined in line 162; used 13 times
ub_meter defined in line 168; used 4 times
ub_wantmr defined in line 165; used 6 times

Defined struct's

a defined in line 131; used 2 times
  • in line 138(2)
sigframe defined in line 47; used 6 times

Defined macros

BUSY defined in line 306; used 3 times
B_UBUF defined in line 297; used 1 times
E_UBUF defined in line 298; used 2 times
QMEG defined in line 295; used 2 times
SOFUB_DEBUG defined in line 274; used 4 times
UMAPSIZ defined in line 159; used 2 times
WANTED defined in line 307; used 3 times
exad defined in line 296; used 1 times
Last modified: 1999-09-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4276
Valid CSS Valid XHTML 1.0 Strict