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