|
|
1.1 root 1: /*
2: * Copyright (c) 1988 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.14 (Berkeley) 5/10/90
7: */
8:
9: #include "../tahoe/mtpr.h"
10: #include "../tahoe/trap.h"
11: #include "../tahoe/psl.h"
12: #include "../tahoe/pte.h"
13: #include "../tahoe/cp.h"
14: #include "../tahoe/mem.h"
15: #include "../tahoe/SYS.h"
16:
17: #include "../tahoemath/fp.h"
18:
19: #include "errno.h"
20: #include "syscall.h"
21: #include "cmap.h"
22:
23: .set HIGH,0x1f # mask for total disable
24: .set NISP,3 # number of interrupt stack pages
25: .set SYSTEM,0xC0000000 # virtual address of system start
26: .set PPAGES,0x100000 # possible pages in P0,P1, etc.
27:
28: /* ACBL for non-negative '_add' */
29: #define ACBL(_limit,_add,_index,_displ) \
30: addl2 _add,_index; \
31: cmpl _index,_limit; \
32: bleq _displ
33:
34: /* _ACBL for negative '_add' */
35: #define _ACBL(_limit,_add,_index,_displ) \
36: addl2 _add,_index; \
37: cmpl _index,_limit; \
38: bgeq _displ
39:
40: #define MOVC3(_srcaddr,_dstaddr,_len) \
41: movl _srcaddr,r0; \
42: movl _dstaddr,r1; \
43: movl _len,r2; \
44: movblk
45:
46: /* keep address of psl if coming from user mode */
47: #define CHECK_SFE(_delta) \
48: bitl $PSL_CURMOD,_delta(sp); \
49: jeql 1f; \
50: moval _delta(sp),_user_psl; \
51: 1:
52:
53: /*
54: * User structure is UPAGES at top of user space.
55: */
56: .globl _u
57: .set _u,SYSTEM - UPAGES*NBPG
58:
59: /*
60: * Restart stack. Used on power recovery or panic.
61: * Takes a core-dump and then halts.
62: */
63: .globl _rsstk
64: .globl pwfl_stk
65: _rsstk:
66: .space 1024-8
67: pwfl_stk:
68: .space 4
69: dumpflag:
70: .space 4
71:
72: .globl _intstack
73: _intstack:
74: .space NISP*NBPG
75: eintstack:
76:
77: /*
78: * Power failure storage block and
79: * macros for saving and restoring.
80: */
81: #define POWERFAIL(id,longs) \
82: .globl pwfl_/**/id \
83: pwfl_/**/id: .space longs*4
84: .data
85: POWERFAIL(r0, 14) # r0-r13
86: POWERFAIL(sp, 1) # r14
87: POWERFAIL(SCBB, 1) # system control block base
88: POWERFAIL(SBR, 1) # system pte base
89: POWERFAIL(SLR, 1) # system pte length
90: POWERFAIL(P0BR, 1) # p0 pte base
91: POWERFAIL(P0LR, 1) # p0 pte length
92: POWERFAIL(P1BR, 1) # p1 pte base
93: POWERFAIL(P1LR, 1) # p1 pte length
94: POWERFAIL(P2BR, 1) # p2 pte base
95: POWERFAIL(P2LR, 1) # p2 pte length
96: POWERFAIL(IPL, 1) # interrupt priority level
97: POWERFAIL(DCK, 1) # data cache key
98: POWERFAIL(CCK, 1) # code cache key
99: POWERFAIL(PCBB, 1) # process control block base
100: POWERFAIL(ISP, 1) # interrupt stack pointer
101: POWERFAIL(KSP, 1) # kernel mode stack pointer
102: POWERFAIL(USP, 1) # user mode stack pointer
103: POWERFAIL(MME, 1) # memory management enable
104: POWERFAIL(PSL, 1) # processor status longword
105:
106: /*
107: * Save current state in power fail storage block.
108: */
109: #define SAVEpwfl() \
110: movpsl pwfl_PSL # Keeps all flags, etc. \
111: storer $0x3fff,pwfl_r0 # Saves r0-r13 \
112: moval 0(sp),pwfl_sp # Saves sp (=r14) \
113: mfpr $SBR,pwfl_SBR # Save all re_loadable registers \
114: mfpr $SLR,pwfl_SLR \
115: mfpr $P0BR,pwfl_P0BR \
116: mfpr $P0LR,pwfl_P0LR \
117: mfpr $P1BR,pwfl_P1BR \
118: mfpr $P1LR,pwfl_P1LR \
119: mfpr $P2BR,pwfl_P2BR \
120: mfpr $P2LR,pwfl_P2LR \
121: mfpr $IPL,pwfl_IPL \
122: mfpr $MME,pwfl_MME \
123: mfpr $DCK,pwfl_DCK \
124: mfpr $CCK,pwfl_CCK \
125: mfpr $PCBB,pwfl_PCBB \
126: mfpr $ISP,pwfl_ISP \
127: mfpr $SCBB,pwfl_SCBB \
128: mfpr $KSP,pwfl_KSP \
129: mfpr $USP,pwfl_USP
130:
131: /*
132: * Restore state saved in power fail block and
133: * jmp to location specified after (possibly)
134: * enabling memory management.
135: */
136: #define RESTOREpwfl(loc) \
137: loadr $0x3fff,pwfl_r0 # Restore r0-r13 \
138: movl pwfl_sp,sp # Restore sp (=r14) \
139: mtpr pwfl_SCBB,$SCBB \
140: mtpr pwfl_SBR,$SBR # Restore all re_loadable registers \
141: mtpr pwfl_SLR,$SLR \
142: mtpr pwfl_P0BR,$P0BR \
143: mtpr pwfl_P0LR,$P0LR \
144: mtpr pwfl_P1BR,$P1BR \
145: mtpr pwfl_P1LR,$P1LR \
146: mtpr pwfl_P2BR,$P2BR \
147: mtpr pwfl_P2LR,$P2LR \
148: mtpr pwfl_IPL,$IPL \
149: mtpr pwfl_DCK,$DCK \
150: mtpr pwfl_CCK,$CCK \
151: mtpr pwfl_PCBB,$PCBB \
152: mtpr pwfl_ISP,$ISP \
153: mtpr pwfl_KSP,$KSP \
154: mtpr pwfl_USP,$USP \
155: \
156: bicpsw $0xff # Restore PSW. \
157: bispsw pwfl_PSL+2 # Set original bits back (just in case..) \
158: # now go to mapped mode \
159: # Have to change PC to system addresses \
160: mtpr $1,$PACC # Thoroughly clean up caches. \
161: mtpr $1,$PADC \
162: mtpr $1,$TBIA \
163: mtpr pwfl_MME,$MME # Restore MME. Last thing to be done. \
164: jmp loc
165:
166: /*
167: * Do a dump.
168: * Called by auto-restart.
169: * May be called manually.
170: */
171: .align 2
172: .text
173: .globl _Xdoadump
174: .globl _doadump
175: _Xdoadump: # CP comes here after power fail
176: RESTOREpwfl(*0f) # restore state
177: _doadump:
178: .word 0
179: 0: mtpr $HIGH,$IPL
180: #define _rsstkmap _Sysmap+12 # powerfail storage, scb, rsstk, int stack
181: tstl dumpflag # dump only once!
182: bneq 1f
183: andl2 $~PG_PROT,_rsstkmap
184: orl2 $PG_KW,_rsstkmap # Make dump stack r/w
185: mtpr $0,$TBIA
186: movl $1,dumpflag
187: movab dumpflag,sp
188: callf $4,_dumpsys
189: 1:
190: halt
191:
192: /*
193: * Interrupt vector routines
194: */
195: .globl _waittime
196: #define SCBVEC(name) \
197: .align 2; \
198: .globl _X/**/name; \
199: _X/**/name
200: #define PANIC(msg) \
201: clrl _waittime; pushab 1f; callf $8,_panic; 1: .asciz msg
202: #define PRINTF(n,msg) \
203: pushab 1f; callf $(n+2)*4,_printf; MSG(msg)
204: #define MSG(msg) .data; 1: .asciz msg; .text
205: /*
206: * r0-r5 are saved across all faults and interrupts.
207: * Routines below and those hidden in vbglue.s (device
208: * interrupts) invoke the PUSHR/POPR macros to execute
209: * this. Also, certain stack frame offset calculations
210: * use this, using the REGSPC definition (and FPSPC defined below).
211: */
212: #define REGSPC 6*4
213: #define PUSHR movab -REGSPC(sp),sp; storer $0x3f,(sp)
214: #define POPR loadr $0x3f,(sp); movab REGSPC(sp),sp
215:
216: /*
217: * Floating point state is saved across faults and
218: * interrupts. The state occupies 4 longwords on
219: * the stack:
220: * precision indicator (single = 0/double = 1)
221: * double representation of accumulator
222: * save accumulator status flag (pcb_savacc)
223: */
224: #define FPSPC (4*4)
225:
226: #define SAVE_FPSTAT(_delta) \
227: bitl $PSL_DBL,_delta(sp); \
228: beql 1f; \
229: pushl $1; \
230: pushd; \
231: jmp 2f; \
232: 1: pushl $0; \
233: pushl $0; \
234: stf -(sp); \
235: 2: tstl _u+PCB_SAVACC; \
236: bneq 3f; \
237: moval 0(sp),_u+PCB_SAVACC; \
238: orl2 $2,8(sp);\
239: 3: pushl $0;
240:
241: #define REST_FPSTAT \
242: tstl (sp)+; \
243: bitl $2,8(sp);\
244: beql 1f;\
245: movl $0,_u+PCB_SAVACC; \
246: 1: bitl $1,8(sp); \
247: beql 2f; \
248: ldd (sp); \
249: jmp 3f; \
250: 2: ldf (sp); \
251: 3: moval 12(sp),sp;
252:
253: #define REST_ACC \
254: tstl _u+PCB_SAVACC; \
255: beql 2f; \
256: movl _u+PCB_SAVACC,r1; \
257: andl3 $(EXPMASK|SIGNBIT),(r1),-(sp); \
258: cmpl $0x80000000,(sp)+; \
259: bneq 3f; \
260: clrl (r1); \
261: 3: bitl $1,8(r1); \
262: beql 1f; \
263: ldd (r1); \
264: jmp 2f; \
265: 1: ldf (r1); \
266: 2: ;
267:
268: .data
269: nofault: .space 4 # bus error non-local goto label
270:
271: .text
272: SCBVEC(buserr):
273: CHECK_SFE(12)
274: SAVE_FPSTAT(12)
275: incl _intrcnt+I_BUSERR # keep stats...
276: pushl r0 # must save
277: andl3 24(sp),$ERRCD,r0 # grab pushed MER value
278: cmpl r0,$APE # address parity error?
279: jneq 1f
280: halt
281: 1: cmpl r0,$VBE # versabus error?
282: jneq 2f
283: halt
284: 2:
285: movl (sp)+,r0 # restore r0 and...
286: bitl $PSL_CURMOD,4*4+3*4(sp) # check if happened in user mode?
287: jeql 3f # yes, then shift stack up for trap...
288: movl 12(sp),16(sp) # sorry, no space for which-buss...
289: movl 8(sp),12(sp)
290: movl 4(sp),8(sp)
291: movl 0(sp),4(sp)
292: movl $T_BUSERR,0(sp) # push trap type code and...
293: jbr alltraps # ...merge with all other traps
294: 3: # kernel mode, check to see if...
295: tstl nofault # ...doing peek/poke?
296: jeql 4f # nofault set? if so, jump to it...
297: movl nofault,4*4+2*4(sp) # ...setup for non-local goto
298: clrl nofault
299: jbr 5f
300: 4:
301: PUSHR
302: pushab 4*4+REGSPC(sp) # address of bus error parameters
303: callf $8,_buserror
304: POPR
305: 5:
306: REST_FPSTAT
307: movab 8(sp),sp # remove bus error parameters
308: rei
309:
310: SCBVEC(powfail): # We should be on interrupt stack now.
311: SAVEpwfl() # save machine state
312: moval _Xdoadump-SYSTEM,_scb+SCB_DOADUMP
313: halt
314:
315: SCBVEC(stray):
316: incl _cnt+V_INTR # add to statistics
317: rei
318:
319: #include "../net/netisr.h"
320: .globl _netisr
321: SCBVEC(netintr):
322: CHECK_SFE(4)
323: SAVE_FPSTAT(4); PUSHR
324: #include "imp.h"
325: #if NIMP > 0
326: bbc $NETISR_IMP,_netisr,1f;
327: andl2 $~(1<<NETISR_IMP),_netisr
328: callf $4,_impintr;
329: 1:
330: #endif
331: #ifdef INET
332: bbc $NETISR_IP,_netisr,1f
333: andl2 $~(1<<NETISR_IP),_netisr
334: callf $4,_ipintr
335: 1:
336: #endif
337: #ifdef NS
338: bbc $NETISR_NS,_netisr,1f
339: andl2 $~(1<<NETISR_NS),_netisr
340: callf $4,_nsintr
341: 1:
342: #endif
343: #ifdef ISO
344: bbc $NETISR_ISO,_netisr,1f
345: andl2 $~(1<<NETISR_ISO),_netisr
346: callf $4,_clnlintr
347: 1:
348: #endif
349: incl _cnt+V_SOFT
350: POPR; REST_FPSTAT
351: rei
352:
353: SCBVEC(cnrint):
354: CHECK_SFE(4)
355: SAVE_FPSTAT(4); PUSHR;
356: pushl $CPCONS; callf $8,_cnrint;
357: incl _intrcnt+I_CNR
358: incl _cnt+V_INTR
359: POPR; REST_FPSTAT;
360: rei
361: SCBVEC(cnxint):
362: CHECK_SFE(4)
363: SAVE_FPSTAT(4); PUSHR;
364: pushl $CPCONS; callf $8,_cnxint;
365: incl _intrcnt+I_CNX
366: incl _cnt+V_INTR
367: POPR; REST_FPSTAT;
368: rei
369: SCBVEC(rmtrint):
370: CHECK_SFE(4)
371: SAVE_FPSTAT(4); PUSHR;
372: pushl $CPREMOT; callf $8,_cnrint;
373: incl _intrcnt+I_RMTR
374: incl _cnt+V_INTR
375: POPR; REST_FPSTAT;
376: rei
377: SCBVEC(rmtxint):
378: CHECK_SFE(4)
379: SAVE_FPSTAT(4); PUSHR;
380: pushl $CPREMOT; callf $8,_cnxint;
381: incl _intrcnt+I_RMTX
382: incl _cnt+V_INTR
383: POPR; REST_FPSTAT;
384: rei
385:
386: #define PUSHPCPSL pushl 4+FPSPC+REGSPC(sp); pushl 4+FPSPC+REGSPC(sp);
387:
388: SCBVEC(hardclock):
389: tstl _clk_enable
390: bneq 1f
391: rei
392: 1:
393: CHECK_SFE(4)
394: SAVE_FPSTAT(4); PUSHR
395: PUSHPCPSL # push pc and psl
396: callf $12,_hardclock # hardclock(pc,psl)
397: incl _intrcnt+I_CLOCK
398: incl _cnt+V_INTR ## temp so not to break vmstat -= HZ
399: POPR; REST_FPSTAT
400: rei
401: SCBVEC(softclock):
402: CHECK_SFE(4)
403: SAVE_FPSTAT(4); PUSHR;
404: PUSHPCPSL # push pc and psl
405: callf $12,_softclock # softclock(pc,psl)
406: incl _cnt+V_SOFT
407: POPR; REST_FPSTAT
408: rei
409:
410: /*
411: * Stray VERSAbus interrupt catch routines
412: */
413: .data
414: #define PJ .align 2; callf $4,_Xvstray
415: .globl _catcher
416: _catcher:
417: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
418: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
419: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
420: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
421: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
422: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
423: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
424: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
425: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
426: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
427: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
428: PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
429:
430: .align 2
431: .globl _cold
432: _cold: .long 0x3
433:
434: .text
435: SCBVEC(vstray):
436: .word 0
437: bbc $0,_cold,2f # system running?
438: bbc $1,_cold,1f # doing autoconfig?
439: jbr 3f # random interrupt, ignore
440: 1:
441: mfpr $IPL,r12 # ...setup br and cvec
442: subl3 $_catcher+7,-8(fp),r11; shar $3,r11,r11
443: addl2 $SCB_DEVBASE,r11
444: jbr 3f
445: 2:
446: PUSHR
447: subl3 $_catcher+7,-8(fp),r0; shar $3,r0,r0
448: addl3 $SCB_DEVBASE,r0,-(sp);
449: mfpr $IPL,-(sp)
450: PRINTF(2, "stray intr ipl %x vec %x\n")
451: POPR
452: 3: moval 0f,-8(fp); ret # pop callf frame...
453: 0: rei # ...and return
454:
455: /*
456: * Trap and fault vector routines
457: */
458: #define TRAP(a) pushl $T_/**/a; jbr alltraps
459:
460: /*
461: * Ast delivery (profiling and/or reschedule)
462: */
463:
464: SCBVEC(kspnotval):
465: CHECK_SFE(4)
466: pushl $0;
467: SAVE_FPSTAT(8)
468: TRAP(KSPNOTVAL)
469: SCBVEC(privinflt):
470: CHECK_SFE(4)
471: pushl $0;
472: SAVE_FPSTAT(8)
473: TRAP(PRIVINFLT)
474: SCBVEC(resopflt):
475: CHECK_SFE(4)
476: pushl $0;
477: SAVE_FPSTAT(8)
478: TRAP(RESOPFLT)
479: SCBVEC(resadflt):
480: CHECK_SFE(4)
481: pushl $0;
482: SAVE_FPSTAT(8)
483: TRAP(RESADFLT)
484: SCBVEC(bptflt):
485: CHECK_SFE(4)
486: pushl $0;
487: SAVE_FPSTAT(8)
488: TRAP(BPTFLT)
489: SCBVEC(kdbintr):
490: CHECK_SFE(4);
491: pushl $0;
492: SAVE_FPSTAT(8);
493: TRAP(KDBTRAP);
494: SCBVEC(tracep):
495: CHECK_SFE(4)
496: pushl $0;
497: SAVE_FPSTAT(8)
498: TRAP(TRCTRAP)
499: SCBVEC(alignflt):
500: #ifdef ALIGN
501: bitl $PSL_CURMOD,4(sp)
502: jeql align_excp # Can't emulate for kernel mode !
503: jbr non_aligned # Only emulated for user mode.
504: align_excp:
505: #else
506: CHECK_SFE(4)
507: #endif
508: pushl $0;
509: SAVE_FPSTAT(8)
510: TRAP(ALIGNFLT)
511: SCBVEC(arithtrap):
512: CHECK_SFE(8)
513: SAVE_FPSTAT(8)
514: TRAP(ARITHTRAP)
515:
516: SCBVEC(protflt):
517: CHECK_SFE(12)
518: bitl $1,(sp)+
519: jneq segflt
520: SAVE_FPSTAT(8)
521: TRAP(PROTFLT)
522: segflt:
523: SAVE_FPSTAT(8)
524: TRAP(SEGFLT)
525:
526: SCBVEC(fpm): # Floating Point Emulation
527: #ifdef FPE
528: CHECK_SFE(16)
529: SAVE_FPSTAT(16)
530: incl _cnt+V_FPE # count emulation traps
531: callf $4,_fpemulate
532: REST_FPSTAT
533: #endif
534: moval 8(sp),sp # Pop operand
535: tstl (sp) # Stack= PSL, PC, return_code
536: jneq _Xarithtrap # If not OK, emulate F.P. exception
537: movab 4(sp),sp # Else remove return_code and
538: rei
539:
540: SCBVEC(sfexcep):
541: CHECK_SFE(4)
542: pushl $0
543: SAVE_FPSTAT(8)
544: TRAP(ASTFLT)
545:
546: SCBVEC(transflt):
547: CHECK_SFE(12)
548: bitl $2,(sp)+
549: bneq tableflt
550: pageflt:
551: SAVE_FPSTAT(8)
552: TRAP(PAGEFLT)
553: tableflt:
554: SAVE_FPSTAT(8)
555: TRAP(TABLEFLT)
556:
557: #define REST_STACK movab 4(sp), sp; REST_FPSTAT; movab 4(sp), sp
558:
559: alltraps:
560: mfpr $USP,-(sp);
561: callf $4,_trap;
562: mtpr (sp)+,$USP
563: incl _cnt+V_TRAP
564: REST_STACK # pop type, code, and fp stuff
565: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
566: rei
567:
568: SCBVEC(syscall):
569: CHECK_SFE(8)
570: SAVE_FPSTAT(8)
571: pushl $T_SYSCALL
572: mfpr $USP,-(sp);
573: callf $4,_syscall;
574: mtpr (sp)+,$USP
575: incl _cnt+V_SYSCALL
576: REST_STACK # pop type, code, and fp stuff
577: mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
578: rei
579:
580: /*
581: * System page table.
582: *
583: * Mbmap and Usrptmap are enlarged by CLSIZE entries
584: * as they are managed by resource maps starting with index 1 or CLSIZE.
585: */
586: #define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+SYSTEM)
587: #define SYSMAP(mname, vname, npte) \
588: _/**/mname: .globl _/**/mname; \
589: .space (npte)*4; \
590: .globl _/**/vname; \
591: .set _/**/vname,vaddr(_/**/mname)
592: #define ADDMAP(npte) .space (npte)*4
593:
594: .data
595: .align 2
596: SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE )
597: SYSMAP(Forkmap ,forkutl ,UPAGES )
598: SYSMAP(Xswapmap ,xswaputl ,UPAGES )
599: SYSMAP(Xswap2map,xswap2utl ,UPAGES )
600: SYSMAP(Swapmap ,swaputl ,UPAGES )
601: SYSMAP(Pushmap ,pushutl ,UPAGES )
602: SYSMAP(Vfmap ,vfutl ,UPAGES )
603: SYSMAP(CMAP1 ,CADDR1 ,1 )
604: SYSMAP(CMAP2 ,CADDR2 ,1 )
605: SYSMAP(mmap ,vmmap ,1 )
606: SYSMAP(alignmap ,alignutl ,1 ) /* XXX */
607: SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT )
608: SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE )
609: #ifdef MFS
610: #include "../ufs/mfsiom.h"
611: /*
612: * Used by the mfs_doio() routine for physical I/O
613: */
614: SYSMAP(Mfsiomap ,mfsiobuf ,MFS_MAPREG )
615: #endif /* MFS */
616: #ifdef NFS
617: #include "../nfs/nfsiom.h"
618: /*
619: * Used by the nfs_doio() routine for physical I/O
620: */
621: SYSMAP(Nfsiomap ,nfsiobuf ,NFS_MAPREG )
622: #endif /* NFS */
623: /*
624: * This is the map used by the kernel memory allocator.
625: * It is expanded as necessary by the special features
626: * that use it.
627: */
628: SYSMAP(kmempt ,kmembase ,NKMEMCLUSTERS*CLSIZE )
629: #ifdef SYSVSHM
630: ADDMAP( SHMMAXPGS )
631: #endif
632: #ifdef GPROF
633: ADDMAP( 600*CLSIZE )
634: #endif
635: /*
636: * Enlarge kmempt as needed for bounce buffers allocated
637: * by tahoe controllers.
638: */
639: #include "hd.h"
640: #if NHD > 0
641: ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) )
642: #endif
643: #include "dk.h"
644: #if NDK > 0
645: ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) )
646: #endif
647: #include "yc.h"
648: #if NYC > 0
649: ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) )
650: #endif
651: #include "mp.h"
652: ADDMAP( NMP*14 )
653: SYSMAP(ekmempt ,kmemlimit ,0 )
654:
655: SYSMAP(VMEMbeg ,vmembeg ,0 )
656: SYSMAP(VMEMmap ,vmem ,VBIOSIZE )
657: SYSMAP(VMEMmap1 ,vmem1 ,0 )
658: #include "ace.h"
659: #if NACE > 0
660: ADDMAP( NACE*32 )
661: #endif
662: #if NHD > 0
663: ADDMAP( NHDC )
664: #endif
665: #include "vx.h"
666: #if NVX > 0
667: ADDMAP( NVX * 16384/NBPG )
668: #endif
669: SYSMAP(VMEMend ,vmemend ,0 )
670:
671: SYSMAP(VBmap ,vbbase ,CLSIZE )
672: #if NHD > 0
673: ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) )
674: #endif
675: #if NDK > 0
676: ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) )
677: #endif
678: #if NYC > 0
679: ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) )
680: #endif
681: ADDMAP( NMP*14 )
682: SYSMAP(eVBmap ,vbend ,0 )
683:
684: SYSMAP(Usrptmap ,usrpt ,USRPTSIZE+CLSIZE )
685: eSysmap:
686: .globl _Syssize
687: .set _Syssize,(eSysmap-_Sysmap)/4
688:
689: .text
690: /*
691: * Initialization
692: *
693: * IPL 0x1f; MME 0; scbb, pcbb, sbr, slr, isp, ksp not set
694: */
695: .align 2
696: .globl start
697: start:
698: .word 0
699: /* set system control block base and system page table params */
700: mtpr $_scb-SYSTEM,$SCBB
701: mtpr $_Sysmap-SYSTEM,$SBR
702: mtpr $_Syssize,$SLR
703: /* double map the kernel into the virtual user addresses of phys mem */
704: mtpr $_Sysmap,$P0BR
705: mtpr $_Syssize,$P0LR
706: mtpr $_Sysmap,$P1BR # against Murphy
707: mtpr $_Syssize,$P1LR
708: /* set ISP */
709: movl $_intstack-SYSTEM+NISP*NBPG,sp # still physical
710: mtpr $_intstack+NISP*NBPG,$ISP
711: /* count up memory; _physmem contains limit */
712: clrl r7
713: shll $PGSHIFT,_physmem,r8
714: decl r8
715: 1: pushl $1; pushl r7; callf $12,_badaddr; tstl r0; bneq 9f
716: ACBL(r8,$64*1024,r7,1b)
717: 9:
718: /* clear memory from kernel bss and pages for proc 0 u. and page table */
719: movab _edata,r6; andl2 $~SYSTEM,r6
720: movab _end,r5; andl2 $~SYSTEM,r5
721: #ifdef KADB
722: subl2 $4,r5
723: 1: clrl (r6); ACBL(r5,$4,r6,1b) # clear just bss
724: addl2 $4,r5
725: bbc $6,r11,0f # check RB_KDB
726: andl3 $~SYSTEM,r9,r5 # skip symbol & string tables
727: andl3 $~SYSTEM,r9,r6
728: #endif
729: 0: orl3 $SYSTEM,r5,r9 # convert to virtual address
730: addl2 $NBPG-1,r9 # roundup to next page
731: addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5
732: 1: clrl (r6); ACBL(r5,$4,r6,1b)
733: /* trap(), syscall(), and fpemulate() save r0-r12 in the entry mask */
734: orw2 $0x01fff,_trap
735: orw2 $0x01fff,_syscall
736: #ifdef FPE
737: orw2 $0x01fff,_fpemulate
738: #endif
739: orw2 $0x01ffc,_panic # for debugging (no r0|r1)
740: callf $4,_fixctlrmask # setup for autoconfig
741: /* initialize system page table: scb and int stack writeable */
742: clrl r2
743: movab eintstack,r1
744: andl2 $~SYSTEM,r1
745: shrl $PGSHIFT,r1,r1 # r1-page number of eintstack
746: /* make 1st page processor storage read/only, 2nd read/write */
747: orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2;
748: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; incl r2;
749: /* other parts of the system are read/write for kernel */
750: 1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; # data:kernel write+phys=virtual
751: aoblss r1,r2,1b
752: /* make rsstk read-only as red zone for interrupt stack */
753: andl2 $~PG_PROT,_rsstkmap
754: orl2 $PG_V|PG_KR,_rsstkmap
755: /* make kernel text space read-only */
756: movab _etext+NBPG-1,r1
757: andl2 $~SYSTEM,r1
758: shrl $PGSHIFT,r1,r1
759: 1: orl3 $PG_V|PG_KR,r2,_Sysmap[r2]
760: aoblss r1,r2,1b
761: /* make kernel data, bss, read-write */
762: andl3 $~SYSTEM,r9,r1
763: shrl $PGSHIFT,r1,r1
764: 1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]
765: aoblss r1,r2,1b
766: /* go to mapped mode, have to change both pc and sp to system addresses */
767: mtpr $1,$TBIA
768: mtpr $1,$PADC # needed by HW parity&ECC logic
769: mtpr $1,$PACC # just in case
770: mtpr $1,$MME
771: movab SYSTEM(sp),sp
772: jmp *$0f
773: 0:
774: /* disable any interrupts */
775: movl $0,_intenable
776: /* init mem sizes */
777: shrl $PGSHIFT,r7,_physmem
778: /* setup context for proc[0] == scheduler */
779: andl3 $~SYSTEM,r9,r6 # convert to physical
780: andl2 $~(NBPG-1),r6 # make page boundary
781: /* setup page table for proc[0] */
782: shrl $PGSHIFT,r6,r3 # r3 = btoc(r6)
783: orl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry
784: incl r3 # r3 - next page
785: movab _usrpt,r0 # r0 - first user page
786: mtpr r0,$TBIS
787: /* init p0br, p0lr */
788: mtpr r0,$P0BR # no p0 for proc[0]
789: mtpr $0,$P0LR
790: mtpr r0,$P1BR # no p1 either
791: mtpr $0,$P1LR
792: /* init p2br, p2lr */
793: movab NBPG(r0),r0
794: movl $PPAGES-UPAGES,r1
795: mtpr r1,$P2LR
796: moval -4*PPAGES(r0),r2
797: mtpr r2,$P2BR
798: /* setup mapping for UPAGES of _u */
799: clrl r2
800: movl $SYSTEM,r1
801: addl2 $UPAGES,r3
802: jbr 2f
803: 1: decl r3
804: moval -NBPG(r1),r1 # r1 = virtual add of next (downward) _u page
805: subl2 $4,r0 # r0 = pte address
806: orl3 $PG_V|PG_URKW,r3,(r0)
807: mtpr r1,$TBIS
808: 2: aobleq $UPAGES,r2,1b
809: /* initialize (slightly) the pcb */
810: movab UPAGES*NBPG(r1),PCB_KSP(r1) # KSP starts at end of _u
811: movl r1,PCB_USP(r1) # USP starts just below _u
812: mfpr $P0BR,PCB_P0BR(r1)
813: mfpr $P0LR,PCB_P0LR(r1)
814: mfpr $P1BR,PCB_P1BR(r1)
815: mfpr $P1LR,PCB_P1LR(r1)
816: mfpr $P2BR,PCB_P2BR(r1)
817: mfpr $P2LR,PCB_P2LR(r1)
818: movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt
819: movl r9,PCB_R9(r1) # r9 obtained from boot
820: movl r10,PCB_R10(r1) # r10 obtained from boot
821: movl r11,PCB_R11(r1) # r11 obtained from CP on boot
822: movab 1f,PCB_PC(r1) # initial pc
823: clrl PCB_PSL(r1) # kernel mode, ipl=0
824: shll $PGSHIFT,r3,r3
825: mtpr r3,$PCBB # first pcbb (physical)
826: /* go to kernel mode */
827: ldpctx
828: rei # Actually next instruction:
829: /* put signal trampoline code in u. area */
830: 1: movab sigcode,r0
831: movab _u+PCB_SIGC,r1
832: movl $19,r2
833: movblk
834: /* save boot device in global _bootdev */
835: movl r10,_bootdev
836: /* save reboot flags in global _boothowto */
837: movl r11,_boothowto
838: #ifdef KADB
839: /* save end of symbol & string table in global _bootesym */
840: subl3 $NBPG-1,r9,_bootesym
841: #endif
842: /* calculate firstaddr, and call main() */
843: andl3 $~SYSTEM,r9,r0
844: shrl $PGSHIFT,r0,-(sp)
845: addl2 $UPAGES+1,(sp) # first physical unused page
846: callf $8,_main
847: /* proc[1] == /etc/init now running here in kernel mode; run icode */
848: pushl $PSL_CURMOD # User mode PSL
849: pushl $0 # PC = 0 (virtual now)
850: rei
851:
852: /*
853: * Mask for saving/restoring registers on entry to
854: * a user signal handler. Space for the registers
855: * is reserved in sendsig, so beware if you want
856: * to change the mask.
857: */
858: #define SIGREGS (R0|R1|R2|R3|R4|R5)
859: .align 2
860: .globl sigcode
861: sigcode:
862: storer $SIGREGS,16(sp) # save volatile registers
863: calls $4*3+4,*12(sp) # params pushed by sendsig for handler
864: loadr $SIGREGS,4(sp) # restore volatile registers
865: movab 24(sp),fp # use parameter list set up in sendsig
866: kcall $SYS_sigreturn # cleanup mask and onsigstack
867: halt # sigreturn does not return!
868:
869: .globl _icode
870: .globl _initflags
871: .globl _szicode
872: /*
873: * Icode is copied out to process 1 to exec /etc/init.
874: * If the exec fails, process 1 exits.
875: */
876: .align 2
877: _icode:
878: /* try /sbin/init */
879: pushab b`argv1-l0(pc)
880: l0: pushab b`init1-l1(pc)
881: l1: pushl $2
882: movab (sp),fp
883: kcall $SYS_execv
884: /* try /etc/init */
885: pushab b`argv2-l2(pc)
886: l2: pushab b`init2-l3(pc)
887: l3: pushl $2
888: movab (sp),fp
889: kcall $SYS_execv
890: /* give up */
891: pushl r0
892: pushl $1
893: movab (sp),fp
894: kcall $SYS_exit
895:
896: init1: .asciz "/sbin/init"
897: init2: .asciz "/etc/init"
898: .align 2
899: _initflags:
900: .long 0
901: argv1: .long init1+6-_icode
902: .long _initflags-_icode
903: .long 0
904: argv2: .long init2+5-_icode
905: .long _initflags-_icode
906: .long 0
907: _szicode:
908: .long _szicode-_icode
909:
910: /*
911: * Primitives
912: */
913:
914: /*
915: * badaddr(addr, len)
916: * see if access addr with a len type instruction causes a machine check
917: * len is length of access (1=byte, 2=short, 4=long)
918: * r0 = 0 means good(exists); r0 =1 means does not exist.
919: */
920: ENTRY(badaddr, R3|R4)
921: mfpr $IPL,r1
922: mtpr $HIGH,$IPL
923: movl _scb+SCB_BUSERR,r2
924: movl 4(fp),r3
925: movl 8(fp),r4
926: movab 9f,_scb+SCB_BUSERR
927: bbc $0,r4,1f; tstb (r3)
928: 1: bbc $1,r4,1f; tstw (r3)
929: 1: bbc $2,r4,1f; tstl (r3)
930: 1: clrl r0
931: 2: movl r2,_scb+SCB_BUSERR
932: mtpr r1,$IPL
933: ret
934:
935: /*
936: * wbadaddr(addr, len, value)
937: * see if write of value to addr with a len type instruction causes
938: * a machine check
939: * len is length of access (1=byte, 2=short, 4=long)
940: * r0 = 0 means good(exists); r0 =1 means does not exist.
941: */
942: ENTRY(wbadaddr, R3|R4)
943: mfpr $IPL,r1
944: mtpr $HIGH,$IPL
945: movl _scb+SCB_BUSERR,r2
946: movl 4(fp),r3
947: movl 8(fp),r4
948: movab 9f,_scb+SCB_BUSERR
949: bbc $0,r4,1f; movb 15(fp), (r3)
950: 1: bbc $1,r4,1f; movw 14(fp), (r3)
951: 1: bbc $2,r4,1f; movl 12(fp), (r3)
952: 1: movl $30000,r0 # delay for error interrupt
953: 1: decl r0
954: jneq 1b
955: 2: movl r2,_scb+SCB_BUSERR # made it w/o machine checks; r0 is 0
956: mtpr r1,$IPL
957: ret
958:
959: .align 2
960: 9: # catch buss error (if it comes)
961: andl3 4(sp),$ERRCD,r0
962: cmpl r0,$APE
963: jneq 1f
964: halt # address parity error
965: 1: cmpl r0,$VBE
966: jneq 1f
967: halt # Versabus error
968: 1:
969: movl $1,r0 # Anything else = bad address
970: movab 8(sp),sp # discard buss error trash
971: movab 2b,(sp) # new program counter on stack.
972: rei
973:
974: /*
975: * badcyaddr(addr)
976: * see if access tape master controller addr causes a bus error
977: * r0 = 0: no error; r0 = 1: timeout error.
978: */
979: ENTRY(badcyaddr, 0)
980: mfpr $IPL,r1
981: mtpr $HIGH,$IPL
982: clrl r2
983: movab 2f,nofault
984: movob $-1, *4(fp)
985: 1: aobleq $1000, r2, 1b
986: clrl nofault # made it w/o bus error
987: clrl r0
988: jbr 3f
989: 2: movl $1,r0
990: 3: mtpr r1,$IPL
991: ret
992:
993: /*
994: * peek(addr)
995: * fetch word and catch any bus error
996: */
997: ENTRY(peek, 0)
998: mfpr $IPL,r1
999: mtpr $0x18,$IPL # not reentrant
1000: movl 4(fp),r2
1001: movab 1f,nofault
1002: movw (r2),r0
1003: clrl nofault
1004: andl2 $0xffff,r0
1005: jbr 2f
1006: 1: movl $-1,r0 # bus error
1007: 2: mtpr r1,$IPL
1008: ret
1009:
1010: /*
1011: * poke(addr, val)
1012: * write word and catch any bus error
1013: */
1014: ENTRY(poke, R3)
1015: mfpr $IPL,r1
1016: mtpr $0x18,$IPL # not reentrant
1017: movl 4(fp),r2
1018: movl 8(fp),r3
1019: clrl r0
1020: movab 1f,nofault
1021: movw r3,(r2)
1022: clrl nofault
1023: jbr 2f
1024: 1: movl $-1,r0 # bus error
1025: 2: mtpr r1,$IPL
1026: ret
1027:
1028: /*
1029: * Copy a potentially overlapping block of memory.
1030: *
1031: * ovbcopy(src, dst, count)
1032: * caddr_t src, dst; unsigned count;
1033: */
1034: ENTRY(ovbcopy, R3|R4)
1035: movl 4(fp),r0
1036: movl 8(fp),r1
1037: movl 12(fp),r2
1038: cmpl r0,r1
1039: bgtru 1f # normal forward case
1040: beql 2f # equal, nothing to do
1041: addl2 r2,r0 # may be overlapping
1042: cmpl r0,r1
1043: bgtru 3f
1044: subl2 r2,r0 # normal forward case
1045: 1:
1046: movblk
1047: 2:
1048: ret
1049: 3:
1050: addl2 r2,r1 # overlapping, must do backwards
1051: subl3 r0,r1,r3
1052: movl r2,r4
1053: jbr 5f
1054: 4:
1055: subl2 r3,r0
1056: subl2 r3,r1
1057: movl r3,r2
1058: movblk
1059: subl2 r3,r0
1060: subl2 r3,r1
1061: subl2 r3,r4
1062: 5:
1063: cmpl r4,r3
1064: jgtr 4b
1065: movl r4,r2
1066: subl2 r2,r0
1067: subl2 r2,r1
1068: movblk
1069: ret
1070:
1071: /*
1072: * Copy a null terminated string from the user address space into
1073: * the kernel address space.
1074: *
1075: * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
1076: */
1077: ENTRY(copyinstr, 0)
1078: movl 12(fp),r5 # r5 = max length
1079: jlss 5f
1080: movl 8(fp),r4 # r4 = kernel address
1081: movl 4(fp),r0 # r0 = user address
1082: andl3 $(NBPG*CLSIZE-1),r0,r2 # r2 = bytes on first page
1083: subl3 r2,$(NBPG*CLSIZE),r2
1084: 1:
1085: cmpl r5,r2 # r2 = min(bytes on page, length left);
1086: jgeq 2f
1087: movl r5,r2
1088: 2:
1089: prober $1,(r0),r2 # bytes accessible?
1090: jeql 5f
1091: subl2 r2,r5 # update bytes left count
1092: movl r2,r3 # r3 = saved count
1093: movl r0,r1
1094: cmps3 # check for null
1095: tstl r2
1096: jneq 3f
1097: subl2 r3,r0 # back up r0
1098: movl r4,r1
1099: movl r3,r2
1100: movblk # copy in next piece
1101: movl r1,r4
1102: movl $(NBPG*CLSIZE),r2 # check next page
1103: tstl r5 # run out of space?
1104: jneq 1b
1105: movl $ENOENT,r0 # set error code and return
1106: jbr 6f
1107: 3:
1108: tstl 16(fp) # return length?
1109: beql 4f
1110: subl3 r5,12(fp),r5 # actual len = maxlen - unused pages
1111: subl2 r2,r5 # - unused on this page
1112: addl3 $1,r5,*16(fp) # + the null byte
1113: 4:
1114: movl r4,r1
1115: subl3 r2,r3,r2 # calc char cnt
1116: subl2 r2,r0 # back up r0
1117: incl r2 # add on null byte
1118: movblk # copy last piece
1119: clrl r0
1120: ret
1121: 5:
1122: movl $EFAULT,r0
1123: 6:
1124: tstl 16(fp)
1125: beql 7f
1126: subl3 r5,12(fp),*16(fp)
1127: 7:
1128: ret
1129:
1130: /*
1131: * Copy a null terminated string from the kernel
1132: * address space to the user address space.
1133: *
1134: * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
1135: */
1136: ENTRY(copyoutstr, 0)
1137: movl 12(fp),r5 # r5 = max length
1138: jlss 5f
1139: movl 4(fp),r0 # r0 = kernel address
1140: movl 8(fp),r4 # r4 = user address
1141: andl3 $(NBPG*CLSIZE-1),r4,r2 # r2 = bytes on first page
1142: subl3 r2,$(NBPG*CLSIZE),r2
1143: 1:
1144: cmpl r5,r2 # r2 = min(bytes on page, length left);
1145: jgeq 2f
1146: movl r5,r2
1147: 2:
1148: probew $1,(r4),r2 # bytes accessible?
1149: jeql 5f
1150: subl2 r2,r5 # update bytes left count
1151: movl r2,r3 # r3 = saved count
1152: movl r0,r1
1153: /*
1154: * This is a workaround for a microcode bug that causes
1155: * a trap type 9 when cmps3/movs3 touches the last byte
1156: * on a valid page immediately followed by an invalid page.
1157: */
1158: #ifdef good_cmps3
1159: cmps3 # check for null
1160: tstl r2
1161: jneq 3b
1162: #else
1163: decl r2
1164: beql 9f # cannot handle case of r2 == 0!
1165: cmps3 # check for null up to last byte
1166: 9:
1167: incl r2
1168: cmpl $1,r2 # get to last byte on page?
1169: bneq 3b
1170: tstb (r0) # last byte on page null?
1171: beql 3b
1172: incl r0 # not null, so bump pointer
1173: #endif not good_cmps3
1174: subl2 r3,r0 # back up r0
1175: movl r4,r1
1176: movl r3,r2
1177: movblk # copy out next piece
1178: movl r1,r4
1179: movl $(NBPG*CLSIZE),r2 # check next page
1180: tstl r5 # run out of space?
1181: jneq 1b
1182: movl $ENOENT,r0 # set error code and return
1183: jbr 6b
1184: 5:
1185: clrl *$0 # this should never execute, if it does
1186: movl $EFAULT,r0 # save me a core dump (mkm - 9/87)
1187: 6:
1188: tstl 16(fp)
1189: beql 7f
1190: subl3 r5,12(fp),*16(fp)
1191: 7:
1192: ret
1193:
1194:
1195: /*
1196: * Copy a null terminated string from one point to another in
1197: * the kernel address space.
1198: *
1199: * copystr(fromaddr, toaddr, maxlength, &lencopied)
1200: */
1201: ENTRY(copystr, 0)
1202: movl 12(fp),r3 # r3 = max length
1203: jlss 5b
1204: movl 4(fp),r0 # r0 = src address
1205: movl 8(fp),r4 # r4 = dest address
1206: clrl r5 # r5 = bytes left
1207: movl r3,r2 # r2 = max bytes to copy
1208: movl r0,r1
1209: cmps3 # check for null
1210: tstl r2
1211: jneq 3b
1212: subl2 r3,r0 # back up r0
1213: movl r4,r1
1214: movl r3,r2
1215: movblk # copy next piece
1216: movl $ENOENT,r0 # set error code and return
1217: jbr 6b
1218:
1219: /*
1220: * Copy a block of data from the user address space into
1221: * the kernel address space.
1222: *
1223: * copyin(fromaddr, toaddr, count)
1224: */
1225: ENTRY(copyin, 0)
1226: movl 12(fp),r0 # copy length
1227: blss 9f
1228: movl 4(fp),r1 # copy user address
1229: cmpl $(CLSIZE*NBPG),r0 # probing one page or less ?
1230: bgeq 2f # yes
1231: 1:
1232: prober $1,(r1),$(CLSIZE*NBPG) # bytes accessible ?
1233: beql 9f # no
1234: addl2 $(CLSIZE*NBPG),r1 # incr user address ptr
1235: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop
1236: 2:
1237: prober $1,(r1),r0 # bytes accessible ?
1238: beql 9f # no
1239: MOVC3(4(fp),8(fp),12(fp))
1240: clrl r0
1241: ret
1242: 9:
1243: movl $EFAULT,r0
1244: ret
1245:
1246: /*
1247: * Copy a block of data from the kernel
1248: * address space to the user address space.
1249: *
1250: * copyout(fromaddr, toaddr, count)
1251: */
1252: ENTRY(copyout, 0)
1253: movl 12(fp),r0 # get count
1254: blss 9b
1255: movl 8(fp),r1 # get user address
1256: cmpl $(CLSIZE*NBPG),r0 # can do in one probew?
1257: bgeq 2f # yes
1258: 1:
1259: probew $1,(r1),$(CLSIZE*NBPG) # bytes accessible?
1260: beql 9b # no
1261: addl2 $(CLSIZE*NBPG),r1 # increment user address
1262: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop
1263: 2:
1264: probew $1,(r1),r0 # bytes accessible?
1265: beql 9b # no
1266: MOVC3(4(fp),8(fp),12(fp))
1267: clrl r0
1268: ret
1269:
1270: /*
1271: * savectx is like setjmp but saves all registers.
1272: * Called before swapping out the u. area, restored by resume()
1273: * below.
1274: */
1275: ENTRY(savectx, 0)
1276: movl 4(fp),r2
1277: storer $0x1ff8,(r2); addl2 $40,r2 # r3-r12
1278: movl (fp),(r2); addl2 $4,r2 # fp
1279: movab 8(fp),(r2); addl2 $4,r2 # sp
1280: movl -8(fp),(r2) # pc
1281: clrl r0
1282: ret
1283:
1284: #ifdef KADB
1285: /*
1286: * C library -- reset, setexit -- XXX
1287: *
1288: * reset(x)
1289: * will generate a "return" from
1290: * the last call to
1291: * setexit()
1292: * by restoring r2 - r12, fp
1293: * and doing a return.
1294: * The returned value is x; on the original
1295: * call the returned value is 0.
1296: */
1297: ENTRY(setexit, 0)
1298: movab setsav,r0
1299: storer $0x1ffc, (r0)
1300: movl (fp),44(r0) # fp
1301: moval 4(fp),48(r0) # sp
1302: movl -8(fp),52(r0) # pc
1303: clrl r0
1304: ret
1305:
1306: ENTRY(reset, 0)
1307: movl 4(fp),r0 # returned value
1308: movab setsav,r1
1309: loadr $0x1ffc,(r1)
1310: movl 44(r1),fp
1311: movl 48(r1),sp
1312: jmp *52(r1)
1313:
1314: .data
1315: .align 2
1316: setsav: .space 14*4
1317: .text
1318: #endif
1319:
1320: .globl _whichqs
1321: .globl _qs
1322: .globl _cnt
1323:
1324: .globl _noproc
1325: .comm _noproc,4
1326: .globl _runrun
1327: .comm _runrun,4
1328: /*
1329: * The following primitives use the fancy TAHOE instructions.
1330: * _whichqs tells which of the 32 queues _qs
1331: * have processes in them. setrq puts processes into queues, remrq
1332: * removes them from queues. The running process is on no queue,
1333: * other processes are on a queue related to p->p_pri, divided by 4
1334: * actually to shrink the 0-127 range of priorities into the 32 available
1335: * queues.
1336: */
1337:
1338: /*
1339: * setrq(p), using fancy TAHOE instructions.
1340: *
1341: * Call should be made at spl8(), and p->p_stat should be SRUN
1342: */
1343: ENTRY(setrq, 0)
1344: movl 4(fp),r0
1345: tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0
1346: beql set1 ##
1347: pushab set3 ##
1348: callf $8,_panic ##
1349: set1:
1350: movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4
1351: shar $2,r1,r1
1352: shal $1,r1,r2
1353: moval _qs[r2],r2
1354: insque (r0),*4(r2) # at end of queue
1355: shal r1,$1,r1
1356: orl2 r1,_whichqs # mark queue non-empty
1357: ret
1358:
1359: set3: .asciz "setrq"
1360:
1361: /*
1362: * remrq(p), using fancy TAHOE instructions
1363: *
1364: * Call should be made at spl8().
1365: */
1366: ENTRY(remrq, 0)
1367: movl 4(fp),r0
1368: movzbl P_PRI(r0),r1
1369: shar $2,r1,r1
1370: bbs r1,_whichqs,rem1
1371: pushab rem3 # it wasn't recorded to be on its q
1372: callf $8,_panic
1373: rem1:
1374: remque (r0)
1375: bneq rem2 # q not empty yet
1376: shal r1,$1,r1
1377: mcoml r1,r1
1378: andl2 r1,_whichqs # mark queue empty
1379: rem2:
1380: clrl P_RLINK(r0) ## for firewall checking
1381: ret
1382:
1383: rem3: .asciz "remrq"
1384:
1385: /*
1386: * Masterpaddr is the p->p_addr of the running process on the master
1387: * processor. When a multiprocessor system, the slave processors will have
1388: * an array of slavepaddr's.
1389: */
1390: .globl _masterpaddr
1391: .data
1392: .align 2
1393: _masterpaddr: .long 0
1394:
1395: .text
1396: sw0: .asciz "swtch"
1397:
1398: /*
1399: * When no processes are on the runq, swtch branches to idle
1400: * to wait for something to come ready.
1401: */
1402: .globl Idle
1403: Idle: idle:
1404: movl $1,_noproc
1405: mtpr $0,$IPL # must allow interrupts here
1406: 1:
1407: tstl _whichqs # look for non-empty queue
1408: bneq sw1
1409: brb 1b
1410:
1411: badsw: pushab sw0
1412: callf $8,_panic
1413: /* NOTREACHED */
1414:
1415: .align 2
1416: /*
1417: * swtch(), using fancy tahoe instructions
1418: */
1419: ENTRY(swtch, 0)
1420: movl (fp),fp # prepare for rei
1421: movl (sp),4(sp) # saved pc
1422: tstl (sp)+
1423: movpsl 4(sp)
1424: incl _cnt+V_SWTCH
1425: sw1: ffs _whichqs,r0 # look for non-empty queue
1426: blss idle # if none, idle
1427: mtpr $0x18,$IPL # lock out all so _whichqs==_qs
1428: bbc r0,_whichqs,sw1 # proc moved via interrupt
1429: shal $1,r0,r1
1430: moval _qs[r1],r1
1431: movl (r1),r2 # r2 = p = highest pri process
1432: remque *(r1)
1433: bvs badsw # make sure something was there
1434: bneq sw2
1435: shal r0,$1,r1
1436: mcoml r1,r1
1437: andl2 r1,_whichqs # no more procs in this queue
1438: sw2:
1439: clrl _noproc
1440: clrl _runrun
1441: #ifdef notdef
1442: tstl P_WCHAN(r2) ## firewalls
1443: bneq badsw ##
1444: cmpb P_STAT(r2),$SRUN ##
1445: bneq badsw ##
1446: #endif
1447: clrl P_RLINK(r2) ##
1448: movl *P_ADDR(r2),r0
1449: #ifdef notdef
1450: cmpl r0,_masterpaddr # resume of current proc is easy
1451: beql res0
1452: #endif
1453: movl r0,_masterpaddr
1454: shal $PGSHIFT,r0,r0 # r0 = pcbb(p)
1455: brb swresume
1456:
1457: /*
1458: * resume(pf)
1459: */
1460: ENTRY(resume, 0)
1461: shal $PGSHIFT,4(fp),r0 # r0 = pcbb(pf)
1462: movl (fp),fp # prepare for rei
1463: movl (sp)+,4(sp) # saved pc
1464: tstl (sp)+
1465: movpsl 4(sp)
1466: swresume:
1467: mtpr $0x18,$IPL # no interrupts, please
1468: movl _CMAP2,_u+PCB_CMAP2 # yech
1469: REST_ACC # restore original accumulator
1470: svpctx
1471: mtpr r0,$PCBB
1472: ldpctx
1473: movl _u+PCB_CMAP2,_CMAP2 # yech
1474: mtpr $_CADDR2,$TBIS
1475: res0:
1476: movl _u+U_PROCP,r2 # r2 = u.u_procp
1477: tstl P_CKEY(r2) # does proc have code key?
1478: bneq 1f
1479: callf $4,_getcodekey # no, give him one
1480: movl _u+U_PROCP,r2 # r2 = u.u_procp
1481: movl r0,P_CKEY(r2)
1482: 1:
1483: tstl P_DKEY(r2) # does proc have data key?
1484: bneq 1f
1485: callf $4,_getdatakey # no, give him one
1486: movl _u+U_PROCP,r2 # r2 = u.u_procp
1487: movl r0,P_DKEY(r2)
1488: 1:
1489: mtpr P_CKEY(r2),$CCK # set code cache key
1490: mtpr P_DKEY(r2),$DCK # set data cache key
1491: tstl _u+PCB_SSWAP
1492: bneq res1
1493: rei
1494: res1: # restore alternate saved context
1495: movl _u+PCB_SSWAP,r2
1496: clrl _u+PCB_SSWAP
1497: loadr $0x3ff8,(r2); addl2 $44,r2 # restore r3-r13 (r13=fp)
1498: movl (r2),r1; addl2 $4,r2 # fetch previous sp ...
1499: movab (sp),r0 # ... and current sp and
1500: cmpl r1,r0 # check for credibility,
1501: bgequ 1f # if further up stack ...
1502: pushab 2f; callf $8,_panic # ... panic
1503: /*NOTREACHED*/
1504: 1: # sp ok, complete return
1505: movl r1,sp # restore sp
1506: pushl $PSL_PRVMOD # kernel mode, ipl 0
1507: pushl (r2) # return address
1508: rei
1509: 2: .asciz "ldctx"
1510:
1511: /*
1512: * {fu,su},{byte,word}
1513: */
1514: ENTRY(fuword, 0)
1515: movl 4(fp), r1
1516: prober $1,(r1),$4 # check access
1517: beql fserr # page unreadable
1518: bitl $1,r1 # check byte alignment
1519: bneq 2f # odd, do byte-word-byte
1520: bitl $2,r1 # check word alignment
1521: bneq 1f # odd, do in 2 words
1522: movl (r1),r0 # move longword
1523: ret
1524: 1:
1525: movw (r1),r0 # move two words
1526: shal $16,r0,r0
1527: movzwl 2(r1),r1 # orw2 sign extends
1528: orl2 r1,r0
1529: ret
1530: 2:
1531: movb (r1),r0 # move byte-word-byte
1532: shal $24,r0,r0
1533: movzwl 1(r1),r2 # orw2 sign extends
1534: shal $8,r2,r2
1535: movzbl 3(r1),r1 # orb2 sign extends
1536: orl2 r2,r1
1537: orl2 r1,r0
1538: ret
1539: fserr:
1540: mnegl $1,r0
1541: ret
1542:
1543: ENTRY(fubyte, 0)
1544: prober $1,*4(fp),$1
1545: beql fserr
1546: movzbl *4(fp),r0
1547: ret
1548:
1549: ENTRY(suword, 0)
1550: movl 4(fp), r0
1551: probew $1,(r0),$4 # check access
1552: beql fserr # page unwritable
1553: bitl $1,r0 # check byte alignment
1554: bneq 1f # odd byte boundary
1555: bitl $2,r0 # check word alignment
1556: beql 2f # longword aligned
1557: movw 8(fp),(r0) # move two words
1558: movw 10(fp),2(r0)
1559: jbr 3f
1560: 1:
1561: movb 8(fp),(r0)
1562: movb 9(fp),1(r0)
1563: movb 10(fp),2(r0)
1564: movb 11(fp),3(r0)
1565: jbr 3f
1566: 2:
1567: movl 8(fp),(r0)
1568: 3:
1569: clrl r0
1570: ret
1571:
1572: ENTRY(subyte, 0)
1573: probew $1,*4(fp),$1
1574: beql fserr
1575: movb 11(fp),*4(fp)
1576: clrl r0
1577: ret
1578:
1579: /*
1580: * Copy 1 relocation unit (NBPG bytes)
1581: * from user virtual address to physical address
1582: */
1583: ENTRY(copyseg, 0)
1584: orl3 $PG_V|PG_KW,8(fp),_CMAP2
1585: mtpr $_CADDR2,$TBIS # invalidate entry for copy
1586: MOVC3(4(fp),$_CADDR2,$NBPG)
1587: ret
1588:
1589: /*
1590: * Clear a page of memory. The page frame is specified.
1591: *
1592: * clearseg(pf);
1593: */
1594: ENTRY(clearseg, 0)
1595: orl3 $PG_V|PG_KW,4(fp),_CMAP1 # Maps to virtual addr CADDR1
1596: mtpr $_CADDR1,$TBIS
1597: movl $255,r0 # r0 = limit
1598: clrl r1 # r1 = index of cleared long
1599: 1:
1600: clrl _CADDR1[r1]
1601: aobleq r0,r1,1b
1602: ret
1603:
1604: /*
1605: * Check user mode read/write access.
1606: *
1607: * useracc(addr, count, mode)
1608: * caddr_t addr; int count, mode;
1609: * mode = 0 write access
1610: * mode = 1 read access
1611: */
1612: ENTRY(useracc, 0)
1613: movl $1,r2 # r2 = 'user mode' for probew/probew
1614: probes:
1615: movl 4(fp),r0 # get va
1616: movl 8(fp),r1 # count
1617: tstl 12(fp) # test for read access ?
1618: bneq userar # yes
1619: cmpl $(CLSIZE*NBPG),r1 # can we do it in one probe ?
1620: bgeq uaw2 # yes
1621: uaw1:
1622: probew r2,(r0),$(CLSIZE*NBPG)
1623: beql uaerr # no access
1624: addl2 $(CLSIZE*NBPG),r0
1625: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uaw1)
1626: uaw2:
1627: probew r2,(r0),r1
1628: beql uaerr
1629: movl $1,r0
1630: ret
1631: userar:
1632: cmpl $(CLSIZE*NBPG),r1
1633: bgeq uar2
1634: uar1:
1635: prober r2,(r0),$(CLSIZE*NBPG)
1636: beql uaerr
1637: addl2 $(CLSIZE*NBPG),r0
1638: _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uar1)
1639: uar2:
1640: prober r2,(r0),r1
1641: beql uaerr
1642: movl $1,r0
1643: ret
1644: uaerr:
1645: clrl r0
1646: ret
1647:
1648: /*
1649: * Check kernel mode read/write access.
1650: *
1651: * kernacc(addr, count, mode)
1652: * caddr_t addr; int count, mode;
1653: * mode = 0 write access
1654: * mode = 1 read access
1655: */
1656: ENTRY(kernacc, 0)
1657: clrl r2 # r2 = 0 means kernel mode probe.
1658: jbr probes # Dijkstra would get gastric distress here.
1659:
1660: /*
1661: * addupc - increment some histogram counter
1662: * in the profiling buffer
1663: *
1664: * addupc(pc, prof, delta)
1665: * long pc; short delta; struct uprof *prof;
1666: *
1667: * struct uprof { # profile arguments
1668: * short *r_base; # buffer base
1669: * unsigned pr_size; # buffer size
1670: * unsigned pr_off; # pc offset
1671: * unsigned pr_scale; # pc scaling
1672: * }
1673: */
1674: ENTRY(addupc, 0)
1675: movl 8(fp),r2 # r2 points to structure
1676: subl3 8(r2),4(fp),r0 # r0 = PC - lowpc
1677: jlss 9f # PC < lowpc , out of range !
1678: shrl $1,r0,r0 # the unit is words
1679: shrl $1,12(r2),r1 # ditto for scale
1680: emul r1,r0,$0,r0
1681: shrq $14,r0,r0
1682: tstl r0 # too big
1683: jneq 9f
1684: cmpl r1,4(r2) # Check buffer overflow
1685: jgequ 9f
1686: probew $1,*0(r2)[r1],$2 # counter accessible?
1687: jeql 9f
1688: shrl $1,r1,r1 # make r1 word index
1689: addw2 14(fp),*0(r2)[r1]
1690: 9: ret
1691:
1692: /*
1693: * scanc(size, cp, table, mask)
1694: */
1695: ENTRY(scanc, R3|R4)
1696: movl 8(fp),r0 # r0 = cp
1697: addl3 4(fp),r0,r2 # end = &cp[size]
1698: movl 12(fp),r1 # r1 = table
1699: movb 19(fp),r4 # r4 = mask
1700: decl r0 # --cp
1701: jbr 0f # just like Fortran...
1702: 1: # do {
1703: movzbl (r0),r3
1704: bitb r4,(r1)[r3] # if (table[*cp] & mask)
1705: jneq 2f # break;
1706: 0: aoblss r2,r0,1b # } while (++cp < end);
1707: 2:
1708: subl3 r0,r2,r0; ret # return (end - cp);
1709:
1710: /*
1711: * skpc(mask, size, cp)
1712: */
1713: ENTRY(skpc, 0)
1714: movl 12(fp),r0 # r0 = cp
1715: addl3 8(fp),r0,r1 # r1 = end = &cp[size];
1716: movb 7(fp),r2 # r2 = mask
1717: decl r0 # --cp;
1718: jbr 0f
1719: 1: # do
1720: cmpb (r0),r2 # if (*cp != mask)
1721: jneq 2f # break;
1722: 0: aoblss r1,r0,1b # while (++cp < end);
1723: 2:
1724: subl3 r0,r1,r0; ret # return (end - cp);
1725:
1726: /*
1727: * locc(mask, size, cp)
1728: */
1729: ENTRY(locc, 0)
1730: movl 12(fp),r0 # r0 = cp
1731: addl3 8(fp),r0,r1 # r1 = end = &cp[size]
1732: movb 7(fp),r2 # r2 = mask
1733: decl r0 # --cp;
1734: jbr 0f
1735: 1: # do
1736: cmpb (r0),r2 # if (*cp == mask)
1737: jeql 2f # break;
1738: 0: aoblss r1,r0,1b # while (++cp < end);
1739: 2:
1740: subl3 r0,r1,r0; ret # return (end - cp);
1741:
1742: #ifdef ALIGN
1743: #include "../tahoealign/align.h"
1744:
1745: .globl _alignment
1746: /*
1747: * There's an intimate relationship between this piece of code
1748: * and the alignment emulation code (especially the layout
1749: * of local variables in alignment.c! Don't change unless
1750: * you update both this, alignment.h and alignment.c !!
1751: */
1752: non_aligned:
1753: orb2 $EMULATEALIGN,_u+U_EOSYS
1754: incl _cnt+V_TRAP
1755: incl _cnt+V_ALIGN # count emulated alignment traps
1756: moval 4(sp),_user_psl
1757: SAVE_FPSTAT(4) # Also zeroes out ret_exception !
1758: pushl $0 # ret_addr
1759: pushl $0 # ret_code
1760: mfpr $USP,-(sp) # user sp
1761: callf $4,_alignment # call w/o parms so regs may be modified
1762: /*
1763: * We return here after a successful emulation or an exception.
1764: * The registers have been restored and we must not alter them
1765: * before returning to the user.
1766: */
1767: 2: mtpr (sp)+,$USP # restore user sp
1768: tstl 8(sp) # Any exception ?
1769: bneq got_excp # Yes, reflect it back to user.
1770: moval 8(sp),sp # pop 2 zeroes pushed above
1771: REST_FPSTAT
1772: xorb2 $EMULATEALIGN,_u+U_EOSYS
1773:
1774: bitl $PSL_T,4(sp) # check for trace bit set
1775: beql 9f
1776: CHECK_SFE(4)
1777: pushl $0
1778: SAVE_FPSTAT(8)
1779: TRAP(TRCTRAP)
1780: 9: rei
1781:
1782: got_excp: # decode exception
1783: casel 8(sp),$ILL_ADDRMOD,$ALIGNMENT
1784: .align 1
1785: L1:
1786: .word ill_addrmod-L1
1787: .word ill_access-L1
1788: .word ill_oprnd-L1
1789: .word arithmetic-L1
1790: .word alignment-L1
1791: brw alignment # default - shouldn't come here at all !
1792:
1793: ill_addrmod: # No other parameters. Set up stack as
1794: moval 8(sp),sp # the HW would do it in a real case.
1795: REST_FPSTAT
1796: jbr _Xresadflt
1797: ill_oprnd:
1798: moval 8(sp),sp
1799: REST_FPSTAT
1800: jbr _Xresopflt
1801: alignment:
1802: moval 8(sp),sp
1803: REST_FPSTAT
1804: jbr align_excp # NB: going to _Xalignflt would cause loop
1805: ill_access:
1806: /*
1807: * Must restore accumulator w/o modifying sp and w/o using
1808: * registers. Solution: copy things needed by REST_FPSTAT.
1809: */
1810: pushl 20(sp) # The flags longword
1811: pushl 20(sp) # acc_low
1812: pushl 20(sp) # acc_high
1813: pushl 20(sp) # ret_exception ignored by REST_FPSTAT
1814: REST_FPSTAT # Back where we were with the sp !
1815: movl (sp),16(sp) # code for illegal access
1816: movl 4(sp),20(sp) # original virtual address
1817: moval 16(sp),sp # Just like the HW would set it up
1818: jbr _Xprotflt
1819: arithmetic: # same trickery as above
1820: pushl 20(sp) # The flags longword
1821: pushl 20(sp) # acc_low
1822: pushl 20(sp) # acc_high
1823: pushl 20(sp) # ret_exception ignored by REST_FPSTAT
1824: REST_FPSTAT # Back where we were with the sp !
1825: movl (sp),20(sp) # code for arithmetic exception
1826: moval 20(sp),sp # Just like the HW would set it up
1827: jbr _Xarithtrap
1828: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.