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