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 = ≻ 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 */