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