|
|
1.1 root 1: /* locore.s 4.50 81/05/18 */
2: # -------------------
3:
4: #include "../machine/mtpr.h"
5: #include "../machine/trap.h"
6: #include "../machine/psl.h"
7: #include "../machine/pte.h"
8: #include "../machine/cp.h"
9: #include "../machine/mem.h"
10:
11: #include "../h/errno.h"
12:
13: .set HIGH,0x1f # mask for total disable
14: .set BERVEC,0x80 # offset into scb of the bus error vector
15: .set RESTVEC,0x8 # offset into scb of the restart vector
16: .set MAXPHYSMEM,8*1024*1024-1 # max physical memory
17: # while we work on CMD/32M !
18: # look at vmsched.c to see why.
19: .set MEMUNIT,64*1024 # minimum memory increment
20:
21: .set NISP,3 # number of interrupt stack pages
22: .set SYSTEM,0xC0000000 # virtual address of system start
23: .set PPAGES,0x100000 # Number of possible pages in P0,P1, etc.
24:
25: /* ACBL for non-negative '_add' */
26: #define ACBL(_limit,_add,_index,_displ) \
27: addl2 _add,_index; \
28: cmpl _index,_limit; \
29: bleq _displ
30:
31: /* _ACBL for negative '_add' */
32: #define _ACBL(_limit,_add,_index,_displ) \
33: addl2 _add,_index; \
34: cmpl _index,_limit; \
35: bgeq _displ
36:
37: #define MOVC3(_len,_srcaddr,_dstaddr) \
38: movl _srcaddr,r0; \
39: movl _dstaddr,r1; \
40: movl _len,r2; \
41: movblk
42:
43: /* Keep address of psl if coming from user mode */
44: #define CHECK_SFE(_delta) \
45: bitl $PSL_CURMOD,_delta(sp); \
46: jeql 1f; \
47: moval _delta(sp),_user_psl; \
48: 1:
49:
50: /*
51: * User structure is UPAGES at top of user space.
52: */
53: .globl _u
54: .set _u,SYSTEM - UPAGES*NBPG
55:
56: /*
57: * Restart stack. Used on power recovery or panic.
58: * Takes a core-dump and then halts.
59: */
60: .globl _rsstk
61:
62: _rsstk: .space 1024-8
63: .globl pwfl_stk
64: pwfl_stk: .space 4
65: dumpflag: .space 4
66:
67: .globl _intstack
68: _intstack:
69: .space NISP*NBPG
70: eintstack:
71:
72: .data
73: .globl pwfl_r0
74: pwfl_r0: .space 14*4 # Enough for r0 - r13
75: .globl pwfl_sp
76: pwfl_sp: .long 0x12345678 # r14
77: .globl pwfl_SCBB
78: pwfl_SCBB: .long 0x12345678
79: .globl pwfl_SBR
80: pwfl_SBR: .long 0x12345678
81: .globl pwfl_SLR
82: pwfl_SLR: .long 0x12345678
83: .globl pwfl_P0BR
84: pwfl_P0BR: .long 0x12345678
85: .globl pwfl_P0LR
86: pwfl_P0LR: .long 0x12345678
87: .globl pwfl_P1BR
88: pwfl_P1BR: .long 0x12345678
89: .globl pwfl_P1LR
90: pwfl_P1LR: .long 0x12345678
91: .globl pwfl_P2BR
92: pwfl_P2BR: .long 0x12345678
93: .globl pwfl_P2LR
94: pwfl_P2LR: .long 0x12345678
95: .globl pwfl_IPL
96: pwfl_IPL: .long 0x12345678
97: .globl pwfl_DCK
98: pwfl_DCK: .long 0x12345678
99: .globl pwfl_CCK
100: pwfl_CCK: .long 0x12345678
101: .globl pwfl_PCBB
102: pwfl_PCBB: .long 0x12345678
103: .globl pwfl_ISP
104: pwfl_ISP: .long 0x12345678
105: .globl pwfl_KSP
106: pwfl_KSP: .long 0x12345678
107: .globl pwfl_USP
108: pwfl_USP: .long 0x12345678
109: .globl pwfl_MME
110: pwfl_MME: .long 0x12345678
111: .globl pwfl_PSL
112: pwfl_PSL: .long 0x12345678
113:
114: /*
115: * Do a dump.
116: * Called by auto-restart.
117: * May be called manually.
118: */
119: .align 2
120: .text
121: .globl _Xdoadump
122: .globl _doadump
123: _Xdoadump: # CP brings Tahoe here on power recovery
124: loadr $0x3fff,pwfl_r0 # Restore r0 - r13
125: movl pwfl_sp,sp # Restore sp ( = r14 )
126: mtpr pwfl_SCBB,$SCBB
127: mtpr pwfl_SBR,$SBR # Restore all re_loadable registers
128: mtpr pwfl_SLR,$SLR
129: mtpr pwfl_P0BR,$P0BR
130: mtpr pwfl_P0LR,$P0LR
131: mtpr pwfl_P1BR,$P1BR
132: mtpr pwfl_P1LR,$P1LR
133: mtpr pwfl_P2BR,$P2BR
134: mtpr pwfl_P2LR,$P2LR
135: mtpr pwfl_IPL,$IPL
136: mtpr pwfl_DCK,$DCK
137: mtpr pwfl_CCK,$CCK
138: mtpr pwfl_PCBB,$PCBB
139: mtpr pwfl_ISP,$ISP
140: mtpr pwfl_KSP,$KSP
141: mtpr pwfl_USP,$USP
142:
143: /* now go to mapped mode */
144: /* Have to change PC to system addresses */
145: mtpr $1,$PACC # Thoroughly clean up caches.
146: mtpr $1,$PADC
147: mtpr $1,$TBIA
148: mtpr pwfl_MME,$MME
149: # Restore PSW. Last thing to be done.
150: bicpsw $0xff
151: bispsw pwfl_PSL+2 # Set original bits back (just in case..)
152: jmp *$0f
153: _doadump:
154: .word 0
155: #define _rsstkmap _Sysmap+12
156: # Tahoe storage, scb, rsstk, interrupt stack
157: 0:
158: mtpr $HIGH,$IPL
159: andl2 $0!PG_PROT,_rsstkmap
160: orl2 $PG_KW,_rsstkmap # Make dump stack r/w
161: tstl dumpflag # dump only once!
162: bneq 1f
163: movl $1,dumpflag
164: mtpr $0,$TBIA
165: movab dumpflag,sp
166: callf $4,_dumpsys
167: 1:
168: halt
169:
170: /*
171: * Interrupt vector routines
172: */
173: .globl _waittime
174:
175: #define SCBVEC(name) \
176: .align 2; \
177: .globl _X/**/name; \
178: _X/**/name
179: #define PANIC(msg) clrl _waittime; pushab 1f; \
180: callf $8,_panic; 1: .asciz msg
181: #define PRINTF(n,msg) pushab 1f; callf $(n+2)*4,_printf; MSG(msg)
182: #define MSG(msg) .data; 1: .asciz msg; .text
183:
184: # these registers are not restored by the C-compiler.
185: #define PUSHR pushl r0; pushl r1;
186: #define POPR movl (sp)+, r1; movl (sp)+, r0;
187: # mask for error code on stack.
188:
189: SCBVEC(buserr):
190: CHECK_SFE(12)
191: PUSHR
192: andl3 12(sp),$ERRCD,r0
193: jeql go_on
194: cmpl r0,$APE
195: jneq 1f
196: halt # Address parity error !!!
197: 1: cmpl r0,$VBE
198: jneq go_on
199: halt # Versabus error !!!
200: go_on:
201: pushab 2*4(sp) # Pointer to parameters
202: callf $8,_buserror
203: POPR
204: movab 8(sp),sp # Remove hardware parameters
205: rei
206:
207: SCBVEC(powfail): # We should be on interrupt stack now.
208: movpsl pwfl_PSL # Keeps all flags, etc.
209: storer $0x3fff,pwfl_r0 # Saves r0 - r13
210: moval 0(sp),pwfl_sp # Saves sp ( = r14 )
211: mfpr $SBR,pwfl_SBR # Save all re_loadable registers
212: mfpr $SLR,pwfl_SLR
213: mfpr $P0BR,pwfl_P0BR
214: mfpr $P0LR,pwfl_P0LR
215: mfpr $P1BR,pwfl_P1BR
216: mfpr $P1LR,pwfl_P1LR
217: mfpr $P2BR,pwfl_P2BR
218: mfpr $P2LR,pwfl_P2LR
219: mfpr $IPL,pwfl_IPL
220: mfpr $MME,pwfl_MME
221: mfpr $DCK,pwfl_DCK
222: mfpr $CCK,pwfl_CCK
223: mfpr $PCBB,pwfl_PCBB
224: mfpr $ISP,pwfl_ISP
225: mfpr $SCBB,pwfl_SCBB
226: mfpr $KSP,pwfl_KSP
227: mfpr $USP,pwfl_USP
228: moval _Xdoadump-SYSTEM,_scb+RESTVEC
229: halt
230:
231: SCBVEC(stray):
232: PUSHR; PRINTF(0, "******* Undefined interrupt *******\n"); POPR;
233: rei
234: SCBVEC(soft15):
235: SCBVEC(soft14):
236: SCBVEC(soft13):
237: SCBVEC(soft12):
238: SCBVEC(soft11):
239: SCBVEC(soft10):
240: #ifndef SIMIO
241: SCBVEC(soft9):
242: #endif
243: SCBVEC(soft7):
244: SCBVEC(soft6):
245: SCBVEC(soft5):
246: SCBVEC(soft4):
247: #ifndef SIMIO
248: SCBVEC(soft3):
249: SCBVEC(soft2):
250: SCBVEC(soft1):
251: #endif
252: PUSHR
253: PRINTF(0, "******* Undefined software interrupt *******\n")
254: POPR;
255: rei
256:
257: #ifdef SIMIO
258: SCBVEC(soft2):
259: #endif
260: SCBVEC(cnrint):
261: CHECK_SFE(4)
262: PUSHR; pushl $CPCONS; callf $8,_cnrint; POPR; incl _cnt+V_INTR; rei
263: #ifdef SIMIO
264: SCBVEC(soft3):
265: #endif
266: SCBVEC(cnxint):
267: CHECK_SFE(4)
268: PUSHR; pushl $CPCONS; callf $8,_cnxint; POPR; incl _cnt+V_INTR; rei
269: SCBVEC(rmtrint):
270: CHECK_SFE(4)
271: PUSHR; pushl $CPREMOT; callf $8,_cnrint; POPR; incl _cnt+V_INTR; rei
272: SCBVEC(rmtxint):
273: CHECK_SFE(4)
274: PUSHR; pushl $CPREMOT; callf $8,_cnxint; POPR; incl _cnt+V_INTR; rei
275: #ifdef SIMIO
276: SCBVEC(soft9):
277: #endif
278: SCBVEC(hardclock):
279: CHECK_SFE(4)
280: PUSHR
281: pushl 4+2*4(sp); pushl 4+2*4(sp);
282: callf $12,_hardclock # hardclock(pc,psl)
283: POPR;
284: incl _cnt+V_INTR ## temp so not to break vmstat -= HZ
285: rei
286: SCBVEC(softclock):
287: CHECK_SFE(4)
288: PUSHR
289: pushl 4+2*4(sp); pushl 4+2*4(sp);
290: callf $12,_softclock # softclock(pc,psl)
291: POPR;
292: rei
293:
294: /*
295: * Trap and fault vector routines
296: */
297: #define TRAP(a) pushl $T_/**/a; jbr alltraps
298:
299: /*
300: * Ast delivery (profiling and/or reschedule)
301: */
302: /*
303: * When we want to reschedule we will force a memory fault by setting the m.s.b
304: * of P0LR. Then , on memory fault if m.s.b of P0LR is on we will clear it and
305: * TRAP(astflt).
306: *
307: */
308:
309: # if this bit is on it is an ast.
310: #define ASTBIT 0x00100000
311: #define P0MASK 0xc0000000
312:
313: SCBVEC(kspnotval):
314: CHECK_SFE(4)
315: pushl $0; TRAP(KSPNOTVAL)
316: SCBVEC(privinflt):
317: CHECK_SFE(4)
318: pushl $0; TRAP(PRIVINFLT)
319: SCBVEC(resopflt):
320: CHECK_SFE(4)
321: pushl $0; TRAP(RESOPFLT)
322: SCBVEC(resadflt):
323: CHECK_SFE(4)
324: pushl $0; TRAP(RESADFLT)
325: SCBVEC(bptflt):
326: CHECK_SFE(4)
327: pushl $0; TRAP(BPTFLT)
328: SCBVEC(tracep):
329: CHECK_SFE(4)
330: pushl $0; TRAP(TRCTRAP)
331: SCBVEC(alignflt):
332: CHECK_SFE(4)
333: pushl $0; TRAP(ALIGNFLT)
334: SCBVEC(arithtrap):
335: CHECK_SFE(8)
336: TRAP(ARITHTRAP)
337:
338: SCBVEC(protflt):
339: CHECK_SFE(12)
340: bitl $1,(sp)+
341: jneq segflt
342: TRAP(PROTFLT)
343: segflt:
344: TRAP(SEGFLT)
345:
346: SCBVEC(fpm): # Floating Point eMulation
347: .globl _fpemulate
348: CHECK_SFE(24)
349: callf $24,_fpemulate # We want psl, pc and opcode
350: # not to be removed by the ret.
351:
352: # Don't modify registers now !!
353: tstl (sp) # Stack= PSL, PC, return_code
354: jneq _Xarithtrap # If not OK, emulate F.P. exception
355: movab 4(sp),sp # Else remove return_code and
356: rei
357:
358: SCBVEC(sfexcep):
359: CHECK_SFE(4)
360: pushl $0
361: TRAP(ASTFLT)
362:
363: SCBVEC(transflt):
364: CHECK_SFE(12)
365: bitl $1,(sp)+
366: bneq tableflt
367: pageflt:
368: TRAP(PAGEFLT)
369: tableflt:
370: TRAP(TABLEFLT)
371:
372: alltraps:
373: mfpr $USP,-(sp); callf $4,_trap; mtpr (sp)+,$USP
374: incl _cnt+V_TRAP
375: movab 8(sp),sp # pop type, code
376: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
377: rei
378:
379: SCBVEC(syscall):
380: CHECK_SFE(8)
381: pushl $T_SYSCALL
382: mfpr $USP,-(sp); callf $4,_syscall; mtpr (sp)+,$USP
383: incl _cnt+V_SYSCALL
384: movab 8(sp),sp # pop type, code
385: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
386: rei
387:
388: /*
389: * System page table
390: */
391: #define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+SYSTEM)
392: #define SYSMAP(mname, vname, npte) \
393: _/**/mname: .globl _/**/mname; \
394: .space npte*4; \
395: .globl _/**/vname; \
396: .set _/**/vname,vaddr(_/**/mname)
397:
398: .data
399: .align 2
400: SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE )
401: SYSMAP(VMEMbeg ,vmembeg ,0 )
402: SYSMAP(VMEMmap ,vmem ,IOSIZE )
403: SYSMAP(VMEMend ,vmemend ,0 )
404: SYSMAP(Usrptmap ,usrpt ,USRPTSIZE )
405: SYSMAP(Forkmap ,forkutl ,UPAGES )
406: SYSMAP(Xswapmap ,xswaputl ,UPAGES )
407: SYSMAP(Xswap2map,xswap2utl ,UPAGES )
408: SYSMAP(Swapmap ,swaputl ,UPAGES )
409: SYSMAP(Pushmap ,pushutl ,UPAGES )
410: SYSMAP(Vfmap ,vfutl ,UPAGES )
411: /*
412: SYSMAP(IOmap ,ioutl ,(MAXBPTE+1) )
413: */
414: SYSMAP(VDmap ,vdutl ,(MAXBPTE+1) )
415: SYSMAP(CYmap ,cyutl ,(TBUFSIZ+1) )
416: SYSMAP(CMAP1 ,CADDR1 ,1 )
417: SYSMAP(CMAP2 ,CADDR2 ,1 )
418: SYSMAP(mmap ,vmmap ,1 )
419: SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT )
420: SYSMAP(camap ,cabase ,16*CLSIZE )
421: SYSMAP(ecamap ,calimit ,0 )
422: SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*CLSIZE)
423: eSysmap:
424: .globl _Syssize
425: .set _Syssize,(eSysmap-_Sysmap)/4
426:
427: .text
428: /*
429: * Initialization
430: *
431: * IPL 0x1f; MME 0; scbb, pcbb, sbr, slr, isp, ksp not set
432: *
433: */
434:
435: .align 2
436: .globl start
437: start:
438: .word 0
439:
440: /* set system control block base and system page table params */
441:
442: mtpr $_scb-SYSTEM,$SCBB
443: mtpr $_Sysmap-SYSTEM,$SBR
444: mtpr $_Syssize,$SLR
445:
446: /* double map the kernel into the virtual user addresses of phys mem */
447: /* (to be on the safe side.This is supposed to run in system sace. ) */
448: mtpr $_Sysmap,$P0BR
449: mtpr $_Syssize,$P0LR
450:
451: mtpr $_Sysmap,$P1BR # Against Murphy
452: mtpr $_Syssize,$P1LR
453:
454: /* set ISP */
455: movl $_intstack-SYSTEM+NISP*NBPG,sp # Still physical !
456: mtpr $_intstack+NISP*NBPG,$ISP
457:
458: /* count up memory */
459:
460: clrl r7
461: 1: pushl $1; pushl r7; callf $12,_badaddr; tstl r0; bneq 9f
462: addl2 $MEMUNIT,r7
463: cmpl r7,$MAXPHYSMEM
464: bleq 1b
465: 9:
466: /* clear memory from kernel bss and pages for proc 0 u. and page table */
467: movab _edata,r6
468: movab _end,r5
469: andl2 $0!SYSTEM,r6
470: andl2 $0!SYSTEM,r5
471: addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5
472: 1: clrl (r6); ACBL( r5,$4,r6,1b)
473:
474: /* trap() and syscall() save r0-r13 in the entry mask (per ../h/reg.h) */
475: /* For floating point emulation, we do same for 'fpemulate' */
476: orw2 $0x01fff,_trap
477: orw2 $0x01fff,_syscall
478: orw2 $0x01fff,_fpemulate
479:
480: /* initialize system page table: scb and int stack writeable */
481: clrl r2
482: movab eintstack,r1
483: andl2 $0!SYSTEM,r1
484: shrl $PGSHIFT,r1,r1 # r1-page number of eintstack.
485:
486: /* Start by making the processor storage read/only */
487:
488: orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2;
489: orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2;
490:
491: /* Other parts of the system are read/write for kernel */
492:
493: 1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; # data:kernel write + phys=virtual
494: aoblss r1,r2,1b
495:
496: /* make rsstk read-only as red zone for interrupt stack */
497: andl2 $0!PG_PROT,_rsstkmap
498: orl2 $PG_V|PG_KR,_rsstkmap # Make dump stack r/w
499:
500: /* make kernel text space read-only */
501: /*
502: * HAVE TO CHECK ALL THE MAGIC CONSTANTS USED HERE : $xxxxxx */
503:
504: movab _etext+NBPG-1,r1
505: andl2 $0!SYSTEM,r1
506: shrl $PGSHIFT,r1,r1
507: 1: orl3 $PG_V|PG_KR,r2,_Sysmap[r2]
508: aoblss r1,r2,1b
509:
510: /* make kernel data, bss, read-write */
511: movab _end+NBPG-1,r1
512: andl2 $0!SYSTEM,r1
513: shrl $PGSHIFT,r1,r1
514: 1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]
515: aoblss r1,r2,1b
516:
517: /* now go to mapped mode */
518: /* Have to change both PC and SP to system addresses */
519: mtpr $1,$TBIA
520: mtpr $1,$PADC /* needed by HW parity & ECC logic */
521: mtpr $1,$PACC /* just in case */
522: mtpr $1,$MME
523: movab SYSTEM(sp),sp
524: .globl go_virt
525: go_virt:
526: jmp *$0f
527: 0:
528:
529: /* disable any interrupts */
530: movl $0,_intenable
531: /* init mem sizes */
532: shrl $PGSHIFT,r7,_maxmem
533: movl _maxmem,_physmem
534: movl _maxmem,_freemem
535:
536: /* setup context for proc[0] == Scheduler */
537: movab _end-SYSTEM+NBPG-1,r6
538: andl2 $0!(NBPG-1),r6 # make page boundary
539:
540: /* setup page table for proc[0] */
541: shrl $PGSHIFT,r6,r3 # r3 = btoc(r6)
542: orl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry
543: incl r3 # r3 - next page
544: movab _usrpt,r0 # r0 - first user page
545: mtpr r0,$TBIS
546:
547: /* init p0br, p0lr */
548: mtpr r0,$P0BR # No P0 for proc[0]
549: mtpr $0,$P0LR
550:
551: mtpr r0,$P1BR # No P1 either
552: mtpr $0,$P1LR
553:
554:
555: /* init p2br, p2lr */
556: movab NBPG(r0),r0
557: movl $PPAGES-UPAGES,r1
558: mtpr r1,$P2LR
559: moval -4*PPAGES(r0),r2
560: mtpr r2,$P2BR
561:
562: /* setup mapping for UPAGES of _u */
563: clrl r2;
564: movl $SYSTEM,r1
565: addl2 $UPAGES,r3
566: jbr 2f
567: 1: decl r3
568: moval -NBPG(r1),r1; # r1 = virtual add of next (downward) _u page
569: subl2 $4,r0 # r0 = pte address
570: orl3 $PG_V|PG_URKW,r3,(r0)
571: mtpr r1,$TBIS
572: 2: aobleq $UPAGES,r2,1b
573:
574: /* initialize (slightly) the pcb */
575: movab UPAGES*NBPG(r1),PCB_KSP(r1) # KSP starts at end of _u
576: movl r1,PCB_USP(r1) # USP starts just below _u
577: mfpr $P0BR,PCB_P0BR(r1)
578: mfpr $P0LR,PCB_P0LR(r1)
579: mfpr $P1BR,PCB_P1BR(r1)
580: mfpr $P1LR,PCB_P1LR(r1)
581: mfpr $P2BR,PCB_P2BR(r1)
582: mfpr $P2LR,PCB_P2LR(r1)
583: movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt
584: movl r11,PCB_R11(r1) # r11 obtained from CP on boot
585: movab 1f,PCB_PC(r1) # initial pc
586: clrl PCB_PSL(r1) # kernel mode, ipl=0
587: movw $0xff,PCB_CKEY(r1) # give him a code key
588: movw $0xff,PCB_DKEY(r1) # give him a data key
589: shll $PGSHIFT,r3,r3
590: mtpr r3,$PCBB # first pcbb (physical ! )
591:
592: /* Go to a 'normal' process mode (kernel) */
593:
594: ldpctx
595: rei # Actually 'returns' to the next instruction:
596:
597: /* put signal trampoline code in u. area */
598: 1: movab _u,r0
599: movl sigcode+0,PCB_SIGC+0(r0)
600: movl sigcode+4,PCB_SIGC+4(r0)
601: movl sigcode+8,PCB_SIGC+8(r0)
602: movl sigcode+12,PCB_SIGC+12(r0)
603:
604: /* save reboot flags in global _boothowto */
605: movl r11,_boothowto
606:
607: /* calculate firstaddr, and call main() */
608: movab _end-SYSTEM+NBPG-1,r0
609: shrl $PGSHIFT,r0,-(sp)
610: addl2 $UPAGES+1,(sp) # First physical unused page number
611: callf $8,_main
612:
613: /* proc[1] == /etc/init now running here in kernel mode; run icode */
614: pushl $PSL_CURMOD # User mode PSL
615: pushl $0 # PC = 0 (virtual now)
616: rei
617:
618: /* signal trampoline code: it is known that this code takes up to 16 */
619: /* bytes in pcb.h and in the code above */
620: /* The following user stack layout was set up by machdep.c/sendsig */
621: /* routine: */
622: /* */
623: /* +---------------+ */
624: /* | Last PSL |\ */
625: /* +---------------+ > for rei */
626: /* :-->| Last PC |/ */
627: /* | +---------------+ */
628: /* :___|__* SP |\ */
629: /* +---------------+ | */
630: /* | sigmask | | */
631: /* +---------------+ > cleaned by kcall $139 (sigcleanup) */
632: /* :-->| u.u_onstack | | */
633: /* | +---------------+ | */
634: /* :___|_* copy of SCP |/ */
635: /* | +---------------+ */
636: /* | | Process' r0 | */
637: /* | +---------------+ */
638: /* | | Process' r1 | */
639: /* | +---------------+ */
640: /* | | Handler addr. |\ */
641: /* | +---------------+ | */
642: /* :___|_* SCP | | */
643: /* +---------------+ > cleaned by ret from calls */
644: /* | u.u_code | | */
645: /* +---------------+ | */
646: /* | signal number|/ */
647: /* +---------------+ */
648: /* */
649: /* * Stack when entering sigcode; setup by sendsig(); */
650: /* */
651: .align 2
652: sigcode: # When the process executes this code
653: # (located in its u. structure), it
654: # is in user mode !
655: calls $4*4+4,*12(sp) # 4 words popped from stack when this call returns
656: movl (sp)+,r1
657: movl (sp)+,r0
658: kcall $139 # Signal cleanup
659: rei # From user mode to user mode !
660:
661: /*
662: * Primitives
663: */
664:
665: /*
666: * badaddr(addr, len)
667: * see if access addr with a len type instruction causes a machine check
668: * len is length of access (1=byte, 2=short, 4=long)
669: * r0 = 0 means good(exists); r0 =1 means does not exist.
670: */
671: .globl _badaddr
672: _badaddr:
673: .word 0x1c # Keep r4,r3,r2
674: mfpr $IPL,r1
675: mtpr $HIGH,$IPL
676: movl _scb+BERVEC,r2
677: movl 4(fp),r3
678: movl 8(fp),r4
679: movab 9f,_scb+BERVEC
680: bbc $0,r4,1f; tstb (r3)
681: 1: bbc $1,r4,1f; tstw (r3)
682: 1: bbc $2,r4,1f; tstl (r3)
683: 1: clrl r0 # made it w/o machine checks
684: 2: movl r2,_scb+BERVEC
685: mtpr r1,$IPL
686: ret
687:
688: .align 2
689: 9: # Here we catch buss error (if it comes)
690: andl3 4(sp),$ERRCD,r0
691: cmpl r0,$APE
692: jneq 1f
693: halt # Address parity error !!!
694: 1: cmpl r0,$VBE
695: jneq 1f
696: halt # Versabus error
697: 1:
698: movl $1,r0 # Anything else = bad address
699: movab 8(sp),sp # discard buss error trash
700: movab 2b,(sp) # new program counter on stack.
701: rei
702:
703:
704: /*
705: * badcyaddr(addr)
706: * see if access tape master controller addr causes a bus error
707: * r0 = 0: no error; r0 = 1: timeout error.
708: */
709: .globl _badcyaddr
710: _badcyaddr:
711: .word 0x0c # Keep r3,r2
712: mfpr $IPL,r1
713: mtpr $HIGH,$IPL
714: movl _scb+BERVEC,r2
715: clrl r3
716: movab 9f,_scb+BERVEC
717: movob $-1, *4(fp)
718: 1: aobleq $1000, r3, 1b
719: clrl r0 # made it w/o machine checks
720: 2: movl r2,_scb+BERVEC
721: mtpr r1,$IPL
722: ret
723:
724: .align 2
725: 9: # Here we catch buss error (if it comes)
726: andl3 4(sp),$ERRCD,r0
727: cmpl r0,$APE
728: jneq 1f
729: halt # Address parity error !!!
730: 1: cmpl r0,$VBE
731: jneq 1f
732: halt # Versabus error
733: 1:
734: movl $1,r0 # Anything else = timeout
735: movab 8(sp),sp # discard buss error trash
736: movab 2b,(sp) # new program counter on stack.
737: rei
738:
739: _bcopy: .globl _bcopy
740: .word 0x4 # save r2
741: # Called by ovbcopy(from,dst,len)
742: movl 4(fp),r0
743: movl 8(fp),r1
744: movl 12(fp),r2
745: movblk
746: ret
747:
748: _ovbcopy: .globl _ovbcopy
749: .word 0x001c
750: movl 4(fp),r0
751: movl 8(fp),r1
752: movl 12(fp),r2
753: cmpl r0,r1
754: bgtru 1f # normal forward case
755: beql 2f # equal, nothing to do
756: addl2 r2,r0 # may be overlapping
757: cmpl r0,r1
758: bgtru 3f
759: subl2 r2,r0 # normal forward case
760: 1:
761: movblk
762: 2:
763: ret
764: 3:
765: addl2 r2,r1 # overlapping, must do backwards
766: subl3 r0,r1,r3
767: movl r2,r4
768: jbr 5f
769: 4:
770: subl2 r3,r0
771: subl2 r3,r1
772: movl r3,r2
773: movblk
774: subl2 r3,r0
775: subl2 r3,r1
776: subl2 r3,r4
777: 5:
778: cmpl r4,r3
779: jgtr 4b
780: movl r4,r2
781: subl2 r2,r0
782: subl2 r2,r1
783: movblk
784: ret
785:
786: /*
787: * bzero (base, count)
788: * zero out a block starting at 'base', size 'count'.
789: */
790: _bzero:
791: .globl _bzero
792: .word 0x4
793: movl $1f,r0 # r0 = null source string
794: movl 4(fp),r1 # r1 = destination address
795: movl 8(fp),r2 # r2 = count
796: movs3
797: ret
798: 1:
799: .byte 0
800:
801:
802: _copyin: .globl _copyin # the _Copyin subroutine in VAX
803: # became _copyin procedure for TAHOE
804: .word 0x0004
805: movl 12(fp),r0 # copy length
806: blss ersb
807: movl 4(fp),r1 # copy user address
808: cmpl $NBPG,r0 # probing one page or less ?
809: bgeq cishort # yes
810: ciloop:
811: prober $1,(r1),$NBPG # bytes accessible ?
812: beql ersb # no
813: addl2 $NBPG,r1 # incr user address ptr
814: _ACBL ($NBPG+1,$-NBPG,r0,ciloop) # reduce count and loop
815: cishort:
816: prober $1,(r1),r0 # bytes accessible ?
817: beql ersb # no
818: MOVC3 (12(fp),4(fp),8(fp))
819: clrl r0
820: ret
821:
822: ersb:
823: movl $EFAULT,r0
824: ret
825:
826: _copyout: .globl _copyout # the _Copyout subroutine in VAX
827: # became _copyout procedure for TAHOE
828: .word 0x04
829: movl 12(fp),r0 # get count
830: blss ersb
831: movl 8(fp),r1 # get user address
832: cmpl $NBPG,r0 # can do in one probew?
833: bgeq coshort # yes
834: coloop:
835: probew $1,(r1),$NBPG # bytes accessible?
836: beql ersb # no
837: addl2 $NBPG,r1 # increment user address
838: _ACBL ($NBPG+1,$-NBPG,r0,coloop) # reduce count and loop
839: coshort:
840: probew $1,(r1),r0 # bytes accessible?
841: beql ersb # no
842: MOVC3 (12(fp),4(fp),8(fp))
843: clrl r0
844: ret
845:
846: /*
847: * non-local goto's
848: */
849: .globl _setjmp # the _Setjmp subroutine in VAX
850: # became _setjmp procedure for TAHOE
851: _setjmp:
852: .word 0x0
853: movl 4(fp),r2
854: storer $0x1ff8,(r2)
855: addl2 $40,r2
856: movl (fp),(r2)
857: addl2 $4,r2
858: movab 8(fp),(r2)
859: addl2 $4,r2
860: movl -8(fp),(r2)
861: clrl r0
862: ret
863:
864: .globl _longjmp # the _Longjmp subroutine in VAX
865: # became _longjmp procedure for TAHOE
866: _longjmp:
867: .word 0x0000
868: movl 4(fp),r2
869: _Longjmp: # called from swtch
870: loadr $0x3ff8,(r2)
871: addl2 $44,r2
872: movl (r2),r1
873: addl2 $4,r2
874: movab (sp),r0
875: cmpl r1,r0 # must be a pop
876: bgequ lj2
877: pushab lj1
878: callf $8,_panic
879: lj2:
880: movl r1,sp
881: jmp *(r2)
882:
883: lj1: .asciz "longjmp"
884:
885:
886: .globl _whichqs
887: .globl _qs
888: .globl _cnt
889:
890: .globl _noproc
891: .comm _noproc,4
892: .globl _runrun
893: .comm _runrun,4
894:
895: /*
896: * The following primitives use the fancy TAHOE instructions.
897: * _whichqs tells which of the 32 queues _qs
898: * have processes in them. setrq puts processes into queues, remrq
899: * removes them from queues. The running process is on no queue,
900: * other processes are on a queue related to p->p_pri, divided by 4
901: * actually to shrink the 0-127 range of priorities into the 32 available
902: * queues.
903: */
904:
905: /*
906: * setrq(p), using fancy TAHOE instructions.
907: *
908: * Call should be made at spl8(), and p->p_stat should be SRUN
909: */
910: .globl _setrq
911: _setrq:
912: .word 0x4
913: movl 4(fp),r0
914: tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0
915: beql set1 ##
916: pushab set3 ##
917: callf $8,_panic ##
918: set1:
919: movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4
920: shar $2,r1,r1
921: shal $1,r1,r2
922: moval _qs[r2],r2
923: insque (r0),*4(r2) # at end of queue
924: shal r1,$1,r1
925: orl2 r1,_whichqs # mark queue non-empty
926: ret
927:
928: set3: .asciz "setrq"
929:
930: /*
931: * remrq(p), using fancy TAHOE instructions
932: *
933: * Call should be made at spl8().
934: */
935: .globl _remrq
936: _remrq:
937: .word 0x0
938: movl 4(fp),r0
939: movzbl P_PRI(r0),r1
940: shar $2,r1,r1
941: bbs r1,_whichqs,rem1
942: pushab rem3 # it wasn't recorded to be on its q
943: callf $8,_panic
944: rem1:
945: remque (r0)
946: bneq rem2 # q not empty yet
947: shal r1,$1,r1
948: mcoml r1,r1
949: andl2 r1,_whichqs # mark queue empty
950: rem2:
951: clrl P_RLINK(r0) ## for firewall checking
952: ret
953:
954: rem3: .asciz "remrq"
955:
956: .globl __insque
957: __insque:
958: .word 0
959: insque *4(fp), *8(fp)
960: ret
961:
962:
963: .globl __remque
964: __remque:
965: .word 0
966: remque *4(fp)
967: ret
968:
969: /*
970: * Masterpaddr is the p->p_addr of the running process on the master
971: * processor. When a multiprocessor system, the slave processors will have
972: * an array of slavepaddr's.
973: */
974: .globl _masterpaddr
975: .data
976: _masterpaddr:
977: .long 0
978:
979: .text
980: sw0: .asciz "swtch"
981: /*
982: * swtch(), using fancy TAHOE instructions
983: */
984: .globl _swtch
985: _swtch:
986: .word 0x0
987: movl (fp),fp # prepare for rei
988: movl (sp),4(sp) # saved pc
989: tstl (sp)+
990: movpsl 4(sp)
991: movl $1,_noproc
992: clrl _runrun
993: mtpr0: mtpr $0,$IPL # must allow interrupts here
994: sw1: ffs _whichqs,r0 # look for non-empty queue
995: bgeq sw1a
996: brb sw1 # this is an idle loop!
997: sw1a: mtpr $0x18,$IPL # lock out all so _whichqs==_qs
998: bbc r0,_whichqs,mtpr0 # proc moved via lbolt interrupt
999: shal $1,r0,r1
1000: moval _qs[r1],r1
1001: movl (r1),r2 # r2 = p = highest pri process
1002: remque *(r1)
1003: bvc sw2 # make sure something was there
1004: sw1b: pushab sw0
1005: callf $8,_panic
1006: sw2: bneq sw3
1007: shal r0,$1,r1
1008: mcoml r1,r1
1009: andl2 r1,_whichqs # no more procs in this queue
1010: sw3:
1011: clrl _noproc
1012: tstl P_WCHAN(r2) ## firewalls
1013: bneq sw1b ##
1014: movzbl P_STAT(r2),r3 ##
1015: cmpl $SRUN,r3 ##
1016: bneq sw1b ##
1017: clrl P_RLINK(r2) ##
1018: movl *P_ADDR(r2),r0
1019: movl r0,_masterpaddr
1020: shal $PGSHIFT,r0,r0 # r0 = pcbb(p)
1021: /* mfpr $PCBB,r1 # resume of current proc is easy
1022: * cmpl r0,r1
1023: */ beql res0
1024: incl _cnt+V_SWTCH
1025: brb swresume
1026: /* fall into... */
1027:
1028: /*
1029: * global cache key used if cant use proc index as key
1030: * (e.g. NPROC>=255)
1031: * otherwise used for temporary storage of key
1032: */
1033: .data
1034: _globkey:
1035: .long 0
1036: .text
1037: /*
1038: * resume(pf)
1039: */
1040: .globl _resume
1041: _resume:
1042: .word 0x0
1043: shal $PGSHIFT,4(fp),r0 # r0 = pcbb(p)
1044: movl (fp),fp # prepare for rei
1045: movl (sp)+,4(sp) # saved pc
1046: tstl (sp)+
1047: movpsl 4(sp)
1048: swresume:
1049: mtpr $0x18,$IPL # no interrupts, please
1050: movl _CMAP2,_u+PCB_CMAP2 # yech
1051: svpctx
1052: mtpr r0,$PCBB
1053: ldpctx
1054: movl _u+PCB_CMAP2,_CMAP2 # yech
1055: mtpr $_CADDR2,$TBIS
1056: res0:
1057: tstl _u+PCB_SSWAP
1058: beql res1
1059: movl _u+PCB_SSWAP,r2
1060: clrl _u+PCB_SSWAP
1061: movab _Longjmp,(sp)
1062: clrl 4(sp) # PSL = kernel mode, IPL=0
1063: res1:
1064: #ifdef GLOBKEY
1065: aoblss $256,_globkey,res2 # define new cache key
1066: mtpr $0,$PACC # out of keys, purge all
1067: mtpr $0,$PADC
1068: movl $1,_globkey
1069: res2:
1070: mtpr _globkey,$CCK
1071: #else
1072: res3:
1073: movzwl _u+PCB_CKEY,_globkey
1074: mtpr _globkey,$CCK
1075: res4:
1076: movzwl _u+PCB_DKEY,_globkey
1077: #endif
1078: mtpr _globkey,$DCK
1079: rei
1080:
1081: /*
1082: * {fu,su},{byte,word}
1083: */
1084: .globl _fuiword
1085: .globl _fuword
1086: _fuiword:
1087: _fuword:
1088: .word 0x0
1089: prober $1,*4(fp),$4
1090: beql fserr
1091: movl *4(fp),r0
1092: ret
1093: fserr:
1094: mnegl $1,r0
1095: ret
1096:
1097: .globl _fuibyte
1098: .globl _fubyte
1099: _fuibyte:
1100: _fubyte:
1101: .word 0x0
1102: prober $1,*4(fp),$1
1103: beql fserr
1104: movzbl *4(fp),r0
1105: ret
1106:
1107: .globl _suiword
1108: .globl _suword
1109: _suiword:
1110: _suword:
1111: .word 0x0
1112: probew $1,*4(fp),$4
1113: beql fserr
1114: movl 8(fp),*4(fp)
1115: clrl r0
1116: ret
1117:
1118: .globl _suibyte
1119: .globl _subyte
1120: _suibyte:
1121: _subyte:
1122: .word 0x0
1123: probew $1,*4(fp),$1
1124: beql fserr
1125: movb 11(fp),*4(fp)
1126: clrl r0
1127: ret
1128:
1129: /*
1130: * Copy 1 relocation unit (NBPG bytes)
1131: * from user virtual address to physical address
1132: */
1133: _copyseg: .globl _copyseg
1134: .word 0x0
1135: orl3 $PG_V|PG_KW,8(fp),_CMAP2
1136: mtpr $_CADDR2,$TBIS # invalidate entry for copy
1137: MOVC3 ($NBPG,4(fp),$_CADDR2)
1138: ret
1139:
1140: /*
1141: * clearseg(physical_page_number);
1142: *
1143: * zero out physical memory
1144: * specified in relocation units (NBPG bytes)
1145: * This routine was optimized for speed on Tahoe.
1146: */
1147: _clearseg: .globl _clearseg
1148: .word 0
1149: orl3 $PG_V|PG_KW,4(fp),_CMAP1 # Maps to virtual addr CADDR1
1150: mtpr $_CADDR1,$TBIS
1151: movl $255,r0 # r0 = limit
1152: clrl r1 # r1 = index of cleared long
1153: 1:
1154: clrl _CADDR1[r1]
1155: aobleq r0,r1,1b
1156: ret
1157:
1158: /*
1159: * if ( useracc(address, count, mode) ) ....
1160: * Check address.
1161: * Given virtual address, byte count, and rw flag
1162: * returns 0 on no access.
1163: * Note : it is assumed that on all calls to this routine,
1164: * mode=0 means write access, mode=1 means read access.
1165: */
1166: _useracc: .globl _useracc
1167: .word 0x4
1168: movl $1,r2 # r2 = 'user mode' for probew/probew
1169: probes:
1170: movl 4(fp),r0 # get va
1171: movl 8(fp),r1 # count
1172: tstl 12(fp) # test for read access ?
1173: bneq userar # yes
1174: cmpl $NBPG,r1 # can we do it in one probe ?
1175: bgeq uaw2 # yes
1176: uaw1:
1177: probew r2,(r0),$NBPG
1178: beql uaerr # no access
1179: addl2 $NBPG,r0
1180: _ACBL($NBPG+1,$-NBPG,r1,uaw1)
1181: uaw2:
1182: probew r2,(r0),r1
1183: beql uaerr
1184: movl $1,r0
1185: ret
1186:
1187: userar:
1188: cmpl $NBPG,r1
1189: bgeq uar2
1190: uar1:
1191: prober r2,(r0),$NBPG
1192: beql uaerr
1193: addl2 $NBPG,r0
1194: _ACBL($NBPG+1,$-NBPG,r1,uar1)
1195: uar2:
1196: prober r2,(r0),r1
1197: beql uaerr
1198: movl $1,r0
1199: ret
1200: uaerr:
1201: clrl r0
1202: ret
1203:
1204: /*
1205: * if ( kernacc(address, count, mode) ) ....
1206: * Check address.
1207: * Given virtual address, byte count, and rw flag
1208: * returns 0 on no access.
1209: * Same as useracc routine but checks for kernel access rights.
1210: */
1211:
1212: _kernacc: .globl _kernacc
1213: .word 0x4
1214: clrl r2 # r2 = 0 means kernel mode probe.
1215: jbr probes # Dijkstra would get gastric distress here.
1216:
1217: /*
1218: * addupc - increment some histogram counter
1219: * in the profiling buffer
1220: *
1221: * addupc(pc, prof, counts)
1222: * long pc , counts; Only least significant word of 'counts' is added.
1223: * struct uprof *prof;
1224: *
1225: * struct uprof { # profile arguments
1226: * short *r_base; # buffer base
1227: * unsigned pr_size; # buffer size
1228: * unsigned pr_off; # pc offset
1229: * unsigned pr_scale; # pc scaling
1230: * }
1231: */
1232: .globl _addupc
1233: _addupc:
1234: .word 4
1235: movl 8(fp),r2 # r2 points to structure
1236: subl3 8(r2),4(fp),r0 # r0 = PC - lowpc
1237: jlss 9f # PC < lowpc , out of range !
1238: shrl $1,r0,r0 # the unit is words
1239: shrl $1,12(r2),r1 # ditto for scale
1240: emul r1,r0,$0,r0
1241: shrq $14,r0,r0
1242: tstl r0 # too big
1243: jneq 9f
1244: cmpl r1,4(r2) # Check buffer overflow
1245: jgequ 9f
1246: probew $1,*0(r2)[r1],$2 # counter accessible?
1247: jeql 9f
1248: shrl $1,r1,r1 # make r1 word index
1249: addw2 14(fp),*0(r2)[r1]
1250: 9: ret
1251: SCBVEC(udintr0):
1252: SCBVEC(xpintr0):
1253: jbr _Xstray
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.