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