|
|
1.1 root 1: /*
2: * Copyright (c) 1980, 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: * @(#)locore.s 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "psl.h"
10: #include "pte.h"
11:
12: #include "errno.h"
13: #include "cmap.h"
14:
15: #include "mtpr.h"
16: #include "trap.h"
17: #include "cpu.h"
18: #include "nexus.h"
19: #include "cons.h"
20: #include "clock.h"
21: #include "ioa.h"
22: #include "ka630.h"
23: #include "../vaxuba/ubareg.h"
24:
25: #include "dz.h"
26: #include "uu.h"
27: #include "ps.h"
28: #include "mba.h"
29: #include "uba.h"
30:
31: .set HIGH,0x1f # mask for total disable
32: .set MCKVEC,4 # offset into scb of machine check vector
33: .set NBPG,512
34: .set PGSHIFT,9
35:
36: .set NISP,3 # number of interrupt stack pages
37:
38: /*
39: * User structure is UPAGES at top of user space.
40: */
41: .globl _u
42: .set _u,0x80000000 - UPAGES*NBPG
43:
44: .globl _intstack
45: _intstack:
46: .space NISP*NBPG
47: eintstack:
48:
49: /*
50: * Do a dump.
51: * Called by auto-restart.
52: * May be called manually.
53: */
54: .align 2
55: .globl _doadump
56: _doadump:
57: nop; nop # .word 0x0101
58: #define _rpbmap _Sysmap # rpb, scb, UNI*vec, istack*4
59: bicl2 $PG_PROT,_rpbmap
60: bisl2 $PG_KW,_rpbmap
61: mtpr $0,$TBIA
62: tstl _rpb+RP_FLAG # dump only once!
63: bneq 1f
64: incl _rpb+RP_FLAG
65: movl sp,erpb
66: movab erpb,sp
67: mfpr $PCBB,-(sp)
68: mfpr $MAPEN,-(sp)
69: mfpr $IPL,-(sp)
70: mtpr $0,$MAPEN
71: mtpr $HIGH,$IPL
72: pushr $0x3fff
73: calls $0,_dumpsys
74: 1:
75: pushl $TXDB_BOOT
76: calls $1,_tocons
77: halt
78:
79: /*
80: * Interrupt vector routines
81: */
82: .globl _waittime
83:
84: #define SCBVEC(name) .align 2; .globl _X/**/name; _X/**/name
85: #define PANIC(msg) clrl _waittime; pushab 1f; \
86: calls $1,_panic; 1: .asciz msg
87: #define PRINTF(n,msg) pushab 1f; calls $n+1,_printf; MSG(msg)
88: #define MSG(msg) .data; 1: .asciz msg; .text
89: #define PUSHR pushr $0x3f
90: #define POPR popr $0x3f
91:
92: .data
93: nofault: .long 0 # where to go on predicted machcheck
94: .text
95: SCBVEC(machcheck):
96: tstl nofault
97: bneq 1f
98: PUSHR; pushab 6*4(sp); calls $1,_machinecheck; POPR;
99: addl2 (sp)+,sp; rei
100: .align 2
101: 1:
102: casel _cpu,$1,$VAX_MAX
103: 0:
104: .word 8f-0b # 1 is 780
105: .word 5f-0b # 2 is 750
106: .word 5f-0b # 3 is 730
107: .word 7f-0b # 4 is 8600
108: .word 1f-0b # ???
109: .word 1f-0b # ???
110: .word 1f-0b # ???
111: .word 1f-0b # 8 is 630
112: 5:
113: #if defined(VAX750) || defined(VAX730)
114: mtpr $0xf,$MCESR
115: #endif
116: brb 1f
117: 7:
118: #if VAX8600
119: mtpr $0,$EHSR
120: #endif
121: brb 1f
122: 8:
123: #if VAX780
124: mtpr $0,$SBIFS
125: #endif
126: 1:
127: addl2 (sp)+,sp # discard mchchk trash
128: movl nofault,(sp)
129: rei
130: SCBVEC(kspnotval):
131: PUSHR; PANIC("KSP not valid");
132: SCBVEC(powfail):
133: halt
134: SCBVEC(chme): SCBVEC(chms): SCBVEC(chmu):
135: PUSHR; PANIC("CHM? in kernel");
136: SCBVEC(stray):
137: PUSHR; PRINTF(0, "stray scb interrupt\n"); POPR;
138: rei
139: SCBVEC(nexzvec):
140: PUSHR; mfpr $IPL,-(sp); PRINTF(1, "nexus stray intr ipl%x\n"); POPR; rei
141: SCBVEC(cmrd):
142: PUSHR; calls $0,_memerr; POPR; rei
143: SCBVEC(wtime):
144: PUSHR; pushl 6*4(sp); PRINTF(1,"write timeout %x\n"); POPR;
145: PANIC("wtimo");
146:
147: #if NMBA > 0
148: SCBVEC(mba3int):
149: PUSHR; incl _intrcnt+I_MBA3; pushl $3; brb 1f
150: SCBVEC(mba2int):
151: PUSHR; incl _intrcnt+I_MBA2; pushl $2; brb 1f
152: SCBVEC(mba1int):
153: PUSHR; incl _intrcnt+I_MBA1; pushl $1; brb 1f
154: SCBVEC(mba0int):
155: PUSHR; incl _intrcnt+I_MBA0; pushl $0
156: 1: calls $1,_mbintr
157: POPR
158: incl _cnt+V_INTR
159: rei
160: #endif
161:
162: #if defined(VAX780) || defined(VAX8600)
163: /*
164: * Registers for the uba handling code
165: */
166: #define rUBANUM r0
167: #define rUBAHD r1
168: #define rUVEC r3
169: #define rUBA r4
170: /* r2,r5 are scratch */
171:
172: #define I_UBA I_UBA0 /* base of UBA interrupt counters */
173:
174: #if NUBA > 4
175: SCBVEC(ua7int):
176: PUSHR; movl $7,rUBANUM; moval _uba_hd+(7*UH_SIZE),rUBAHD; brb 1f
177: SCBVEC(ua6int):
178: PUSHR; movl $6,rUBANUM; moval _uba_hd+(6*UH_SIZE),rUBAHD; brb 1f
179: SCBVEC(ua5int):
180: PUSHR; movl $5,rUBANUM; moval _uba_hd+(5*UH_SIZE),rUBAHD; brb 1f
181: SCBVEC(ua4int):
182: PUSHR; movl $4,rUBANUM; moval _uba_hd+(4*UH_SIZE),rUBAHD; brb 1f
183: #endif
184: SCBVEC(ua3int):
185: PUSHR; movl $3,rUBANUM; moval _uba_hd+(3*UH_SIZE),rUBAHD; brb 1f
186: SCBVEC(ua2int):
187: PUSHR; movl $2,rUBANUM; moval _uba_hd+(2*UH_SIZE),rUBAHD; brb 1f
188: SCBVEC(ua1int):
189: PUSHR; movl $1,rUBANUM; moval _uba_hd+(1*UH_SIZE),rUBAHD; brb 1f
190: SCBVEC(ua0int):
191: PUSHR; movl $0,rUBANUM; moval _uba_hd+(0*UH_SIZE),rUBAHD;
192: 1:
193: mfpr $IPL,r2 /* r2 = mfpr(IPL); */
194: movl UH_UBA(rUBAHD),rUBA /* uba = uhp->uh_uba; */
195: movl UBA_BRRVR-0x14*4(rUBA)[r2],rUVEC
196: /* uvec = uba->uba_brrvr[r2-0x14] */
197: ubanorm:
198: bleq ubaerror
199: addl2 UH_VEC(rUBAHD),rUVEC /* uvec += uh->uh_vec */
200: bicl3 $3,(rUVEC),r1
201: jmp 2(r1) /* 2 skips ``pushr $0x3f'' */
202: ubaerror:
203: PUSHR; calls $0,_ubaerror; POPR /* ubaerror r/w's r0-r5 */
204: tstl rUVEC; jneq ubanorm /* rUVEC contains result */
205: incl _intrcnt+I_UBA[rUBANUM]
206: incl _cnt+V_INTR
207: POPR
208: rei
209: #endif
210: SCBVEC(cnrint):
211: PUSHR; calls $0,_cnrint; POPR
212: incl _cnt+V_INTR
213: incl _intrcnt+I_CNR
214: rei
215: SCBVEC(cnxint):
216: PUSHR; calls $0,_cnxint; POPR
217: incl _cnt+V_INTR
218: incl _intrcnt+I_CNX
219: rei
220: SCBVEC(hardclock):
221: PUSHR
222: mtpr $ICCS_RUN|ICCS_IE|ICCS_INT|ICCS_ERR,$ICCS
223: #if NPS > 0
224: pushl 4+6*4(sp); pushl 4+6*4(sp);
225: calls $2,_psextsync
226: #endif
227: pushl 4+6*4(sp); pushl 4+6*4(sp);
228: calls $2,_hardclock # hardclock(pc,psl)
229: POPR;
230: incl _cnt+V_INTR
231: incl _intrcnt+I_CLOCK
232: rei
233: SCBVEC(softclock):
234: PUSHR
235: pushl 4+6*4(sp); pushl 4+6*4(sp);
236: calls $2,_softclock # softclock(pc,psl)
237: POPR;
238: incl _cnt+V_SOFT
239: rei
240:
241: #include "../net/netisr.h"
242: .globl _netisr
243: SCBVEC(netintr):
244: PUSHR
245: #include "imp.h"
246: #if NIMP > 0
247: bbcc $NETISR_IMP,_netisr,1f; calls $0,_impintr; 1:
248: #endif
249: #ifdef INET
250: bbcc $NETISR_IP,_netisr,1f; calls $0,_ipintr; 1:
251: #endif
252: #ifdef NS
253: bbcc $NETISR_NS,_netisr,1f; calls $0,_nsintr; 1:
254: #endif
255: bbcc $NETISR_RAW,_netisr,1f; calls $0,_rawintr; 1:
256: POPR
257: incl _cnt+V_SOFT
258: rei
259:
260: #if defined(VAX750) || defined(VAX730) || defined(VAX8600)
261: SCBVEC(consdin):
262: PUSHR;
263: incl _intrcnt+I_TUR
264: casel _cpu,$VAX_750,$VAX_8600
265: 0:
266: .word 5f-0b # 2 is VAX_750
267: .word 3f-0b # 3 is VAX_730
268: .word 6f-0b # 4 is VAX_8600
269: halt
270: 5:
271: #if defined(VAX750) && !defined(MRSP)
272: jsb tudma
273: #endif
274: 3:
275: #if defined(VAX750) || defined(VAX730)
276: calls $0,_turintr
277: brb 2f
278: #else
279: halt
280: #endif
281: 6:
282: #if VAX8600
283: calls $0, _crlintr
284: #else
285: halt
286: #endif
287: 2:
288: POPR;
289: incl _cnt+V_INTR;
290: rei
291: #else
292: SCBVEC(consdin):
293: halt
294: #endif
295:
296: #if defined(VAX750) || defined(VAX730)
297: SCBVEC(consdout):
298: PUSHR; calls $0,_tuxintr; POPR
299: incl _cnt+V_INTR
300: incl _intrcnt+I_TUX
301: rei
302: #else
303: SCBVEC(consdout):
304: halt
305: #endif
306:
307: #if NDZ > 0
308: /*
309: * DZ pseudo dma routine:
310: * r0 - controller number
311: */
312: .align 1
313: .globl dzdma
314: dzdma:
315: mull2 $8*20,r0
316: movab _dzpdma(r0),r3 # pdma structure base
317: # for this controller
318: dzploop:
319: movl r3,r0
320: movl (r0)+,r1 # device register address
321: movzbl 1(r1),r2 # get line number
322: bitb $0x80,r2 # TRDY on?
323: beql dzprei # no
324: bicb2 $0xf8,r2 # clear garbage bits
325: mull2 $20,r2
326: addl2 r2,r0 # point at line's pdma structure
327: movl (r0)+,r2 # p_mem
328: cmpl r2,(r0)+ # p_mem < p_end ?
329: bgequ dzpcall # no, go call dzxint
330: movb (r2)+,6(r1) # dztbuf = *p_mem++
331: movl r2,-8(r0)
332: brb dzploop # check for another line
333: dzprei:
334: POPR
335: incl _cnt+V_PDMA
336: rei
337:
338: dzpcall:
339: pushl r3
340: pushl (r0)+ # push tty address
341: calls $1,*(r0) # call interrupt rtn
342: movl (sp)+,r3
343: brb dzploop # check for another line
344: #endif
345:
346: #if NUU > 0 && defined(UUDMA)
347: /*
348: * Pseudo DMA routine for tu58 (on DL11)
349: * r0 - controller number
350: */
351: .align 1
352: .globl uudma
353: uudma:
354: movl _uudinfo[r0],r2
355: movl 16(r2),r2 # r2 = uuaddr
356: mull3 $48,r0,r3
357: movab _uu_softc(r3),r5 # r5 = uuc
358:
359: cvtwl 2(r2),r1 # c = uuaddr->rdb
360: bbc $15,r1,1f # if (c & UUDB_ERROR)
361: movl $13,16(r5) # uuc->tu_state = TUC_RCVERR;
362: rsb # let uurintr handle it
363: 1:
364: tstl 4(r5) # if (uuc->tu_rcnt) {
365: beql 1f
366: movb r1,*0(r5) # *uuc->tu_rbptr++ = r1
367: incl (r5)
368: decl 4(r5) # if (--uuc->tu_rcnt)
369: beql 2f # done
370: tstl (sp)+
371: POPR # registers saved in ubglue.s
372: rei # }
373: 2:
374: cmpl 16(r5),$8 # if (uuc->tu_state != TUS_GETH)
375: beql 2f # let uurintr handle it
376: 1:
377: rsb
378: 2:
379: mull2 $14,r0 # sizeof(uudata[ctlr]) = 14
380: movab _uudata(r0),r4 # data = &uudata[ctlr];
381: cmpb $1,(r4) # if (data->pk_flag != TUF_DATA)
382: bneq 1b
383: #ifdef notdef
384: /* this is for command packets */
385: beql 1f # r0 = uuc->tu_rbptr
386: movl (r5),r0
387: brb 2f
388: 1: # else
389: #endif
390: movl 24(r5),r0 # r0 = uuc->tu_addr
391: 2:
392: movzbl 1(r4),r3 # counter to r3 (data->pk_count)
393: movzwl (r4),r1 # first word of checksum (=header)
394: mfpr $IPL,-(sp) # s = spl5();
395: mtpr $0x15,$IPL # to keep disk interrupts out
396: clrw (r2) # disable receiver interrupts
397: 3: bbc $7,(r2),3b # while ((uuaddr->rcs & UUCS_READY)==0);
398: cvtwb 2(r2),(r0)+ # *buffer = uuaddr->rdb & 0xff
399: sobgtr r3,1f # continue with next byte ...
400: addw2 2(r2),r1 # unless this was the last (odd count)
401: brb 2f
402:
403: 1: bbc $7,(r2),1b # while ((uuaddr->rcs & UUCS_READY)==0);
404: cvtwb 2(r2),(r0)+ # *buffer = uuaddr->rdb & 0xff
405: addw2 -2(r0),r1 # add to checksum..
406: 2:
407: adwc $0,r1 # get the carry
408: sobgtr r3,3b # loop while r3 > 0
409: /*
410: * We're ready to get the checksum
411: */
412: 1: bbc $7,(r2),1b # while ((uuaddr->rcs & UUCS_READY)==0);
413: cvtwb 2(r2),12(r4) # get first (lower) byte
414: 1: bbc $7,(r2),1b
415: cvtwb 2(r2),13(r4) # ..and second
416: cmpw 12(r4),r1 # is checksum ok?
417: beql 1f
418: movl $14,16(r5) # uuc->tu_state = TUS_CHKERR
419: brb 2f # exit
420: 1:
421: movl $11,16(r5) # uuc->tu_state = TUS_GET (ok)
422: 2:
423: movw $0x40,(r2) # enable receiver interrupts
424: mtpr (sp)+,$IPL # splx(s);
425: rsb # continue processing in uurintr
426: #endif
427:
428: #if defined(VAX750) && !defined(MRSP)
429: /*
430: * Pseudo DMA routine for VAX-11/750 console tu58
431: * (without MRSP)
432: */
433: .align 1
434: .globl tudma
435: tudma:
436: movab _tu,r5 # r5 = tu
437: tstl 4(r5) # if (tu.tu_rcnt) {
438: beql 3f
439: mfpr $CSRD,r1 # get data from tu58
440: movb r1,*0(r5) # *tu.tu_rbptr++ = r1
441: incl (r5)
442: decl 4(r5) # if (--tu.tu_rcnt)
443: beql 1f # done
444: tstl (sp)+
445: POPR # registers saved in ubglue.s
446: rei # data handled, done
447: 1: # }
448: cmpl 16(r5),$8 # if (tu.tu_state != TUS_GETH)
449: beql 2f # let turintr handle it
450: 3:
451: rsb
452: 2:
453: movab _tudata,r4 # r4 = tudata
454: cmpb $1,(r4) # if (tudata.pk_flag != TUF_DATA)
455: bneq 3b # let turintr handle it
456: 1: # else
457: movl 24(r5),r1 # get buffer pointer to r1
458: movzbl 1(r4),r3 # counter to r3
459: movzwl (r4),r0 # first word of checksum (=header)
460: mtpr $0,$CSRS # disable receiver interrupts
461: 3:
462: bsbw 5f # wait for next byte
463: mfpr $CSRD,r5
464: movb r5,(r1)+ # *buffer = rdb
465: sobgtr r3,1f # continue with next byte ...
466: mfpr $CSRD,r2 # unless this was the last (odd count)
467: brb 2f
468:
469: 1: bsbw 5f # wait for next byte
470: mfpr $CSRD,r5
471: movb r5,(r1)+ # *buffer = rdb
472: movzwl -2(r1),r2 # get the last word back from memory
473: 2:
474: addw2 r2,r0 # add to checksum..
475: adwc $0,r0 # get the carry
476: sobgtr r3,3b # loop while r3 > 0
477: /*
478: * We're ready to get the checksum.
479: */
480: bsbw 5f
481: movab _tudata,r4
482: mfpr $CSRD,r5
483: movb r5,12(r4) # get first (lower) byte
484: bsbw 5f
485: mfpr $CSRD,r5
486: movb r5,13(r4) # ..and second
487: movab _tu,r5
488: cmpw 12(r4),r0 # is checksum ok?
489: beql 1f
490: movl $14,16(r5) # tu.tu_state = TUS_CHKERR
491: brb 2f # exit
492: 1:
493: movl $11,16(r5) # tu.tu_state = TUS_GET
494: 2:
495: mtpr $0x40,$CSRS # enable receiver interrupts
496: rsb # continue processing in turintr
497: /*
498: * Loop until a new byte is ready from
499: * the tu58, make sure we don't loop forever
500: */
501: 5:
502: movl $5000,r5 # loop max 5000 times
503: 1:
504: mfpr $CSRS,r2
505: bbs $7,r2,1f
506: sobgtr r5,1b
507: movab _tu,r5
508: movl $13,16(r5) # return TUS_RCVERR
509: tstl (sp)+ # and let turintr handle it
510: 1:
511: rsb
512: #endif
513:
514: /*
515: * Stray UNIBUS interrupt catch routines
516: */
517: .data
518: .align 2
519: #define PJ PUSHR;jsb _Xustray
520: .globl _catcher
521: _catcher:
522: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
523: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
524: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
525: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
526: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
527: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
528: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
529: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
530:
531: .globl _cold
532: _cold: .long 1
533: .data
534:
535: .text
536: SCBVEC(ustray):
537: blbc _cold,1f
538: mfpr $IPL,r11
539: subl3 $_catcher+8,(sp)+,r10
540: ashl $-1,r10,r10
541: POPR
542: rei
543: 1:
544: subl3 $_catcher+8,(sp)+,r0
545: ashl $-1,r0,-(sp)
546: mfpr $IPL,-(sp)
547: PRINTF(2, "uba?: stray intr ipl %x vec %o\n")
548: POPR
549: rei
550:
551: #ifdef VAX630
552: /*
553: * Emulation OpCode jump table:
554: * ONLY GOES FROM 0xf8 (-8) TO 0x3B (59)
555: */
556: #define EMUTABLE 0x43
557: #define NOEMULATE .long noemulate
558: #define EMULATE(a) .long _EM/**/a
559: .globl _emJUMPtable
560: _emJUMPtable:
561: /* f8 */ EMULATE(ashp); EMULATE(cvtlp); NOEMULATE; NOEMULATE
562: /* fc */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
563: /* 00 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
564: /* 04 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
565: /* 08 */ EMULATE(cvtps); EMULATE(cvtsp); NOEMULATE; EMULATE(crc)
566: /* 0c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
567: /* 10 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
568: /* 14 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
569: /* 18 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
570: /* 1c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
571: /* 20 */ EMULATE(addp4); EMULATE(addp6); EMULATE(subp4); EMULATE(subp6)
572: /* 24 */ EMULATE(cvtpt); EMULATE(mulp); EMULATE(cvttp); EMULATE(divp)
573: /* 28 */ NOEMULATE; EMULATE(cmpc3); EMULATE(scanc); EMULATE(spanc)
574: /* 2c */ NOEMULATE; EMULATE(cmpc5); EMULATE(movtc); EMULATE(movtuc)
575: /* 30 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
576: /* 34 */ EMULATE(movp); EMULATE(cmpp3); EMULATE(cvtpl); EMULATE(cmpp4)
577: /* 38 */ EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc)
578: #endif
579:
580: /*
581: * Trap and fault vector routines
582: */
583: #define TRAP(a) pushl $T_/**/a; jbr alltraps
584:
585: /*
586: * Ast delivery (profiling and/or reschedule)
587: */
588: SCBVEC(astflt):
589: pushl $0; TRAP(ASTFLT)
590: SCBVEC(privinflt):
591: pushl $0; TRAP(PRIVINFLT)
592: SCBVEC(xfcflt):
593: pushl $0; TRAP(XFCFLT)
594: SCBVEC(resopflt):
595: pushl $0; TRAP(RESOPFLT)
596: SCBVEC(resadflt):
597: pushl $0; TRAP(RESADFLT)
598: SCBVEC(bptflt):
599: pushl $0; TRAP(BPTFLT)
600: SCBVEC(compatflt):
601: TRAP(COMPATFLT);
602: SCBVEC(tracep):
603: pushl $0; TRAP(TRCTRAP)
604: SCBVEC(arithtrap):
605: TRAP(ARITHTRAP)
606: SCBVEC(protflt):
607: blbs (sp)+,segflt
608: TRAP(PROTFLT)
609: segflt:
610: TRAP(SEGFLT)
611:
612: /*
613: * The following is called with the stack set up as follows:
614: *
615: * (sp): Opcode
616: * 4(sp): Instruction PC
617: * 8(sp): Operand 1
618: * 12(sp): Operand 2
619: * 16(sp): Operand 3
620: * 20(sp): Operand 4
621: * 24(sp): Operand 5
622: * 28(sp): Operand 6
623: * 32(sp): Operand 7 (unused)
624: * 36(sp): Operand 8 (unused)
625: * 40(sp): Return PC
626: * 44(sp): Return PSL
627: * 48(sp): TOS before instruction
628: *
629: * Each individual routine is called with the stack set up as follows:
630: *
631: * (sp): Return address of trap handler
632: * 4(sp): Opcode (will get return PSL)
633: * 8(sp): Instruction PC
634: * 12(sp): Operand 1
635: * 16(sp): Operand 2
636: * 20(sp): Operand 3
637: * 24(sp): Operand 4
638: * 28(sp): Operand 5
639: * 32(sp): Operand 6
640: * 36(sp): saved register 11
641: * 40(sp): saved register 10
642: * 44(sp): Return PC
643: * 48(sp): Return PSL
644: * 52(sp): TOS before instruction
645: */
646:
647: SCBVEC(emulate):
648: #ifdef VAX630
649: movl r11,32(sp) # save register r11 in unused operand
650: movl r10,36(sp) # save register r10 in unused operand
651: cvtbl (sp),r10 # get opcode
652: addl2 $8,r10 # shift negative opcodes
653: subl3 r10,$EMUTABLE,r11 # forget it if opcode is out of range
654: bcs noemulate
655: movl _emJUMPtable[r10],r10 # call appropriate emulation routine
656: jsb (r10) # routines put return values into regs 0-5
657: movl 32(sp),r11 # restore register r11
658: movl 36(sp),r10 # restore register r10
659: insv (sp),$0,$4,44(sp) # and condition codes in Opcode spot
660: addl2 $40,sp # adjust stack for return
661: rei
662: noemulate:
663: addl2 $48,sp # adjust stack for
664: #endif VAX630
665: .word 0xffff # "reserved instruction fault"
666: SCBVEC(emulateFPD):
667: .word 0xffff # "reserved instruction fault"
668: SCBVEC(transflt):
669: bitl $2,(sp)+
670: bnequ tableflt
671: jsb Fastreclaim # try and avoid pagein
672: TRAP(PAGEFLT)
673: tableflt:
674: TRAP(TABLEFLT)
675:
676: alltraps:
677: mfpr $USP,-(sp); calls $0,_trap; mtpr (sp)+,$USP
678: incl _cnt+V_TRAP
679: addl2 $8,sp # pop type, code
680: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
681: rei
682:
683: SCBVEC(syscall):
684: pushl $T_SYSCALL
685: mfpr $USP,-(sp); calls $0,_syscall; mtpr (sp)+,$USP
686: incl _cnt+V_SYSCALL
687: addl2 $8,sp # pop type, code
688: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
689: rei
690:
691: /*
692: * System page table
693: * Mbmap and Usrptmap are enlarged by CLSIZE entries
694: * as they are managed by resource maps starting with index 1 or CLSIZE.
695: */
696: #define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+0x80000000)
697: #define SYSMAP(mname, vname, npte) \
698: _/**/mname: .globl _/**/mname; \
699: .space (npte)*4; \
700: .globl _/**/vname; \
701: .set _/**/vname,vaddr(_/**/mname)
702:
703: .data
704: .align 2
705: SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE )
706: SYSMAP(Forkmap ,forkutl ,UPAGES )
707: SYSMAP(Xswapmap ,xswaputl ,UPAGES )
708: SYSMAP(Xswap2map,xswap2utl ,UPAGES )
709: SYSMAP(Swapmap ,swaputl ,UPAGES )
710: SYSMAP(Pushmap ,pushutl ,UPAGES )
711: SYSMAP(Vfmap ,vfutl ,UPAGES )
712: SYSMAP(CMAP1 ,CADDR1 ,1 )
713: SYSMAP(CMAP2 ,CADDR2 ,1 )
714: SYSMAP(mmap ,vmmap ,1 )
715: SYSMAP(alignmap ,alignutl ,1 ) /* XXX */
716: SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT )
717: SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*CLSIZE+CLSIZE )
718: SYSMAP(camap ,cabase ,16*CLSIZE )
719: #ifdef GPROF
720: SYSMAP(profmap ,profbase ,600*CLSIZE )
721: #endif
722: SYSMAP(ecamap ,calimit ,0 )
723:
724: SYSMAP(UMBAbeg ,umbabeg ,0 )
725: SYSMAP(Nexmap ,nexus ,16*MAXNNEXUS )
726: SYSMAP(UMEMmap ,umem ,UBAPAGES*NUBA )
727: SYSMAP(Ioamap ,ioa ,MAXNIOA*IOAMAPSIZ/NBPG )
728: SYSMAP(UMBAend ,umbaend ,0 )
729: #if VAX630
730: SYSMAP(Clockmap ,cldevice ,1 )
731: SYSMAP(Ka630map ,ka630cpu ,1 )
732: #endif
733:
734: SYSMAP(Usrptmap ,usrpt ,USRPTSIZE+CLSIZE )
735:
736: eSysmap:
737: .globl _Syssize
738: .set _Syssize,(eSysmap-_Sysmap)/4
739: .text
740:
741: /*
742: * Initialization
743: *
744: * ipl 0x1f; mapen 0; scbb, pcbb, sbr, slr, isp, ksp not set
745: */
746: .data
747: .globl _cpu
748: _cpu: .long 0
749: .text
750: .globl start
751: start:
752: .word 0
753: mtpr $0,$ICCS
754: /* set system control block base and system page table params */
755: mtpr $_scb-0x80000000,$SCBB
756: mtpr $_Sysmap-0x80000000,$SBR
757: mtpr $_Syssize,$SLR
758: /* double map the kernel into the virtual user addresses of phys mem */
759: mtpr $_Sysmap,$P0BR
760: mtpr $_Syssize,$P0LR
761: /* set ISP and get cpu type */
762: movl $_intstack+NISP*NBPG,sp
763: mfpr $SID,r0
764: movab _cpu,r1
765: extzv $24,$8,r0,(r1)
766: /* init RPB */
767: movab _rpb,r0
768: movl r0,(r0)+ # rp_selfref
769: movab _doadump,r1
770: movl r1,(r0)+ # rp_dumprout
771: movl $0x1f,r2
772: clrl r3
773: 1: addl2 (r1)+,r3; sobgtr r2,1b
774: movl r3,(r0)+ # rp_chksum
775: /* count up memory */
776: clrl r7
777: 1: pushl $4; pushl r7; calls $2,_badaddr; tstl r0; bneq 9f
778: acbl $MAXMEM*1024-1,$64*1024,r7,1b
779: 9:
780: #ifdef VAX630
781: /* leave an area for uVAX II console scratch pad at the top */
782: cmpb _cpu,$VAX_630
783: bneq 1f
784: subl2 $4096,r7
785: 1:
786: #endif
787: /* clear memory from kernel bss and pages for proc 0 u. and page table */
788: movab _edata,r6
789: movab _end,r5
790: bbcc $31,r5,0f; 0:
791: addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5
792: 1: clrq (r6); acbl r5,$8,r6,1b
793: /* trap() and syscall() save r0-r11 in the entry mask (per ../h/reg.h) */
794: /* panic() is convenient place to save all for debugging */
795: bisw2 $0x0fff,_trap
796: bisw2 $0x0fff,_syscall
797: bisw2 $0x0fff,_panic
798: calls $0,_fixctlrmask
799: /* initialize system page table: uba vectors and int stack writeable */
800: clrl r2
801: movab eintstack,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1
802: 1: bisl3 $PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b
803: /* make rpb, scb read-only as red zone for interrupt stack */
804: bicl2 $PG_PROT,_rpbmap
805: bisl2 $PG_KR,_rpbmap
806: /* make kernel text space read-only */
807: movab _etext+NBPG-1,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1
808: 1: bisl3 $PG_V|PG_URKR,r2,_Sysmap[r2]; aoblss r1,r2,1b
809: /* make kernel data, bss, read-write */
810: movab _end+NBPG-1,r1; bbcc $31,r1,0f; 0:; ashl $-PGSHIFT,r1,r1
811: 1: bisl3 $PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b
812: /* now go to mapped mode */
813: mtpr $0,$TBIA; mtpr $1,$MAPEN; jmp *$0f; 0:
814: /* init mem sizes */
815: ashl $-PGSHIFT,r7,_maxmem
816: movl _maxmem,_physmem
817: movl _maxmem,_freemem
818: /* setup context for proc[0] == Scheduler */
819: movab _end+NBPG-1,r6
820: bicl2 $NBPG-1,r6 # make page boundary
821: /* setup page table for proc[0] */
822: bbcc $31,r6,0f; 0:
823: ashl $-PGSHIFT,r6,r3 # r3 = btoc(r6)
824: bisl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry
825: incl r3
826: movab _usrpt,r0
827: mtpr r0,$TBIS
828: /* init p0br, p0lr */
829: mtpr r0,$P0BR
830: mtpr $0,$P0LR
831: /* init p1br, p1lr */
832: movab NBPG(r0),r0
833: movl $0x200000-UPAGES,r1
834: mtpr r1,$P1LR
835: mnegl r1,r1
836: moval -4*UPAGES(r0)[r1],r2
837: mtpr r2,$P1BR
838: /* setup mapping for UPAGES of _u */
839: movl $UPAGES,r2; movab _u+NBPG*UPAGES,r1; addl2 $UPAGES,r3; jbr 2f
840: 1: decl r3
841: moval -NBPG(r1),r1;
842: bisl3 $PG_V|PG_URKW,r3,-(r0)
843: mtpr r1,$TBIS
844: 2: sobgeq r2,1b
845: /* initialize (slightly) the pcb */
846: movab UPAGES*NBPG(r1),PCB_KSP(r1)
847: mnegl $1,PCB_ESP(r1)
848: mnegl $1,PCB_SSP(r1)
849: movl r1,PCB_USP(r1)
850: mfpr $P0BR,PCB_P0BR(r1)
851: mfpr $P0LR,PCB_P0LR(r1)
852: movb $4,PCB_P0LR+3(r1) # disable ast
853: mfpr $P1BR,PCB_P1BR(r1)
854: mfpr $P1LR,PCB_P1LR(r1)
855: movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt
856: movl r10,PCB_R10(r1)
857: movl r11,PCB_R11(r1)
858: movab 1f,PCB_PC(r1) # initial pc
859: clrl PCB_PSL(r1) # mode(k,k), ipl=0
860: ashl $PGSHIFT,r3,r3
861: mtpr r3,$PCBB # first pcbb
862: /* set regs, p0br, p0lr, p1br, p1lr, astlvl, ksp and change to kernel mode */
863: ldpctx
864: rei
865: /* put signal trampoline code in u. area */
866: 1: movab _u,r0
867: movc3 $19,sigcode,PCB_SIGC(r0)
868: /* save boot device in global _bootdev */
869: movl r10,_bootdev
870: /* save reboot flags in global _boothowto */
871: movl r11,_boothowto
872: /* calculate firstaddr, and call main() */
873: movab _end+NBPG-1,r0; bbcc $31,r0,0f; 0:; ashl $-PGSHIFT,r0,-(sp)
874: addl2 $UPAGES+1,(sp); calls $1,_main
875: /* proc[1] == /etc/init now running here; run icode */
876: pushl $PSL_CURMOD|PSL_PRVMOD; pushl $0; rei
877:
878: /* signal trampoline code: it is known that this code takes exactly 19 bytes */
879: /* in ../vax/pcb.h and in the movc3 above */
880: sigcode:
881: calls $4,8(pc) # params pushed by sendsig
882: movl sp,ap # calls frame built by sendsig
883: chmk $103 # cleanup mask and onsigstack
884: halt # sigreturn() does not return!
885: .word 0x3f # registers 0-5
886: callg (ap),*16(ap) # call the signal handler
887: ret # return to code above
888:
889: .set exec,11
890: .set exit,1
891: .globl _icode
892: .globl _initflags
893: .globl _szicode
894: /*
895: * Icode is copied out to process 1 to exec /etc/init.
896: * If the exec fails, process 1 exits.
897: */
898: _icode:
899: pushab b`argv-l0(pc)
900: l0: pushab b`init-l1(pc)
901: l1: pushl $2
902: movl sp,ap
903: chmk $exec
904: chmk $exit
905:
906: init: .asciz "/etc/init"
907: .align 2
908: _initflags:
909: .long 0
910: argv: .long init+5-_icode
911: .long _initflags-_icode
912: .long 0
913: _szicode:
914: .long _szicode-_icode
915:
916: /*
917: * Primitives
918: */
919:
920: #ifdef GPROF
921: #define ENTRY(name, regs) \
922: .globl _/**/name; .align 1; _/**/name: .word regs; jsb mcount
923: #define JSBENTRY(name, regs) \
924: .globl _/**/name; _/**/name: \
925: movl fp,-(sp); movab -12(sp),fp; pushr $(regs); jsb mcount; \
926: popr $(regs); movl (sp)+,fp
927: #else
928: #define ENTRY(name, regs) \
929: .globl _/**/name; .align 1; _/**/name: .word regs
930: #define JSBENTRY(name, regs) \
931: .globl _/**/name; _/**/name:
932: #endif GPROF
933: #define R0 0x01
934: #define R1 0x02
935: #define R2 0x04
936: #define R3 0x08
937: #define R4 0x10
938: #define R5 0x20
939: #define R6 0x40
940:
941: /*
942: * badaddr(addr, len)
943: * see if access addr with a len type instruction causes a machine check
944: * len is length of access (1=byte, 2=short, 4=long)
945: */
946: .globl _badaddr
947: _badaddr:
948: .word 0
949: movl $1,r0
950: mfpr $IPL,r1
951: mtpr $HIGH,$IPL
952: movl 4(ap),r3
953: movl 8(ap),r4
954: movab 2f,nofault # jump to 2f on machcheck
955: bbc $0,r4,1f; tstb (r3)
956: 1: bbc $1,r4,1f; tstw (r3)
957: 1: bbc $2,r4,1f; tstl (r3)
958: 1: clrl r0 # made it w/o machine checks
959: 2: clrl nofault
960: mtpr r1,$IPL
961: ret
962:
963: /*
964: * update profiling information for the user
965: * addupc(pc, &u.u_prof, ticks)
966: */
967: ENTRY(addupc, 0)
968: movl 8(ap),r2 # &u.u_prof
969: subl3 8(r2),4(ap),r0 # corrected pc
970: blss 9f
971: extzv $1,$31,r0,r0 # logical right shift
972: extzv $1,$31,12(r2),r1 # ditto for scale
973: emul r1,r0,$0,r0
974: ashq $-14,r0,r0
975: tstl r1
976: bneq 9f
977: bicl2 $1,r0
978: cmpl r0,4(r2) # length
979: bgequ 9f
980: addl2 (r2),r0 # base
981: probew $3,$2,(r0)
982: beql 8f
983: addw2 12(ap),(r0)
984: 9:
985: ret
986: 8:
987: clrl 12(r2)
988: ret
989:
990: /*
991: * Copy a null terminated string from the user address space into
992: * the kernel address space.
993: *
994: * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
995: */
996: ENTRY(copyinstr, R6)
997: movl 12(ap),r6 # r6 = max length
998: jlss 8f
999: movl 4(ap),r1 # r1 = user address
1000: bicl3 $~(NBPG*CLSIZE-1),r1,r2 # r2 = bytes on first page
1001: subl3 r2,$NBPG*CLSIZE,r2
1002: movl 8(ap),r3 # r3 = kernel address
1003: 1:
1004: cmpl r6,r2 # r2 = min(bytes on page, length left);
1005: jgeq 2f
1006: movl r6,r2
1007: 2:
1008: prober $3,r2,(r1) # bytes accessible?
1009: jeql 8f
1010: subl2 r2,r6 # update bytes left count
1011: #ifdef NOSUBSINST
1012: # fake the locc instr. for processors that don't have it
1013: movl r2,r0
1014: 6:
1015: tstb (r1)+
1016: jeql 5f
1017: sobgtr r0,6b
1018: jbr 7f
1019: 5:
1020: decl r1
1021: jbr 3f
1022: 7:
1023: #else
1024: locc $0,r2,(r1) # null byte found?
1025: jneq 3f
1026: #endif
1027: subl2 r2,r1 # back up pointer updated by `locc'
1028: movc3 r2,(r1),(r3) # copy in next piece
1029: movl $(NBPG*CLSIZE),r2 # check next page
1030: tstl r6 # run out of space?
1031: jneq 1b
1032: movl $ENOENT,r0 # set error code and return
1033: jbr 9f
1034: 3:
1035: tstl 16(ap) # return length?
1036: beql 4f
1037: subl3 r6,12(ap),r6 # actual len = maxlen - unused pages
1038: subl2 r0,r6 # - unused on this page
1039: addl3 $1,r6,*16(ap) # + the null byte
1040: 4:
1041: subl2 r0,r2 # r2 = number of bytes to move
1042: subl2 r2,r1 # back up pointer updated by `locc'
1043: incl r2 # copy null byte as well
1044: movc3 r2,(r1),(r3) # copy in last piece
1045: clrl r0 # redundant
1046: ret
1047: 8:
1048: movl $EFAULT,r0
1049: 9:
1050: tstl 16(ap)
1051: beql 1f
1052: subl3 r6,12(ap),*16(ap)
1053: 1:
1054: ret
1055:
1056: /*
1057: * Copy a null terminated string from the kernel
1058: * address space to the user address space.
1059: *
1060: * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
1061: */
1062: ENTRY(copyoutstr, R6)
1063: movl 12(ap),r6 # r6 = max length
1064: jlss 8b
1065: movl 4(ap),r1 # r1 = kernel address
1066: movl 8(ap),r3 # r3 = user address
1067: bicl3 $~(NBPG*CLSIZE-1),r3,r2 # r2 = bytes on first page
1068: subl3 r2,$NBPG*CLSIZE,r2
1069: 1:
1070: cmpl r6,r2 # r2 = min(bytes on page, length left);
1071: jgeq 2f
1072: movl r6,r2
1073: 2:
1074: probew $3,r2,(r3) # bytes accessible?
1075: jeql 8b
1076: subl2 r2,r6 # update bytes left count
1077: #ifdef NOSUBSINST
1078: # fake the locc instr. for processors that don't have it
1079: movl r2,r0
1080: 6:
1081: tstb (r1)+
1082: jeql 5f
1083: sobgtr r0,6b
1084: jbr 7f
1085: 5:
1086: decl r1
1087: jbr 3b
1088: 7:
1089: #else
1090: locc $0,r2,(r1) # null byte found?
1091: jneq 3b
1092: #endif
1093: subl2 r2,r1 # back up pointer updated by `locc'
1094: movc3 r2,(r1),(r3) # copy in next piece
1095: movl $(NBPG*CLSIZE),r2 # check next page
1096: tstl r6 # run out of space?
1097: jneq 1b
1098: movl $ENOENT,r0 # set error code and return
1099: jbr 9b
1100:
1101: /*
1102: * Copy a null terminated string from one point to another in
1103: * the kernel address space.
1104: *
1105: * copystr(fromaddr, toaddr, maxlength, &lencopied)
1106: */
1107: ENTRY(copystr, R6)
1108: movl 12(ap),r6 # r6 = max length
1109: jlss 8b
1110: movl 4(ap),r1 # r1 = src address
1111: movl 8(ap),r3 # r3 = dest address
1112: 1:
1113: movzwl $65535,r2 # r2 = bytes in first chunk
1114: cmpl r6,r2 # r2 = min(bytes in chunk, length left);
1115: jgeq 2f
1116: movl r6,r2
1117: 2:
1118: subl2 r2,r6 # update bytes left count
1119: #ifdef NOSUBSINST
1120: # fake the locc instr. for processors that don't have it
1121: movl r2,r0
1122: 6:
1123: tstb (r1)+
1124: jeql 5f
1125: sobgtr r0,6b
1126: jbr 7f
1127: 5:
1128: decl r1
1129: jbr 3b
1130: 7:
1131: #else
1132: locc $0,r2,(r1) # null byte found?
1133: jneq 3b
1134: #endif
1135: subl2 r2,r1 # back up pointer updated by `locc'
1136: movc3 r2,(r1),(r3) # copy in next piece
1137: tstl r6 # run out of space?
1138: jneq 1b
1139: movl $ENOENT,r0 # set error code and return
1140: jbr 9b
1141:
1142: /*
1143: * Copy specified amount of data from user space into the kernel
1144: * Copyin(from, to, len)
1145: * r1 == from (user source address)
1146: * r3 == to (kernel destination address)
1147: * r5 == length
1148: */
1149: .align 1
1150: JSBENTRY(Copyin, R1|R3|R5)
1151: cmpl r5,$(NBPG*CLSIZE) # probing one page or less ?
1152: bgtru 1f # no
1153: prober $3,r5,(r1) # bytes accessible ?
1154: beql ersb # no
1155: movc3 r5,(r1),(r3)
1156: /* clrl r0 # redundant */
1157: rsb
1158: 1:
1159: blss ersb # negative length?
1160: pushl r6 # r6 = length
1161: movl r5,r6
1162: bicl3 $~(NBPG*CLSIZE-1),r1,r0 # r0 = bytes on first page
1163: subl3 r0,$(NBPG*CLSIZE),r0
1164: addl2 $(NBPG*CLSIZE),r0 # plus one additional full page
1165: jbr 2f
1166:
1167: ciloop:
1168: movc3 r0,(r1),(r3)
1169: movl $(2*NBPG*CLSIZE),r0 # next amount to move
1170: 2:
1171: cmpl r0,r6
1172: bleq 3f
1173: movl r6,r0
1174: 3:
1175: prober $3,r0,(r1) # bytes accessible ?
1176: beql ersb1 # no
1177: subl2 r0,r6 # last move?
1178: bneq ciloop # no
1179:
1180: movc3 r0,(r1),(r3)
1181: /* clrl r0 # redundant */
1182: movl (sp)+,r6 # restore r6
1183: rsb
1184:
1185: ersb1:
1186: movl (sp)+,r6 # restore r6
1187: ersb:
1188: movl $EFAULT,r0
1189: rsb
1190:
1191: /*
1192: * Copy specified amount of data from kernel to the user space
1193: * Copyout(from, to, len)
1194: * r1 == from (kernel source address)
1195: * r3 == to (user destination address)
1196: * r5 == length
1197: */
1198: .align 1
1199: JSBENTRY(Copyout, R1|R3|R5)
1200: cmpl r5,$(NBPG*CLSIZE) # moving one page or less ?
1201: bgtru 1f # no
1202: probew $3,r5,(r3) # bytes writeable?
1203: beql ersb # no
1204: movc3 r5,(r1),(r3)
1205: /* clrl r0 # redundant */
1206: rsb
1207: 1:
1208: blss ersb # negative length?
1209: pushl r6 # r6 = length
1210: movl r5,r6
1211: bicl3 $~(NBPG*CLSIZE-1),r3,r0 # r0 = bytes on first page
1212: subl3 r0,$(NBPG*CLSIZE),r0
1213: addl2 $(NBPG*CLSIZE),r0 # plus one additional full page
1214: jbr 2f
1215:
1216: coloop:
1217: movc3 r0,(r1),(r3)
1218: movl $(2*NBPG*CLSIZE),r0 # next amount to move
1219: 2:
1220: cmpl r0,r6
1221: bleq 3f
1222: movl r6,r0
1223: 3:
1224: probew $3,r0,(r3) # bytes writeable?
1225: beql ersb1 # no
1226: subl2 r0,r6 # last move?
1227: bneq coloop # no
1228:
1229: movc3 r0,(r1),(r3)
1230: /* clrl r0 # redundant */
1231: movl (sp)+,r6 # restore r6
1232: rsb
1233:
1234: /*
1235: * non-local goto's
1236: */
1237: #ifdef notdef /* this is now expanded completely inline */
1238: .align 1
1239: JSBENTRY(Setjmp, R0)
1240: movl fp,(r0)+ # current stack frame
1241: movl (sp),(r0) # resuming pc
1242: clrl r0
1243: rsb
1244: #endif
1245:
1246: #define PCLOC 16 /* location of pc in calls frame */
1247: #define APLOC 8 /* location of ap,fp in calls frame */
1248: .align 1
1249: JSBENTRY(Longjmp, R0)
1250: movl (r0)+,newfp # must save parameters in memory as all
1251: movl (r0),newpc # registers may be clobbered.
1252: 1:
1253: cmpl fp,newfp # are we there yet?
1254: bgequ 2f # yes
1255: moval 1b,PCLOC(fp) # redirect return pc to us!
1256: ret # pop next frame
1257: 2:
1258: beql 3f # did we miss our frame?
1259: pushab 4f # yep ?!?
1260: calls $1,_panic
1261: 3:
1262: movl newpc,r0 # all done, just return to the `setjmp'
1263: jmp (r0) # ``rsb''
1264:
1265: .data
1266: newpc: .space 4
1267: newfp: .space 4
1268: 4: .asciz "longjmp"
1269: .text
1270: /*
1271: * setjmp that saves all registers as the call frame may not
1272: * be available to recover them in the usual mannor by longjmp.
1273: * Called before swapping out the u. area, restored by resume()
1274: * below.
1275: */
1276: ENTRY(savectx, 0)
1277: movl 4(ap),r0
1278: movq r6,(r0)+
1279: movq r8,(r0)+
1280: movq r10,(r0)+
1281: movq APLOC(fp),(r0)+ # save ap, fp
1282: addl3 $8,ap,(r0)+ # save sp
1283: movl PCLOC(fp),(r0) # save pc
1284: clrl r0
1285: ret
1286:
1287: .globl _whichqs
1288: .globl _qs
1289: .globl _cnt
1290:
1291: .globl _noproc
1292: .comm _noproc,4
1293: .globl _runrun
1294: .comm _runrun,4
1295:
1296: /*
1297: * The following primitives use the fancy VAX instructions
1298: * much like VMS does. _whichqs tells which of the 32 queues _qs
1299: * have processes in them. Setrq puts processes into queues, Remrq
1300: * removes them from queues. The running process is on no queue,
1301: * other processes are on a queue related to p->p_pri, divided by 4
1302: * actually to shrink the 0-127 range of priorities into the 32 available
1303: * queues.
1304: */
1305:
1306: /*
1307: * Setrq(p), using fancy VAX instructions.
1308: *
1309: * Call should be made at splclock(), and p->p_stat should be SRUN
1310: */
1311: .align 1
1312: JSBENTRY(Setrq, R0)
1313: tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0
1314: beql set1 ##
1315: pushab set3 ##
1316: calls $1,_panic ##
1317: set1:
1318: movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4
1319: ashl $-2,r1,r1
1320: movaq _qs[r1],r2
1321: insque (r0),*4(r2) # at end of queue
1322: bbss r1,_whichqs,set2 # mark queue non-empty
1323: set2:
1324: rsb
1325:
1326: set3: .asciz "setrq"
1327:
1328: /*
1329: * Remrq(p), using fancy VAX instructions
1330: *
1331: * Call should be made at splclock().
1332: */
1333: .align 1
1334: JSBENTRY(Remrq, R0)
1335: movzbl P_PRI(r0),r1
1336: ashl $-2,r1,r1
1337: bbsc r1,_whichqs,rem1
1338: pushab rem3 # it wasn't recorded to be on its q
1339: calls $1,_panic
1340: rem1:
1341: remque (r0),r2
1342: beql rem2
1343: bbss r1,_whichqs,rem2
1344: rem2:
1345: clrl P_RLINK(r0) ## for firewall checking
1346: rsb
1347:
1348: rem3: .asciz "remrq"
1349:
1350: /*
1351: * Masterpaddr is the p->p_addr of the running process on the master
1352: * processor. When a multiprocessor system, the slave processors will have
1353: * an array of slavepaddr's.
1354: */
1355: .globl _masterpaddr
1356: .data
1357: _masterpaddr:
1358: .long 0
1359:
1360: .set ASTLVL_NONE,4
1361: .text
1362: sw0: .asciz "swtch"
1363:
1364: /*
1365: * When no processes are on the runq, Swtch branches to idle
1366: * to wait for something to come ready.
1367: */
1368: .globl Idle
1369: Idle: idle:
1370: mtpr $0,$IPL # must allow interrupts here
1371: tstl _whichqs # look for non-empty queue
1372: bneq sw1
1373: brb idle
1374:
1375: badsw: pushab sw0
1376: calls $1,_panic
1377: /*NOTREACHED*/
1378:
1379: /*
1380: * Swtch(), using fancy VAX instructions
1381: */
1382: .align 1
1383: JSBENTRY(Swtch, 0)
1384: movl $1,_noproc
1385: incl _cnt+V_SWTCH
1386: sw1: ffs $0,$32,_whichqs,r0 # look for non-empty queue
1387: beql idle # if none, idle
1388: mtpr $0x18,$IPL # lock out all so _whichqs==_qs
1389: bbcc r0,_whichqs,sw1 # proc moved via lbolt interrupt
1390: movaq _qs[r0],r1
1391: remque *(r1),r2 # r2 = p = highest pri process
1392: bvs badsw # make sure something was there
1393: sw2: beql sw3
1394: insv $1,r0,$1,_whichqs # still more procs in this queue
1395: sw3:
1396: clrl _noproc
1397: clrl _runrun
1398: tstl P_WCHAN(r2) ## firewalls
1399: bneq badsw ##
1400: cmpb P_STAT(r2),$SRUN ##
1401: bneq badsw ##
1402: clrl P_RLINK(r2) ##
1403: movl *P_ADDR(r2),r0
1404: #ifdef notdef
1405: cmpl r0,_masterpaddr # resume of current proc is easy
1406: beql res0
1407: #endif
1408: movl r0,_masterpaddr
1409: ashl $PGSHIFT,r0,r0 # r0 = pcbb(p)
1410: /* fall into... */
1411:
1412: /*
1413: * Resume(pf)
1414: */
1415: JSBENTRY(Resume, R0)
1416: mtpr $HIGH,$IPL # no interrupts, please
1417: movl _CMAP2,_u+PCB_CMAP2 # yech
1418: svpctx
1419: mtpr r0,$PCBB
1420: ldpctx
1421: movl _u+PCB_CMAP2,_CMAP2 # yech
1422: mtpr $_CADDR2,$TBIS
1423: res0:
1424: tstl _u+PCB_SSWAP
1425: bneq res1
1426: rei
1427: res1:
1428: movl _u+PCB_SSWAP,r0 # longjmp to saved context
1429: clrl _u+PCB_SSWAP
1430: movq (r0)+,r6
1431: movq (r0)+,r8
1432: movq (r0)+,r10
1433: movq (r0)+,r12
1434: movl (r0)+,r1
1435: cmpl r1,sp # must be a pop
1436: bgequ 1f
1437: pushab 2f
1438: calls $1,_panic
1439: /* NOTREACHED */
1440: 1:
1441: movl r1,sp
1442: movl (r0),(sp) # address to return to
1443: movl $PSL_PRVMOD,4(sp) # ``cheating'' (jfr)
1444: rei
1445:
1446: 2: .asciz "ldctx"
1447:
1448: /*
1449: * {fu,su},{byte,word}, all massaged by asm.sed to jsb's
1450: */
1451: .align 1
1452: JSBENTRY(Fuword, R0)
1453: prober $3,$4,(r0)
1454: beql fserr
1455: movl (r0),r0
1456: rsb
1457: fserr:
1458: mnegl $1,r0
1459: rsb
1460:
1461: .align 1
1462: JSBENTRY(Fubyte, R0)
1463: prober $3,$1,(r0)
1464: beql fserr
1465: movzbl (r0),r0
1466: rsb
1467:
1468: .align 1
1469: JSBENTRY(Suword, R0|R1)
1470: probew $3,$4,(r0)
1471: beql fserr
1472: movl r1,(r0)
1473: clrl r0
1474: rsb
1475:
1476: .align 1
1477: JSBENTRY(Subyte, R0|R1)
1478: probew $3,$1,(r0)
1479: beql fserr
1480: movb r1,(r0)
1481: clrl r0
1482: rsb
1483:
1484: /*
1485: * Copy 1 relocation unit (NBPG bytes)
1486: * from user virtual address to physical address
1487: */
1488: ENTRY(copyseg, 0)
1489: bisl3 $PG_V|PG_KW,8(ap),_CMAP2
1490: mtpr $_CADDR2,$TBIS # invalidate entry for copy
1491: movc3 $NBPG,*4(ap),_CADDR2
1492: ret
1493:
1494: /*
1495: * zero out physical memory
1496: * specified in relocation units (NBPG bytes)
1497: */
1498: ENTRY(clearseg, 0)
1499: bisl3 $PG_V|PG_KW,4(ap),_CMAP1
1500: mtpr $_CADDR1,$TBIS
1501: movc5 $0,(sp),$0,$NBPG,_CADDR1
1502: ret
1503:
1504: /*
1505: * Check address.
1506: * Given virtual address, byte count, and rw flag
1507: * returns 0 on no access.
1508: */
1509: ENTRY(useracc, 0)
1510: movl 4(ap),r0 # get va
1511: movl 8(ap),r1 # count
1512: tstl 12(ap) # test for read access ?
1513: bneq userar # yes
1514: cmpl $NBPG,r1 # can we do it in one probe ?
1515: bgeq uaw2 # yes
1516: uaw1:
1517: probew $3,$NBPG,(r0)
1518: beql uaerr # no access
1519: addl2 $NBPG,r0
1520: acbl $NBPG+1,$-NBPG,r1,uaw1
1521: uaw2:
1522: probew $3,r1,(r0)
1523: beql uaerr
1524: movl $1,r0
1525: ret
1526:
1527: userar:
1528: cmpl $NBPG,r1
1529: bgeq uar2
1530: uar1:
1531: prober $3,$NBPG,(r0)
1532: beql uaerr
1533: addl2 $NBPG,r0
1534: acbl $NBPG+1,$-NBPG,r1,uar1
1535: uar2:
1536: prober $3,r1,(r0)
1537: beql uaerr
1538: movl $1,r0
1539: ret
1540: uaerr:
1541: clrl r0
1542: ret
1543:
1544: /*
1545: * kernacc - check for kernel access privileges
1546: *
1547: * We can't use the probe instruction directly because
1548: * it ors together current and previous mode.
1549: */
1550: ENTRY(kernacc, 0)
1551: movl 4(ap),r0 # virtual address
1552: bbcc $31,r0,kacc1
1553: bbs $30,r0,kacerr
1554: mfpr $SBR,r2 # address and length of page table (system)
1555: bbss $31,r2,0f; 0:
1556: mfpr $SLR,r3
1557: brb kacc2
1558: kacc1:
1559: bbsc $30,r0,kacc3
1560: mfpr $P0BR,r2 # user P0
1561: mfpr $P0LR,r3
1562: brb kacc2
1563: kacc3:
1564: mfpr $P1BR,r2 # user P1 (stack)
1565: mfpr $P1LR,r3
1566: kacc2:
1567: addl3 8(ap),r0,r1 # ending virtual address
1568: addl2 $NBPG-1,r1
1569: ashl $-PGSHIFT,r0,r0
1570: ashl $-PGSHIFT,r1,r1
1571: bbs $31,4(ap),kacc6
1572: bbc $30,4(ap),kacc6
1573: cmpl r0,r3 # user stack
1574: blss kacerr # address too low
1575: brb kacc4
1576: kacc6:
1577: cmpl r1,r3 # compare last page to P0LR or SLR
1578: bgtr kacerr # address too high
1579: kacc4:
1580: movl (r2)[r0],r3
1581: bbc $31,4(ap),kacc4a
1582: bbc $31,r3,kacerr # valid bit is off
1583: kacc4a:
1584: cmpzv $27,$4,r3,$1 # check protection code
1585: bleq kacerr # no access allowed
1586: tstb 12(ap)
1587: bneq kacc5 # only check read access
1588: cmpzv $27,$2,r3,$3 # check low 2 bits of prot code
1589: beql kacerr # no write access
1590: kacc5:
1591: aoblss r1,r0,kacc4 # next page
1592: movl $1,r0 # no errors
1593: ret
1594: kacerr:
1595: clrl r0 # error
1596: ret
1597: /*
1598: * Extracted and unrolled most common case of pagein (hopefully):
1599: * resident and not on free list (reclaim of page is purely
1600: * for the purpose of simulating a reference bit)
1601: *
1602: * Built in constants:
1603: * CLSIZE of 2, any bit fields in pte's
1604: */
1605: .text
1606: .globl Fastreclaim
1607: Fastreclaim:
1608: PUSHR
1609: #ifdef GPROF
1610: movl fp,-(sp)
1611: movab 12(sp),fp
1612: jsb mcount
1613: movl (sp)+,fp
1614: #endif GPROF
1615: extzv $9,$23,28(sp),r3 # virtual address
1616: bicl2 $1,r3 # v = clbase(btop(virtaddr));
1617: movl _u+U_PROCP,r5 # p = u.u_procp
1618: # from vtopte(p, v) ...
1619: movl $1,r2 # type = CTEXT;
1620: cmpl r3,P_TSIZE(r5)
1621: jlssu 1f # if (isatsv(p, v)) {
1622: addl3 P_TSIZE(r5),P_DSIZE(r5),r0
1623: cmpl r3,r0
1624: jgequ 2f
1625: clrl r2 # type = !CTEXT;
1626: 1:
1627: ashl $2,r3,r4
1628: addl2 P_P0BR(r5),r4 # tptopte(p, vtotp(p, v));
1629: jbr 3f
1630: 2:
1631: cvtwl P_SZPT(r5),r4 # } else (isassv(p, v)) {
1632: ashl $7,r4,r4
1633: subl2 $0x400000,r4
1634: addl2 r3,r4
1635: ashl $2,r4,r4
1636: addl2 P_P0BR(r5),r4 # sptopte(p, vtosp(p, v));
1637: clrl r2 # type = !CTEXT;
1638: 3: # }
1639: bitb $0x82,3(r4)
1640: beql 2f # if (pte->pg_v || pte->pg_fod)
1641: POPR; rsb # let pagein handle it
1642: 2:
1643: bicl3 $0xffe00000,(r4),r0
1644: jneq 2f # if (pte->pg_pfnum == 0)
1645: POPR; rsb # let pagein handle it
1646: 2:
1647: subl2 _firstfree,r0
1648: ashl $-1,r0,r0
1649: incl r0 # pgtocm(pte->pg_pfnum)
1650: mull2 $SZ_CMAP,r0
1651: addl2 _cmap,r0 # &cmap[pgtocm(pte->pg_pfnum)]
1652: tstl r2
1653: jeql 2f # if (type == CTEXT &&
1654: jbc $C_INTRANS,(r0),2f # c_intrans)
1655: POPR; rsb # let pagein handle it
1656: 2:
1657: jbc $C_FREE,(r0),2f # if (c_free)
1658: POPR; rsb # let pagein handle it
1659: 2:
1660: bisb2 $0x80,3(r4) # pte->pg_v = 1;
1661: jbc $26,4(r4),2f # if (anycl(pte, pg_m)
1662: bisb2 $0x04,3(r4) # pte->pg_m = 1;
1663: 2:
1664: bicw3 $0x7f,2(r4),r0
1665: bicw3 $0xff80,6(r4),r1
1666: bisw3 r0,r1,6(r4) # distcl(pte);
1667: ashl $PGSHIFT,r3,r0
1668: mtpr r0,$TBIS
1669: addl2 $NBPG,r0
1670: mtpr r0,$TBIS # tbiscl(v);
1671: tstl r2
1672: jeql 2f # if (type == CTEXT)
1673: movl P_TEXTP(r5),r0
1674: movl X_CADDR(r0),r5 # for (p = p->p_textp->x_caddr; p; ) {
1675: jeql 2f
1676: ashl $2,r3,r3
1677: 3:
1678: addl3 P_P0BR(r5),r3,r0 # tpte = tptopte(p, tp);
1679: bisb2 $1,P_FLAG+3(r5) # p->p_flag |= SPTECHG;
1680: movl (r4),(r0)+ # for (i = 0; i < CLSIZE; i++)
1681: movl 4(r4),(r0) # tpte[i] = pte[i];
1682: movl P_XLINK(r5),r5 # p = p->p_xlink;
1683: jneq 3b # }
1684: 2: # collect a few statistics...
1685: incl _u+U_RU+RU_MINFLT # u.u_ru.ru_minflt++;
1686: moval _cnt,r0
1687: incl V_FAULTS(r0) # cnt.v_faults++;
1688: incl V_PGREC(r0) # cnt.v_pgrec++;
1689: incl V_FASTPGREC(r0) # cnt.v_fastpgrec++;
1690: incl V_TRAP(r0) # cnt.v_trap++;
1691: POPR
1692: addl2 $8,sp # pop pc, code
1693: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
1694: rei
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.