1: /* 2: * Copyright (c) 1987 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: * @(#)mch_trap.s 2.2 (2.11BSD GTE) 1/9/94 7: */ 8: #include "DEFS.h" 9: #include "../machine/mch_iopage.h" 10: #include "../machine/koverlay.h" 11: #include "../machine/trap.h" 12: 13: 14: SPACE(LOCAL, saveps, 2) 15: 16: /* 17: * jsr r0,call 18: * jmp trap_handler 19: * 20: * mov PS,saveps 21: * jsr r0,call1 22: * jmp trap_handler 23: * 24: * Interrupt interface code to C. Creates an interrupt stack frame, calls 25: * the indicated trap_handler. Call forces the previous mode to be user so 26: * that copy in/out and friends use user space if called from interrupt 27: * level. Call1 is simply an alternate entry to call that assumes that the 28: * PS has already been changed and the original PS can be found in saveps. 29: * Call1 also doesn't increment cnt.v_intr since it's only called from 30: * synchronous software traps. 31: * 32: * The interrupt stack frame - note that values in <pdp/reg.h> must agree: 33: * 34: * reg.h 35: * | ps | 2 / ps and pc saved by interrupt 36: * | pc | 1 37: * u.u_ar0 | r0 | 0 38: * | nps | / from interrupt vector 39: * | ovno | 40: * | r1 | -3 41: * | sp | -4 42: * | code | / nps & 037 43: * --------------------------------/ above belongs to call, below to csv 44: * | ret | / return address to call 45: * r5 | old r5 | -7 46: * | ovno | 47: * | r4 | -9 48: * | r3 | -10 49: * | r2 | -11 50: * sp | *empty* | 51: */ 52: call1: 53: mov saveps,-(sp) / stuff saved nps into interrupt frame 54: SPLLOW / ensure low priority (why?) 55: br 1f / branch around count of interrupts 56: 57: ASENTRY(call) 58: /* 59: * Interrupt entry code. Save various registers, etc., and call 60: * interrupt service routine. 61: */ 62: mov PS,-(sp) / stuff nps into interrupt frame 63: #ifdef UCB_METER 64: inc _cnt+V_INTR / cnt.v_intr++ 65: #endif 66: 1: 67: mov __ovno,-(sp) / save overlay number, 68: mov r1,-(sp) / r1, 69: mfpd sp / sp 70: mov 6(sp),-(sp) / grab nps and calculate 71: bic $!37,(sp) / code = nps & 037 72: bis $30000,PS / force previous mode = user 73: jsr pc,(r0) / call trap_handler 74: #ifdef INET 75: /* 76: * Check for scheduled network service requests. The network sets 77: * _knetisr to schedule network activity at a later time when the 78: * system IPL is low and things are ``less hectic'' ... 79: */ 80: mov PS,-(sp) / set SPL7 so _knetisr doesn't get 81: SPL7 / changed while we're looking at it 82: tst _knetisr / if (_knetisr != 0 83: beq 2f 84: bit $340,20(sp) / && interrupted IPL == 0 85: bne 2f / [shouldn't we check against SPLNET?] 86: cmp sp,$_u / && sp > _u (not on interrupt stack)) 87: blos 2f 88: #ifdef UCB_METER 89: inc _cnt+V_SOFT / increment soft interrupt counter, 90: #endif 91: clr _knetisr / reset the flag, 92: SPLNET / set network IPL, 93: clr -(sp) / and KScall(netintr, 0) 94: mov $_netintr,-(sp) 95: jsr pc,_KScall 96: cmp (sp)+,(sp)+ 97: 2: 98: mov (sp)+,PS / restore PS 99: #endif 100: /* 101: * Clean up from interrupt. If previous mode was user and _runrun 102: * is set, generate an artificial SWITCHTRAP so we can schedule in a 103: * new process. 104: */ 105: bit $20000,10(sp) / previous mode = user?? 106: beq 4f 107: tstb _runrun / yep, is the user's time up? 108: beq 3f 109: mov $T_SWITCHTRAP,(sp) / yep, set code to T_SWITCHTRAP 110: jsr pc,_trap / and give up cpu 111: 3: 112: /* 113: * Trap from user space: toss code and reset user's stack pointer. 114: */ 115: tst (sp)+ / toss code, reset user's sp 116: mtpd sp / and enter common cleanup code 117: br 5f 118: 4: 119: /* 120: * Trap from kernel or supervisor space: toss code and stack pointer 121: * (only user stack pointers need to be set or reset). 122: */ 123: cmp (sp)+,(sp)+ / trap from kernel or supervisor: 124: 5: / toss code and sp 125: /* 126: * Finish final clean up, restore registers, etc. make sure we 127: * leave the same overlay mapped that we came in on, and return 128: * from the interrupt. 129: */ 130: mov (sp)+,r1 / restore r1 131: 132: mov (sp)+,r0 / current overlay different from 133: cmp r0,__ovno / interrupted overlay? 134: beq 6f 135: SPL7 / yes, go non-interruptable (rtt 136: / below restores PS) 137: mov r0,__ovno / reset ovno and mapping for 138: asl r0 / interrupted overlay 139: mov ova(r0),OVLY_PAR 140: mov ovd(r0),OVLY_PDR 141: 6: 142: tst (sp)+ / toss nps 143: mov (sp)+,r0 / restore r0 144: rtt / and return from the trap ... 145: 146: 147: #ifdef INET 148: /* 149: * iothndlr is used to allow the network in supervisor mode to make calls 150: * to the kernel. 151: * 152: * the network pushes a <pc,ps> pair on the kernel stack before doing the 153: * 'iot'. when we process the iot here we throw the saved <pc,ps> pair 154: * resulting from the 'iot' away and use instead the pair pushed by the 155: * network as the target for our 'rtt'. 156: * 157: * there was a warning that this hasn't been tested with overlays in the 158: * kernel. can't see why it wouldn't work. 159: */ 160: ASENTRY(iothndlr) 161: mov PS,saveps / save PS in case we have to trap 162: bit $20000,PS / previous mode = supervisor? 163: bne trap1 / (no, let trap handle it) 164: bit $10000,PS 165: beq trap1 / (no, let trap handle it) 166: cmp (sp)+,(sp)+ / yes, toss iot frame and execute rtt 167: rtt / on behalf of networking kernel 168: #endif 169: 170: 171: /* 172: * System call interface to C code. Creates a fake interrupt stack frame and 173: * then vectors on to the real syscall handler. It's not necessary to 174: * create a real interrupt stack frame with everything in the world saved 175: * since this is a synchronous trap. 176: */ 177: ASENTRY(syscall) 178: mov PS,saveps / save PS just in case we need to trap 179: bit $20000,PS / trap from user space? 180: beq trap2 / no, die 181: mov r0,-(sp) 182: cmp -(sp),-(sp) / fake __ovno and nps - not needed 183: mov r1,-(sp) 184: mfpd sp / grab user's sp for argument addresses 185: tst -(sp) / fake code - not needed 186: jsr pc,_syscall / call syscall and start cleaning up 187: tst (sp)+ 188: mtpd sp / reload user sp, r1 and r0 189: mov (sp)+,r1 / (cret already reloaded the other 190: cmp (sp)+,(sp)+ / registers) 191: mov (sp)+,r0 192: rtt / and return from the trap 193: 194: 195: /* 196: * Emt takes emulator traps, which are requests to change the overlay for the 197: * current process. If an invalid emt is received, _trap is called. Note 198: * that choverlay is not called with a trap frame - only r0 and r1 are saved; 199: * it's not necessary to save __ovno as this is a synchronous trap. 200: */ 201: ASENTRY(emt) 202: mov PS,saveps / save PS just in case we need to trap 203: bit $20000,PS / if the emt isn't from user mode, 204: beq trap2 / or, the process isn't overlaid, 205: tst _u+U_OVBASE / or the requested overlay number 206: beq trap2 / isn't valid, enter _trap 207: cmp r0,$NOVL 208: bhi trap2 209: mov r0,-(sp) / everything's cool, save r0 and r1 210: mov r1,-(sp) / so they don't get trashed 211: mov r0,_u+U_CUROV / u.u_curov = r0 212: mov $RO,-(sp) / map the overlay in read only 213: #ifdef UCB_METER 214: inc _cnt+V_OVLY / cnt.v_ovly++ 215: #endif 216: add $1,_u+U_RU+RU_OVLY+2 / u.u_ru.ru_ovly++ 217: adc _u+U_RU+RU_OVLY 218: jsr pc,_choverlay / and get choverlay to bring the overlay in 219: tst (sp)+ / toss choverlay's paramter, 220: mov (sp)+,r1 / restore r0 and r1, 221: mov (sp)+,r0 222: rtt / and return from the trap 223: 224: 225: /* 226: * Traps without specialized catchers get vectored here. We re-enable memory 227: * management because the fault that caused this trap may have been a memory 228: * management fault which sometimes causes the contents of the memory managment 229: * registers to be frozen so error recovery can be attempted. 230: */ 231: ASENTRY(trap) 232: mov PS,saveps / save PS for call1 233: trap1: 234: tst nofault / if someone's already got this trap 235: bne catchfault / scoped out, give it to them 236: /* 237: * save current values of memory management registers in case we 238: * want to back up the instruction that failed 239: */ 240: mov SSR0,ssr 241: #ifndef KERN_NONSEP 242: mov SSR1,ssr+2 243: #endif 244: mov SSR2,ssr+4 245: mov $1,SSR0 / re-enable relocation 246: trap2: 247: jsr r0,call1; jmp _trap / and let call take us in to _trap ... 248: /*NOTREACHED*/ 249: 250: 251: /* 252: * We branch here when we take a trap and find that the variable nofault is 253: * set indicating that someone else is interested in taking the trap. 254: */ 255: catchfault: 256: mov $1,SSR0 / re-enable memory management 257: mov nofault,(sp) / relocation, fiddle with the 258: rtt / machine trap frame and boogie 259: 260: 261: /* 262: * Power fail handling. On power down, we just set up for the next trap. 263: * On power up we attempt an autoboot ... 264: */ 265: #define PVECT 24 / power fail vector 266: 267: ASENTRY(powrdown) 268: mov $powrup,PVECT / on power up, trap to powrup, 269: SPL7 / and loop at high priority 270: br . 271: 272: #ifndef KERN_NONSEP 273: .data 274: #endif 275: /* 276: * Power back on... wait a bit, then attempt a reboot. Can't do much 277: * since memory management is off (hence we are in "data" space). 278: */ 279: powrup: 280: /* 281: * Not sure why these are necessary except that on a 44 it appears 282: * that the first instruction or two of a power up trap do not 283: * execute properly. 284: */ 285: nop;nop;nop 286: /* 287: * The nested loop below gives 38 seconds of delay on a 11/44 (30 sec 288: * on a 11/93) for controllers to complete selftest after power comes 289: * back up. 290: */ 291: mov $400.,r0 292: 2: 293: clr r1 294: 3: nop 295: sob r1,3b 296: sob r0,2b 297: 298: mov $RB_POWRFAIL,r4 / and try to reboot ... 299: mov _bootdev,r3 300: /* 301: * 'jsr' can not be used because there is no stack at the moment (battery 302: * backup preserves memory but not registers). 'hardboot' sets up a stack 303: * if it needs one, so it is not necessary to do that here. 304: */ 305: jmp *$hardboot 306: /*NOTREACHED*/ 307: .text