|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Low level routines dealing with exception entry and exit.
26: * There are various types of exception:
27: *
28: * Interrupt, trap, system call and debugger entry. Each has it's own
29: * handler since the state save routine is different for each. The
30: * code is very similar (a lot of cut and paste).
31: *
32: * The code for the FPU disabled handler (lazy fpu) is in cswtch.s
33: */
34:
35: #include <debug.h>
36: #include <mach_assert.h>
37:
38: #include <mach/exception.h>
39: #include <mach/ppc/vm_param.h>
40:
41: #include <assym.h>
42:
43: #include <machdep/ppc/asm.h>
44: #include <machdep/ppc/proc_reg.h>
45: #include <machdep/ppc/trap.h>
46: #include <machdep/ppc/exception.h>
47: #include <kernserv/ppc/spl.h>
48: #include <machdep/ppc/machspl.h>
49: #include <kern/ast.h>
50:
51: /*
52: * thandler(type)
53: *
54: * Entry: VM switched ON
55: * Interrupts OFF
56: * original r1-3 saved in sprg1-3
57: * original srr0 and srr1 saved in per_proc_info structure
58: * original cr saved in per_proc_info structure
59: * exception type saved in per_proc_info structure
60: * r1 = scratch
61: * r2 = virt addr of per_proc_info
62: * r3 = exception type (one of EXC_...)
63: */
64:
65: /*
66: * If pcb.ksp == 0 then the kernel stack is already busy,
67: * we save ppc_saved state below the current stack pointer,
68: * leaving enough space for the `red zone' in case the
69: * trapped thread was in the middle of saving state below
70: * its stack pointer.
71: *
72: * otherwise we save a ppc_saved_state in the pcb, and switch to
73: * the kernel stack (setting pcb.ksp to 0)
74: *
75: * on return, we do the reverse, the last state is popped from the pcb
76: * and pcb.ksp is set to the top of stack below the kernel state + frame
77: * TODO NMGS - is this frame used? I don't think so
78: *
79: * Diagram of a thread's kernel stack
80: *
81: * --------------- TOP OF STACK
82: * |kernel_state |
83: * |---------------|
84: * |backpointer FM |
85: * |---------------|
86: * |... C usage ...|
87: * | |
88: * |---------------| TRAP IN KERNEL CODE
89: * |ppc_saved_state| STATE SAVED HERE
90: * |---------------|
91: * |backpointer FM |
92: * |---------------|
93: * |... C usage ...|
94: * | |
95: * | |
96: * | |
97: * | |
98: */
99:
100:
101: #if DEBUG
102:
103: /* TRAP_SPACE_NEEDED is the space assumed free on the kernel stack when
104: * another trap is taken. We need at least enough space for a saved state
105: * structure plus two small backpointer frames, and we add a few
106: * hundred bytes for the space needed by the C (which may be less but
107: * may be much more). We're trying to catch kernel stack overflows :-)
108: */
109:
110: #define TRAP_SPACE_NEEDED FM_REDZONE+SS_SIZE+(2*FM_SIZE)+256
111:
112: #endif /* DEBUG */
113:
114: .text
115:
116: ENTRY(thandler, TAG_NO_FRAME_USED) /* What tag should this have?! */
117:
118: /* If we're on the gdb stack, there has probably been
119: * a fault reading user memory or something like that,
120: * so we should pass this to the gdb handler. NOTE
121: * we may have entered gdb through an interrupt handler
122: * (keyboard or serial line, for example), so interrupt
123: * stack may be busy too.
124: */
125: addis r1, 0, ha16(EXT(gdbstackptr))
126: addi r1, r1, lo16(EXT(gdbstackptr)) /* TODO assumes 1 CPU */
127: lwz r1, 0(r1)
128: cmpwi CR0, r1, 0
129: beq- CR0, EXT(gdbhandler)
130:
131: #if DEBUG
132: /* Make sure we're not on the interrupt stack */
133: addis r1, 0, ha16(EXT(istackptr))
134: addi r1, r1, lo16(EXT(istackptr))
135: lwz r1, 0(r1)
136: cmpwi CR0, r1, 0
137:
138: /* If we are on the interrupt stack, treat as an interrupt,
139: * the interrupt handler will panic with useful info.
140: */
141:
142: beq- CR0, EXT(ihandler)
143:
144: #endif /* DEBUG */
145:
146: lwz r3, PP_CPU_DATA(r2)
147:
148: lwz r3, CPU_ACTIVE_THREAD(r3)
149: lwz r3, THREAD_PCB(r3)
150: lwz r1, PCB_KSP(r3)
151:
152: cmpwi CR1, r1, 0 /* zero implies already on kstack */
153: bne CR1, .L_kstackfree /* This test is also used below */
154:
155: mfsprg r1, 1 /* recover previous stack ptr */
156:
157: /* On kernel stack, allocate stack frame and check for overflow */
158:
159: /* Move stack pointer below redzone + reserve a saved_state */
160:
161: subi r1, r1, FM_REDZONE+SS_SIZE
162:
163: b .L_kstack_save_state
164:
165: .L_kstackfree:
166: mr r1, r3 /* r1 points to save area of pcb */
167:
168: .L_kstack_save_state:
169:
170: /* Once we reach here, r1 contains the place
171: * where we can store a ppc_saved_state structure. This may
172: * or may not be part of a pcb, we test that again once
173: * we've saved state. (CR1 still holds test done on ksp)
174: */
175:
176: stw r0, SS_R0(r1)
177:
178: mfsprg r0, 1
179: stw r0, SS_R1(r1)
180:
181: mfsprg r0, 2
182: stw r0, SS_R2(r1)
183:
184: mfsprg r0, 3
185: stw r0, SS_R3(r1)
186:
187: stw r4, SS_R4(r1)
188: stw r5, SS_R5(r1)
189: stw r6, SS_R6(r1)
190: stw r7, SS_R7(r1)
191: stw r8, SS_R8(r1)
192: stw r9, SS_R9(r1)
193: stw r10, SS_R10(r1)
194: stw r11, SS_R11(r1)
195: stw r12, SS_R12(r1)
196: stw r13, SS_R13(r1)
197: stw r14, SS_R14(r1)
198: stw r15, SS_R15(r1)
199: stw r16, SS_R16(r1)
200: stw r17, SS_R17(r1)
201: stw r18, SS_R18(r1)
202: stw r19, SS_R19(r1)
203: stw r20, SS_R20(r1)
204: stw r21, SS_R21(r1)
205: stw r22, SS_R22(r1)
206: stw r23, SS_R23(r1)
207: stw r24, SS_R24(r1)
208: stw r25, SS_R25(r1)
209: stw r26, SS_R26(r1)
210: stw r27, SS_R27(r1)
211: stw r28, SS_R28(r1)
212: stw r29, SS_R29(r1)
213: stw r30, SS_R30(r1)
214: stw r31, SS_R31(r1)
215:
216: /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
217: * some of this comes back out from the per-processor structure
218: * pointed to by r2
219: */
220:
221: lwz r0, PP_SAVE_CR(r2)
222: stw r0, SS_CR(r1)
223:
224: lwz r0, PP_SAVE_SRR0(r2)
225: stw r0, SS_SRR0(r1)
226:
227: /* WARNING - r0 from the following instruction is used
228: * further below
229: */
230:
231: lwz r0, PP_SAVE_SRR1(r2)
232: stw r0, SS_SRR1(r1)
233:
234:
235: /* WARNING! These two instructions assume that we didn't take
236: * any type of exception whilst saving state, it's a bit late
237: * for that!
238: * TODO NMGS move these up the code somehow, put in PROC_REG?
239: */
240:
241: mfdsisr ARG2 /* r4 */
242: mfdar ARG3 /* r5 */
243:
244: /* work out if we will reenable interrupts or not depending
245: * upon the state which we came from, store as tmp in ARG5
246: */
247: li ARG5, MSR_SUPERVISOR_INT_OFF
248: rlwimi ARG5, r0, 0, MSR_EE_BIT, MSR_EE_BIT
249:
250: mfxer r0
251: stw r0, SS_XER(r1)
252:
253: mflr r0
254: stw r0, SS_LR(r1)
255:
256: mfctr r0
257: stw r0, SS_CTR(r1)
258:
259: /* Don't save MQ, we don't bother for now */
260:
261: /* Free the reservation whilst saving SR_COPYIN */
262:
263: mfsr r0, SR_COPYIN_NAME
264: li ARG7, SS_SR_COPYIN
265: sync /* bug fix for 3.2 processors */
266: stwcx. r0, ARG7, r1
267: stw r0, SS_SR_COPYIN(r1)
268:
269: /* r3 still holds our pcb, CR1 still holds test to see if we're
270: * in the pcb or have saved state on the kernel stack */
271:
272: mr ARG1, r1 /* Preserve saved_state ptr in ARG1 */
273:
274: beq CR1, .L_state_on_kstack/* using above test for pcb/stack */
275:
276: /* We saved state in the pcb, recover the stack pointer */
277: lwz r1, PCB_KSP(r3)
278:
279: /* Mark that we're occupying the kernel stack for sure now */
280: li r0, 0
281: stw r0, PCB_KSP(r3)
282:
283: .L_state_on_kstack:
284:
285: /* Phew!
286: *
287: * To summarise, when we reach here, we have filled out
288: * a ppc_saved_state structure either in the pcb or on
289: * the kernel stack, and the stack is marked as busy.
290: * r4 holds a pointer to this state, r1 is now the stack
291: * pointer no matter where the state was savd.
292: * We now generate a small stack frame with backpointers
293: * to follow the calling
294: * conventions. We set up the backpointers to the trapped
295: * routine allowing us to backtrace.
296: */
297:
298: /* WARNING!! Using mfsprg below assumes interrupts are still off here */
299:
300: subi r1, r1, FM_SIZE
301: mfsprg r0, 1
302: stw r0, FM_BACKPTR(r1) /* point back to previous stackptr */
303:
304: #if DEBUG
305: /* If debugging, we need two frames, the first being a dummy
306: * which links back to the trapped routine. The second is
307: * that which the C routine below will need
308: */
309: lwz r0, SS_SRR0(r1)
310: stw r0, FM_LR_SAVE(r1) /* save old instr ptr as LR value */
311:
312: //stwu r1, -FM_SIZE(r1) /* and make new frame */
313: stw r1, -FM_SIZE(r1) /* and make new frame */
314: subi r1, r1, FM_SIZE
315: #endif /* DEBUG */
316:
317:
318: /* call trap handler proper, with
319: * ARG0 = type (not yet, holds pcb ptr)
320: * ARG1 = saved_state ptr (already there)
321: * ARG2 = dsisr (already there)
322: * ARG3 = dar (already there)
323: */
324:
325: /* This assumes that no (non-tlb) exception/interrupt has occured
326: * since PP_SAVE_* get clobbered by an exception...
327: */
328: lwz ARG0, PP_SAVE_EXCEPTION_TYPE(r2)
329:
330: /* Reenable interrupts if they were enabled before we came here */
331: mtmsr ARG5
332: isync
333:
334: /* syscall exception might warp here if there's nothing left
335: * to do except generate a trap
336: */
337: .L_call_trap:
338: bl EXT(trap)
339:
340: /*
341: * Ok, return from C function
342: *
343: * This is also the point where new threads come when they are created.
344: * The new thread is setup to look like a thread that took an
345: * interrupt and went immediatly into trap.
346: *
347: * r3 must hold the pointer to the saved state, either on the
348: * stack or in the pcb.
349: */
350:
351: thread_return:
352: /* Reload the saved state */
353:
354: /* r0-3 will be restored last, use as temp for now */
355:
356: lwz r4, SS_R4(r3)
357: lwz r5, SS_R5(r3)
358: lwz r6, SS_R6(r3)
359: lwz r7, SS_R7(r3)
360: lwz r8, SS_R8(r3)
361: lwz r9, SS_R9(r3)
362: lwz r10, SS_R10(r3)
363: lwz r11, SS_R11(r3)
364: lwz r12, SS_R12(r3)
365: lwz r13, SS_R13(r3)
366: lwz r14, SS_R14(r3)
367: lwz r15, SS_R15(r3)
368: lwz r16, SS_R16(r3)
369: lwz r17, SS_R17(r3)
370: lwz r18, SS_R18(r3)
371: lwz r19, SS_R19(r3)
372: lwz r20, SS_R20(r3)
373: lwz r21, SS_R21(r3)
374: lwz r22, SS_R22(r3)
375: lwz r23, SS_R23(r3)
376: lwz r24, SS_R24(r3)
377: lwz r25, SS_R25(r3)
378: lwz r26, SS_R26(r3)
379: lwz r27, SS_R27(r3)
380: lwz r28, SS_R28(r3)
381: lwz r29, SS_R29(r3)
382: lwz r30, SS_R30(r3)
383: lwz r31, SS_R31(r3)
384:
385: lwz r0, SS_XER(r3)
386: mtxer r0
387: lwz r0, SS_LR(r3)
388: mtlr r0
389: lwz r0, SS_CTR(r3)
390: mtctr r0
391: lwz r0, SS_SR_COPYIN(r3)
392: isync
393: mtsr SR_COPYIN_NAME, r0
394: isync
395:
396:
397: /* TODO NMGS don't restore mq since we're not 601-specific enough */
398:
399: /* Disable interrupts */
400: li r0, MSR_SUPERVISOR_INT_OFF
401: mtmsr r0
402:
403:
404: /* Is this the last saved state, found in the pcb? */
405: /* TODO NMGS optimise this by spreading it through the code above? */
406:
407: /* After this we no longer to keep &per_proc_info in r2 */
408:
409: lwz r1, PP_CPU_DATA(r2)
410: lwz r1, CPU_ACTIVE_THREAD(r1)
411: lwz r0, THREAD_PCB(r1)
412:
413: cmp CR0,0, r0, r3
414: bne CR0, .L_notthelast_trap
415:
416: /* our saved state is actually part of the thread's pcb so
417: * we need to mark that we're leaving the kernel stack and
418: * jump into user space
419: */
420:
421: /* Mark the kernel stack as free */
422:
423: /* There may be a critical region here for traps(interrupts?)
424: * once the stack is marked as free, PCB_SR0 may be trampled on
425: * so interrupts should be switched off
426: */
427: /* Release any processor reservation we may have had too */
428:
429: lwz r2, THREAD_KERNEL_STACK(r1)
430: addi r0, r2, KSTK_SIZE-KS_SIZE-FM_SIZE
431: li r2, PCB_KSP
432: /* we have to use an indirect store to clear reservation */
433: sync /* bug fix for 3.2 processors */
434: stwcx. r0, r2, r3 /* clear reservation */
435: stw r0, PCB_KSP(r3) /* mark stack as free */
436:
437: /* We may be returning to something in the kernel space.
438: * If we are, we can skip the trampoline and just rfi,
439: * since we don't want to restore the user's space regs
440: */
441: lwz r0, SS_SRR1(r3)
442: andi. r0, r0, MASK(MSR_PR)
443: beq- .L_trap_ret_to_kspace
444:
445: /* If jumping into user space, we should restore the user's
446: * segment register 0. We jump via a trampoline in physical mode
447: */
448:
449: lwz r0, SS_CR(r3)
450: mtcrf 0xFF,r0
451:
452: /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
453: * as arguments */
454: lwz r0, SS_R1(r3)
455: mtsprg 1, r0
456: lwz r0, SS_R2(r3)
457: mtsprg 2, r0
458: lwz r0, SS_R3(r3)
459: mtsprg 3, r0
460:
461: lwz r0, SS_R0(r3)
462:
463: /* Prepare to rfi to the exception exit routine, which is
464: * in physical address space */
465: addis r1, 0, ha16(EXT(exception_exit))
466: addi r1, r1, lo16(EXT(exception_exit))
467: lwz r1, 0(r1)
468: mtsrr0 r1
469: li r1, MSR_VM_OFF
470: mtsrr1 r1
471:
472:
473: lwz r1, PCB_SR0(r3) /* For trampoline */
474: lwz r2, SS_SRR0(r3) /* For trampoline */
475:
476: lwz r3, SS_SRR1(r3) /* load the last register... */
477:
478: rfi
479:
480: .L_trap_ret_to_kspace:
481: .L_notthelast_trap:
482: /* If we're not the last trap on the kernel stack life is easier,
483: * we don't need to switch back into the user's segment. we can
484: * simply restore the last registers and rfi
485: */
486:
487: lwz r0, SS_CR(r3)
488: mtcrf 0xFF,r0
489: lwz r0, SS_SRR0(r3)
490: mtsrr0 r0
491: lwz r0, SS_SRR1(r3)
492: mtsrr1 r0
493:
494: lwz r0, SS_R0(r3)
495: lwz r1, SS_R1(r3)
496: /* critical region for traps(interrupt?) since r1 no longer points
497: * to bottom of stack. Could be fixed. But interrupts are off (?).
498: */
499: lwz r2, SS_R2(r3) /* r2 is a constant (&per_proc_info) */
500: /* r3 restored last */
501: lwz r4, SS_R4(r3)
502: lwz r5, SS_R5(r3)
503: /* and lastly... */
504: lwz r3, SS_R3(r3)
505:
506: rfi /* return to calling context */
507:
508:
509:
510: /*QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
511: * void CallPseudoKernel ( void )
512: *
513: * This op provides a means of invoking the BlueBox PseudoKernel from a
514: * system (68k) or native (PPC) context while changing BlueBox interruption
515: * state atomically. As an added bonus, this op clobbers only r0 while leaving
516: * the rest of PPC user state registers intact.
517: *
518: * This op is invoked as follows:
519: * li r0, kCallPseudoKernelNumber // load this op's firmware call number
520: * sc // invoke CallPseudoKernel
521: * dc.l CallPseudoKernelDescriptorPtr // static pointer to CallPseudoKernelDescriptor
522: *
523: * NOTE: The CallPseudoKernelDescriptor and the word pointed to by
524: * intControlAddr must be locked, else this op will crash the kernel.
525: *
526: * Entry: VM switched ON
527: * Interrupts OFF
528: * original r1-3 saved in sprg1-3
529: * original srr0 and srr1 saved in per_proc_info structure
530: * original cr saved in per_proc_info structure
531: * exception type saved in per_proc_info structure
532: * r1 = scratch
533: * r2 = virt addr of per_proc_info
534: * r3 = exception type (one of EXC_...)
535: *
536: QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ*/
537: .align 5
538:
539: __fcCallPseudoKernel:
540:
541: // Needed to save some state so this code matches NuKernel Support
542: lwz r1, PP_CPU_DATA(r2)
543: lwz r3, CPU_ACTIVE_THREAD(r1)
544: lwz r1, THREAD_PCB(r3)
545:
546: stw r0, SS_R0(r1)
547:
548: lwz r0, PP_SAVE_SRR0(r2)
549: stw r0, SS_SRR0(r1)
550:
551: lwz r0, PP_SAVE_SRR1(r2)
552: stw r0, SS_SRR1(r1)
553:
554: lwz r0, PP_SAVE_CR(r2)
555: stw r0, SS_CR(r1)
556:
557: mfsprg r0, 1
558: stw r0, SS_R1(r1)
559:
560: mfsprg r0, 2
561: stw r0, SS_R2(r1)
562:
563: mfsprg r0, 3
564: stw r0, SS_R3(r1)
565:
566: stw r4, SS_R4(r1)
567: stw r5, SS_R5(r1)
568: stw r6, SS_R6(r1)
569: stw r7, SS_R7(r1)
570: stw r8, SS_R8(r1)
571: stw r9, SS_R9(r1)
572: stw r10, SS_R10(r1)
573: stw r11, SS_R11(r1)
574: stw r12, SS_R12(r1)
575:
576: // word following the sc is the descriptor's address
577: lwz r3, SS_SRR0(r1)
578:
579: lwz r10, SS_CR(r1) // setup r10 with CR
580:
581: lwz r3, 0(r3) // get descriptor's address
582:
583: lwz r11, CPKD_INTCONTROLADDR(r3)
584: lwz r4, CPKD_PC(r3)
585: lwz r6, CPKD_NEWSTATE(r3)
586: lwz r7, CPKD_INTSTATEMASK(r3)
587: lwz r8, 0(r11) // get current interruption control word
588: lwz r5, CPKD_GPR0(r3)
589: lwz r12, CPKD_SYSCONTEXTSTATE(r3)
590: andc r9, r8, r7 // remove current state
591: and r8, r8, r7 // extract current state
592: cmplw r8, r12 // test for entry from system context
593: or r9, r9, r6 // insert new state
594: bne CallFromAlternateContext
595:
596: CallFromSystemContext:
597: lwz r6, CPKD_INTCR2SHIFT(r3)
598: lwz r7, CPKD_INTCR2MASK(r3)
599: srw r10, r10, r6 // position live CR2 from cr register as required
600: andc r9, r9, r7 // remove old backup CR2
601: and r10, r10, r7 // mask live CR2
602: or r9, r9, r10 // insert CR2 into backup CR2
603: b CallContinue
604:
605: CallFromAlternateContext:
606: CallContinue:
607: stw r9, 0(r11) // update interruption control word
608:
609: // introduce new pc and gr0 contents
610: lwz r6, SS_SRR1(r1)
611: stw r4, SS_SRR0(r1)
612: stw r5, SS_R0(r1)
613:
614: // insert updated fe0, fe1, se, and be bits into user msr
615: rlwimi r6, r6, 0, MSR_FE1_BIT, MSR_FE0_BIT
616: /* Turn off FPU */
617: rlwinm r6, r6, 0, MSR_FP_BIT+1, MSR_FP_BIT-1
618:
619: // zero single step and branch step control in user msr
620: stw r6, SS_SRR1(r1) // update user msr
621:
622: /*
623: ** Restore state for exit
624: */
625: lwz r0, SS_CR(r1)
626: mtcrf 0xFF, r0
627:
628: /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
629: * as arguments */
630: lwz r0, SS_R1(r1)
631: mtsprg 1, r0
632:
633: lwz r0, SS_R2(r1)
634: mtsprg 2, r0
635:
636: lwz r0, SS_R3(r1)
637: mtsprg 3, r0
638:
639: lwz r0, SS_R0(r1)
640:
641: lwz r4, SS_R4(r1)
642: lwz r5, SS_R5(r1)
643: lwz r6, SS_R6(r1)
644: lwz r7, SS_R7(r1)
645: lwz r8, SS_R8(r1)
646: lwz r9, SS_R9(r1)
647: lwz r10, SS_R10(r1)
648: lwz r11, SS_R11(r1)
649: lwz r12, SS_R12(r1)
650:
651: /* Prepare to rfi to the exception exit routine, which is
652: * in physical address space */
653: addis r3, 0, ha16(EXT(exception_exit))
654: addi r3, r3, lo16(EXT(exception_exit))
655: lwz r3, 0(r3)
656: mtsrr0 r3
657: li r3, MSR_VM_OFF
658: mtsrr1 r3
659:
660: lwz r2, SS_SRR0(r1) /* For trampoline */
661: lwz r3, SS_SRR1(r1) /* For trampoline */
662: lwz r1, PCB_SR0(r1) /* load the last register... */
663:
664: rfi
665:
666:
667:
668: /*QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
669: * void ExitPseudoKernel ( ExitPseudoKernelDescriptorPtr exitDescriptor )
670: *
671: * This op provides a means of exiting from the BlueBox PseudoKernel to a
672: * user context while changing the BlueBox interruption state atomically.
673: * It also allows all of the user state PPC registers to be loaded.
674: *
675: * This op is invoked as follows:
676: * lwz r3, ExitPseudoKernelDescriptorPtr
677: * li r0, kCallPseudoKernelNumber // load this op's firmware call number
678: * sc // invoke CallPseudoKernel
679: *
680: * Entry: VM switched ON
681: * Interrupts OFF
682: * original r1-3 saved in sprg1-3
683: * original srr0 and srr1 saved in per_proc_info structure
684: * original cr saved in per_proc_info structure
685: * exception type saved in per_proc_info structure
686: * r1 = scratch
687: * r2 = virt addr of per_proc_info
688: * r3 = exception type (one of EXC_...)
689: *
690: QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ*/
691: .align 5
692: __fcExitPseudoKernel:
693: // Needed to save some state so this code matches NuKernel Support
694: lwz r1, PP_CPU_DATA(r2)
695: lwz r1, CPU_ACTIVE_THREAD(r1)
696: lwz r1, THREAD_PCB(r1)
697:
698: stw r0, SS_R0(r1)
699:
700: lwz r0, PP_SAVE_SRR0(r2)
701: stw r0, SS_SRR0(r1)
702:
703: lwz r0, PP_SAVE_SRR1(r2)
704: stw r0, SS_SRR1(r1)
705:
706: lwz r0, PP_SAVE_CR(r2)
707: stw r0, SS_CR(r1)
708:
709: mfsprg r0, 1
710: stw r0, SS_R1(r1)
711:
712: mfsprg r0, 2
713: stw r0, SS_R2(r1)
714:
715: mfsprg r0, 3
716: stw r0, SS_R3(r1)
717:
718: stw r4, SS_R4(r1)
719: stw r5, SS_R5(r1)
720: stw r6, SS_R6(r1)
721: stw r7, SS_R7(r1)
722: stw r8, SS_R8(r1)
723: stw r9, SS_R9(r1)
724: stw r10, SS_R10(r1)
725: stw r11, SS_R11(r1)
726: stw r12, SS_R12(r1)
727:
728: /* start of actual routine */
729:
730: lwz r9, SS_SRR1(r1)
731:
732: lwz r3, SS_R3(r1) // restore r3, it is exitdescptr
733:
734: lwz r8, EPKD_CR(r3)
735:
736: lwz r11, EPKD_INTCONTROLADDR(r3)
737: lwz r4, EPKD_PC(r3)
738: lwz r7, EPKD_NEWSTATE(r3)
739: lwz r10, EPKD_INTSTATEMASK(r3)
740: lwz r5, 0(r11) // get current interruption control word
741: lwz r0, EPKD_SYSCONTEXTSTATE(r3)
742: andc r12, r5, r10 // remove current state
743: cmplw r7, r0 // test for exit to system context
744: or r12, r12, r7 // insert new state
745: lwz r0, EPKD_MSRUPDATE(r3)
746: beq ExitToSystemContext
747:
748: ExitToAlternateContext:
749: lwz r5, EPKD_INTPENDINGMASK(r3)
750: lwz r6, EPKD_INTPENDINGPC(r3)
751: and. r7, r12, r5 // test for pending 'rupt in backup cr2
752: beq ExitUpdateRuptControlWord // and enter alternate context if none pending
753: mr r4, r6 // otherwise, introduce entry abort pc
754: b ExitNoUpdateRuptControlWord // and prepare to reenter pseudokernel
755:
756: ExitToSystemContext:
757: lwz r5, EPKD_INTCR2SHIFT(r3)
758: lwz r6, EPKD_INTCR2MASK(r3)
759: slw r7, r12, r5 // position backup cr2
760: and r7, r7, r6 // and mask it
761: or r8, r8, r7 // then or it into the live cr2
762: // ...fall through into system context
763:
764: ExitUpdateRuptControlWord:
765: // insert updated fe0, fe1, se, and be bits into user msr
766: rlwimi r9, r0, 0, MSR_FE0_BIT, MSR_FE1_BIT
767: /* Turn off FPU */
768: rlwinm r9, r9, 0, MSR_FP_BIT+1, MSR_FP_BIT-1
769: stw r12, 0(r11) // update interruption control word
770: ExitNoUpdateRuptControlWord:
771: lwz r5, EPKD_GPR0(r3)
772: lwz r6, EPKD_SP(r3)
773: lwz r7, EPKD_GPR3(r3)
774: // load caller's new register contents
775:
776: stw r4, SS_SRR0(r1)
777: stw r5, SS_R0(r1)
778: stw r6, SS_R1(r1)
779: stw r7, SS_R3(r1)
780: stw r8, SS_CR(r1)
781: stw r9, SS_SRR1(r1)
782:
783:
784: lwz r0, SS_CR(r1)
785: mtcrf 0xFF,r0 /* update cr, it is live */
786:
787: /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
788: * as arguments */
789: lwz r0, SS_R1(r1)
790: mtsprg 1, r0
791: lwz r0, SS_R2(r1)
792: mtsprg 2, r0
793: lwz r0, SS_R3(r1)
794: mtsprg 3, r0
795:
796: lwz r0, SS_R0(r1)
797:
798: lwz r4, SS_R4(r1)
799: lwz r5, SS_R5(r1)
800: lwz r6, SS_R6(r1)
801: lwz r7, SS_R7(r1)
802: lwz r8, SS_R8(r1)
803: lwz r9, SS_R9(r1)
804: lwz r10, SS_R10(r1)
805: lwz r11, SS_R11(r1)
806: lwz r12, SS_R12(r1)
807:
808: /* Prepare to rfi to the exception exit routine, which is
809: * in physical address space */
810: addis r3, 0, ha16(EXT(exception_exit))
811: addi r3, r3, lo16(EXT(exception_exit))
812: lwz r3, 0(r3)
813: mtsrr0 r3
814: li r3, MSR_VM_OFF
815: mtsrr1 r3
816:
817: lwz r2, SS_SRR0(r1) /* For trampoline */
818: lwz r3, SS_SRR1(r1) /* load the last register... */
819: lwz r1, PCB_SR0(r1) /* For trampoline... */
820:
821: rfi
822:
823:
824: /*
825: * void cthread_set_self(cproc_t p)
826: *
827: * set's thread state "user_value"
828: *
829: * This op is invoked as follows:
830: * li r0, CthreadSetSelfNumber // load the fast-trap number
831: * sc // invoke fast-trap
832: * blr
833: *
834: * Entry: VM switched ON
835: * Interrupts OFF
836: * original r1-3 saved in sprg1-3
837: * original srr0 and srr1 saved in per_proc_info structure
838: * original cr saved in per_proc_info structure
839: * exception type saved in per_proc_info structure
840: * r1 = scratch
841: * r2 = virt addr of per_proc_info
842: * r3 = exception type (one of EXC_...)
843: *
844: */
845: .text
846: .align 5
847: __fcCthreadSetSelfNumber:
848: lwz r1, PP_CPU_DATA(r2)
849: lwz r1, CPU_ACTIVE_THREAD(r1)
850: lwz r1, THREAD_PCB(r1)
851:
852: mfsprg r3, 3
853: stw r3, CTHREAD_SELF(r1)
854:
855: /* Prepare to rfi to the exception exit routine, which is
856: * in physical address space */
857: addis r3, 0, ha16(EXT(exception_exit))
858: addi r3, r3, lo16(EXT(exception_exit))
859: lwz r3, 0(r3)
860: mtsrr0 r3
861: li r3, MSR_VM_OFF
862: mtsrr1 r3
863:
864: lwz r3, PP_SAVE_SRR1(r2) /* load the last register... */
865: lwz r2, PP_SAVE_SRR0(r2) /* For trampoline */
866: lwz r1, PCB_SR0(r1) /* For trampoline... */
867:
868: rfi
869:
870:
871: /*
872: * ur_cthread_t ur_cthread_self(void)
873: *
874: * return thread state "user_value"
875: *
876: * This op is invoked as follows:
877: * li r0, UrCthreadSelfNumber // load the fast-trap number
878: * sc // invoke fast-trap
879: * blr
880: *
881: * Entry: VM switched ON
882: * Interrupts OFF
883: * original r1-3 saved in sprg1-3
884: * original srr0 and srr1 saved in per_proc_info structure
885: * original cr saved in per_proc_info structure
886: * exception type saved in per_proc_info structure
887: * r1 = scratch
888: * r2 = virt addr of per_proc_info
889: * r3 = exception type (one of EXC_...)
890: *
891: */
892: .text
893: .align 5
894: __fcUrCthreadSelfNumber:
895: lwz r1, PP_CPU_DATA(r2)
896: lwz r1, CPU_ACTIVE_THREAD(r1)
897: lwz r1, THREAD_PCB(r1)
898:
899: lwz r3, CTHREAD_SELF(r1)
900: mtsprg 3, r3
901:
902:
903: /* Prepare to rfi to the exception exit routine, which is
904: * in physical address space */
905: addis r3, 0, ha16(EXT(exception_exit))
906: addi r3, r3, lo16(EXT(exception_exit))
907: lwz r3, 0(r3)
908: mtsrr0 r3
909: li r3, MSR_VM_OFF
910: mtsrr1 r3
911:
912: lwz r3, PP_SAVE_SRR1(r2) /* load the last register... */
913: lwz r2, PP_SAVE_SRR0(r2) /* For trampoline */
914: lwz r1, PCB_SR0(r1) /* For trampoline... */
915:
916: rfi
917:
918:
919:
920: /*
921: * shandler(type)
922: *
923: * Entry: VM switched ON
924: * Interrupts OFF
925: * original r1-3 saved in sprg1-3
926: * original srr0 and srr1 saved in per_proc_info structure
927: * original cr saved in per_proc_info structure
928: * exception type saved in per_proc_info structure
929: * r1 = scratch
930: * r2 = virt addr of per_proc_info
931: * r3 = exception type (one of EXC_...)
932: */
933:
934: /*
935: * If pcb.ksp == 0 then the kernel stack is already busy,
936: * this is an error - jump to the debugger entry
937: *
938: * otherwise we save a (partial - TODO ) ppc_saved_state
939: * in the pcb, and, depending upon the type of
940: * syscall, look it up in the kernel table
941: * or pass it to the server.
942: *
943: * on return, we do the reverse, the state is popped from the pcb
944: * and pcb.ksp is set to the top of stack.
945: */
946:
947: ENTRY(shandler, TAG_NO_FRAME_USED) /* What tag should this have?! */
948:
949: #if DEBUG
950: /* Make sure we're not on the interrupt stack */
951: addis r1, 0, ha16(EXT(istackptr))
952: addi r1, r1, lo16(EXT(istackptr))
953: lwz r1, 0(r1)
954: cmpwi CR0, r1, 0
955:
956: /* If we are on the interrupt stack, treat as an interrupt,
957: * the interrupt handler will panic with useful info.
958: */
959: beq EXT(ihandler)
960:
961: #endif /* DEBUG */
962:
963: /*
964: ** check for special BlueBox calls
965: */
966: addis r1, 0, ha16(EXT(nsysent))
967: addi r1, r1, lo16(EXT(nsysent))
968: lwz r3, 0(r1)
969: cmpw CR0, r0, r3
970: ble L_shandler_syscall
971:
972: cmpwi CR0, r0, 0x7FFC
973: beq- __fcCallPseudoKernel
974:
975: cmpwi CR0, r0, 0x7FFE
976: beq- __fcExitPseudoKernel
977:
978: cmpwi CR0, r0, 0x7FF1 ;CthreadSetSelfNumber
979: beq- __fcCthreadSetSelfNumber
980:
981: cmpwi CR0, r0, 0x7FF2 ;UrCthreadSelfNumber
982: beq- __fcUrCthreadSelfNumber
983:
984: L_shandler_syscall:
985: lwz r3, PP_CPU_DATA(r2)
986: lwz r3, CPU_ACTIVE_THREAD(r3)
987: lwz r1, THREAD_PCB(r3)
988: #if DEBUG
989: /* Check that we're not on kernel stack already */
990: lwz r1, PCB_KSP(r1)
991:
992: /* If we are on a kernel stack, treat as a interrupt
993: * the interrupt handler will panic with useful info.
994: */
995: cmpwi CR1, r1, 0
996: /* tell the handler that we performed a syscall from this loc */
997: li r3, EXC_SYSTEM_CALL
998: beq CR1, EXT(ihandler)
999:
1000: /* Reload active thread into r3 and PCB into r1 as before */
1001: lwz r3, PP_CPU_DATA(r2)
1002: lwz r3, CPU_ACTIVE_THREAD(r3)
1003: lwz r1, THREAD_PCB(r3)
1004: #endif /* DEBUG */
1005:
1006: /* Once we reach here, r1 contains the pcb
1007: * where we can store a partial ppc_saved_state structure,
1008: * and r3 contains the active thread structure (used later)
1009: */
1010:
1011: /* TODO NMGS - could only save callee saved regs for
1012: * many(all?) Mach syscalls, not for unix since might be fork() etc
1013: */
1014: stw r0, SS_R0(r1) /* Save trap number for debugging */
1015:
1016: lwz r0, PP_SAVE_CR(r2)
1017: stw r0, SS_CR(r1)
1018:
1019: lwz r0, PP_SAVE_SRR0(r2) /* Save SRR0 in debug call frame */
1020: stw r0, SS_SRR0(r1)
1021:
1022: lwz r0, PP_SAVE_SRR1(r2)
1023: oris r0, r0, MSR_SYSCALL_MASK >> 16 /* Mark syscall state */
1024: stw r0, SS_SRR1(r1)
1025:
1026: mfsprg r0, 1
1027: stw r0, SS_R1(r1)
1028:
1029: mfsprg r0, 2
1030: stw r0, SS_R2(r1)
1031:
1032: /* SAVE ARG REGISTERS? - YES, needed by server system calls */
1033: mfsprg r0, 3
1034: stw r0, SS_R3(r1)
1035:
1036: stw r4, SS_R4(r1)
1037: stw r5, SS_R5(r1)
1038: stw r6, SS_R6(r1)
1039: stw r7, SS_R7(r1)
1040: stw r8, SS_R8(r1)
1041: stw r9, SS_R9(r1)
1042: stw r10, SS_R10(r1)
1043:
1044: stw r11, SS_R11(r1)
1045: stw r12, SS_R12(r1)
1046: stw r13, SS_R13(r1)
1047:
1048: /*
1049: * Callee saved state, need to save in case we
1050: * are executing a 'fork' unix system call or similar
1051: */
1052:
1053: stw r14, SS_R14(r1)
1054: stw r15, SS_R15(r1)
1055: stw r16, SS_R16(r1)
1056: stw r17, SS_R17(r1)
1057: stw r18, SS_R18(r1)
1058: stw r19, SS_R19(r1)
1059: stw r20, SS_R20(r1)
1060: stw r21, SS_R21(r1)
1061: stw r22, SS_R22(r1)
1062: stw r23, SS_R23(r1)
1063: stw r24, SS_R24(r1)
1064: stw r25, SS_R25(r1)
1065:
1066: /* We use these registers in the code below, save them */
1067:
1068: stw r26, SS_R26(r1)
1069: stw r27, SS_R27(r1)
1070: stw r28, SS_R28(r1)
1071: stw r29, SS_R29(r1)
1072: stw r30, SS_R30(r1)
1073: stw r31, SS_R31(r1)
1074:
1075: /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
1076: * some of this comes back out from the per-processor structure
1077: */
1078:
1079: mflr r0
1080: stw r0, SS_LR(r1)
1081:
1082: /* Volatile state, still restoring for sensible corefiles */
1083: mfctr r0
1084: stw r0, SS_CTR(r1)
1085:
1086: mfxer r0
1087: stw r0, SS_XER(r1)
1088:
1089: /* Don't bother with MQ for now */
1090:
1091: /* Free the reservation whilst saving SR_COPYIN */
1092:
1093: mfsr r0, SR_COPYIN_NAME
1094: li r31, SS_SR_COPYIN
1095: sync /* bug fix for 3.2 processors */
1096: stwcx. r0, r31, r1
1097: stw r0, SS_SR_COPYIN(r1)
1098:
1099: /* We saved state in the pcb, recover the stack pointer */
1100: lwz r31, PCB_KSP(r1) /* Get ksp */
1101:
1102: li r0, 0
1103: stw r0, PCB_KSP(r1) /* Mark stack as busy with 0 val */
1104:
1105: /* Phew!
1106: *
1107: * To summarise, when we reach here, we have filled out
1108: * a (partial) ppc_saved_state structure in the pcb, moved
1109: * to kernel stack, and the stack is marked as busy.
1110: * r1 holds a pointer to this state, and r3 holds a
1111: * pointer to the active thread. r31 holds kernel stack ptr.
1112: * We now move onto the kernel stack and generate a small
1113: * stack frame to follow the calling
1114: * conventions. We set up the backpointers to the calling
1115: * routine allowing us to backtrace.
1116: */
1117:
1118: mr r30, r1 /* Save pointer to state in r30 */
1119: mr r1, r31 /* move to kernel stack */
1120: mfsprg r0, 1 /* get old stack pointer */
1121: stw r0, FM_BACKPTR(r1) /* store as backpointer */
1122:
1123: #if DEBUG
1124: /* If debugging, we need two frames, the first being a dummy
1125: * which links back to the trapped routine. The second is
1126: * that which the C routine below will need
1127: */
1128: stw r29, FM_LR_SAVE(r1) /* save old instr ptr as LR value */
1129: //stwu r1, -FM_SIZE(r1) /* point back to previous frame */
1130: stw r1, -FM_SIZE(r1) /* point back to previous frame */
1131: subi r1, r1, FM_SIZE
1132: #endif /* DEBUG */
1133:
1134: //stwu r1, -(FM_SIZE+ARG_SIZE)(r1)
1135: //stwu r1, -(FM_SIZE+FM_REDZONE)(r1)
1136: stw r1, -(FM_SIZE+FM_REDZONE)(r1)
1137: subi r1, r1, (FM_SIZE+FM_REDZONE)
1138:
1139: /* switch on interrupts now kernel stack is busy and valid */
1140: mfmsr r0
1141: rlwimi r0, r0, 0, MSR_EE_BIT, MSR_EE_BIT
1142: mtmsr r0
1143:
1144:
1145: /* we should still have r1=ksp, r3(ie ARG0)=current-thread,
1146: * r30 = pointer to saved state (in pcb)
1147: */
1148:
1149: /* Work out what kind of syscall we have to deal with.
1150: */
1151:
1152: #if MACH_ASSERT
1153: /* Call a function that can print out our syscall info */
1154: mr r4, r30
1155: bl syscall_trace
1156: /* restore those volatile argument registers */
1157: lwz r4, SS_R4(r30)
1158: lwz r5, SS_R5(r30)
1159: lwz r6, SS_R6(r30)
1160: lwz r7, SS_R7(r30)
1161: lwz r8, SS_R8(r30)
1162: lwz r9, SS_R9(r30)
1163: lwz r10, SS_R10(r30)
1164:
1165: #endif /* MACH_ASSERT */
1166: mr r3, r30 /* put pcb in ARG0 */
1167: lwz r0, SS_R0(r30)
1168:
1169: cmpwi CR0, r0, 0
1170: blt- .L_mach_kernel_syscall
1171:
1172: /* +ve syscall - go to server */
1173:
1174: b EXT(unix_syscall)
1175:
1176: .L_mach_kernel_syscall:
1177:
1178: b EXT(mach_syscall)
1179:
1180:
1181:
1182: .L_thread_syscall_return:
1183:
1184: li r3, MSR_SUPERVISOR_INT_OFF
1185: mtmsr r3
1186:
1187: /* thread_exception_return returns to here, almost all
1188: * registers intact. It expects a full context restore
1189: * of what it hasn't restored itself (ie. what we use).
1190: *
1191: * In particular for us,
1192: * we still have r31 points to the current thread,
1193: * r30 points to the current pcb
1194: */
1195:
1196: mr r3, r30
1197: mr r1, r31
1198: /* r0-2 will be restored last, use as temp for now */
1199:
1200:
1201: /* Callee saved state was saved and restored by the functions
1202: * that we have called, assuming that we performed a standard
1203: * function calling sequence. We only restore those that we
1204: * are currently using.
1205: *
1206: * thread_exception_return arrives here, however, and it
1207: * expects the full state to be restored
1208: */
1209: #if DEBUG
1210: /* the following callee-saved state should already be restored */
1211:
1212: lwz r30, SS_R14(r3)@ twne r30, r14
1213: lwz r30, SS_R15(r3)@ twne r30, r15
1214: lwz r30, SS_R16(r3)@ twne r30, r16
1215: lwz r30, SS_R17(r3)@ twne r30, r17
1216: lwz r30, SS_R18(r3)@ twne r30, r18
1217: lwz r30, SS_R19(r3)@ twne r30, r19
1218: lwz r30, SS_R20(r3)@ twne r30, r20
1219: lwz r30, SS_R21(r3)@ twne r30, r21
1220: lwz r30, SS_R22(r3)@ twne r30, r22
1221: lwz r30, SS_R23(r3)@ twne r30, r23
1222: lwz r30, SS_R24(r3)@ twne r30, r24
1223: lwz r30, SS_R25(r3)@ twne r30, r25
1224: lwz r30, SS_R26(r3)@ twne r30, r26
1225: lwz r30, SS_R27(r3)@ twne r30, r27
1226: lwz r30, SS_R28(r3)@ twne r30, r28
1227: lwz r30, SS_R29(r3)@ twne r30, r29
1228: #endif /* DEBUG */
1229:
1230: lwz r30, SS_R30(r3)
1231: lwz r31, SS_R31(r3)
1232:
1233: lwz r0, SS_LR(r3)
1234: mtlr r0
1235:
1236: /* Volatile state, still restoring for sensible corefiles */
1237: lwz r0, SS_CTR(r3)
1238: mtctr r0
1239:
1240: lwz r0, SS_XER(r3)
1241: mtxer r0
1242:
1243: lwz r0, SS_SR_COPYIN(r3)
1244: isync
1245: mtsr SR_COPYIN_NAME, r0
1246: isync
1247:
1248: /* mark kernel stack as free before restoring r30, r31 */
1249:
1250: /* we no longer need r2 pointer to per_proc_info at this point */
1251:
1252: /* There may be a critical region here for traps(interrupts?)
1253: * once the stack is marked as free, PCB_SR0 may be trampled on
1254: * so interrupts must be off.
1255: */
1256: /* Clear reservation at the same time */
1257: lwz r2, THREAD_KERNEL_STACK(r1)
1258: addi r0, r2, KSTK_SIZE-KS_SIZE-FM_SIZE
1259: li r2, PCB_KSP
1260: /* we have to use an indirect store to clear reservation */
1261: sync /* bug fix for 3.2 processors */
1262: stwcx. r0, r2, r3 /* clear reservation */
1263: stw r0, PCB_KSP(r3) /* mark stack as free */
1264:
1265: /* We may be returning to something in the kernel space.
1266: * If we are, we can skip the trampoline and just rfi,
1267: * since we don't want to restore the user's space regs
1268: */
1269: lwz r0, SS_SRR1(r3)
1270: andi. r0, r0, MASK(MSR_PR)
1271: bne+ .L_syscall_returns_to_user
1272:
1273: /* TODO NMGS - is this code in common with interrupts and traps?*/
1274: /* the syscall is returning to something in
1275: * priviliged mode, can just rfi without modifying
1276: * space registers
1277: */
1278:
1279: lwz r0, SS_CR(r3)
1280: mtcrf 0xFF,r0
1281: lwz r0, SS_SRR0(r3)
1282: mtsrr0 r0
1283: lwz r0, SS_SRR1(r3)
1284: mtsrr1 r0
1285:
1286: lwz r0, SS_R0(r3)
1287: lwz r1, SS_R1(r3)
1288: /* critical region for traps(interrupt?) since r1 no longer points
1289: * to bottom of stack. Could be fixed. But interrupts are off (?).
1290: */
1291:
1292: lwz r2, SS_R2(r3)
1293: /* r3 restored last */
1294: lwz r3, SS_R3(r3)
1295:
1296: rfi /* return to calling context */
1297:
1298: .L_syscall_returns_to_user:
1299:
1300: /* If jumping into user space, we should restore the user's
1301: * segment register 0. We jump via a trampoline in physical mode
1302: * TODO NMGS this trampoline code probably isn't needed
1303: */
1304:
1305: lwz r0, SS_CR(r3)
1306: mtcrf 0xFF,r0
1307:
1308: /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
1309: * as arguments */
1310: lwz r0, SS_R1(r3)
1311: mtsprg 1, r0
1312: lwz r0, SS_R2(r3)
1313: mtsprg 2, r0
1314: lwz r0, SS_R3(r3)
1315: mtsprg 3, r0
1316:
1317: lwz r0, SS_R0(r3)
1318: /* Prepare to rfi to the exception exit routine, which is
1319: * in physical address space */
1320: addis r1, 0, ha16(EXT(exception_exit))
1321: addi r1, r1, lo16(EXT(exception_exit))
1322: lwz r1, 0(r1)
1323: mtsrr0 r1
1324: li r1, MSR_VM_OFF
1325: mtsrr1 r1
1326:
1327: lwz r1, PCB_SR0(r3) /* For trampoline */
1328: lwz r2, SS_SRR0(r3) /* For trampoline */
1329: lwz r3, SS_SRR1(r3) /* load the last register... */
1330:
1331: rfi
1332:
1333:
1334:
1335: /*
1336: * thread_exception_return()
1337: *
1338: * Return to user mode directly from within a system call.
1339: */
1340:
1341: ENTRY(thread_exception_return, TAG_NO_FRAME_USED)
1342:
1343: .L_thread_exc_ret_check_ast:
1344:
1345: /* Disable interrupts */
1346: li r3, MSR_SUPERVISOR_INT_OFF
1347: mtmsr r3
1348:
1349: /* Check to see if there's an outstanding AST */
1350: /* We don't bother establishing a call frame even though CHECK_AST
1351: can invoke ast_taken(), because it can just borrow our caller's
1352: frame, given that we're not going to return. */
1353:
1354: bl EXT(check_for_ast)
1355:
1356: .L_exc_ret_no_ast:
1357: /* arriving here, interrupts should be disabled */
1358:
1359: mfsprg r2, 0 /* HACK - need to get around r2 problem */
1360: /* Get the active thread's PCB pointer to restore regs
1361: */
1362:
1363: lwz r31, PP_CPU_DATA(r2)
1364: lwz r31, CPU_ACTIVE_THREAD(r31)
1365: lwz r30, THREAD_PCB(r31)
1366:
1367: /* If the MSR_SYSCALL_MASK isn't set, then we came from a trap,
1368: * so warp into the return_from_trap (thread_return) routine,
1369: * which takes PCB pointer in ARG0, not in r30!
1370: */
1371: lwz r0, SS_SRR1(r30)
1372: mr ARG0, r30 /* Copy pcb pointer into ARG0 in case */
1373:
1374: /* test top half of msr */
1375: srwi r0, r0, 16
1376: cmpwi CR0, r0, MSR_SYSCALL_MASK >> 16
1377: bne- CR0, thread_return
1378:
1379: /* Otherwise, go to thread_syscall return, which requires
1380: * r31 holding current thread, r30 holding current pcb
1381: */
1382:
1383: /*
1384: * restore saved state here
1385: * except for r0-2, r3, r29, r30 and r31 used
1386: * by thread_syscall_return,
1387: */
1388: lwz r4, SS_R4(r30)
1389: lwz r5, SS_R5(r30)
1390: lwz r6, SS_R6(r30)
1391: lwz r7, SS_R7(r30)
1392: lwz r8, SS_R8(r30)
1393: lwz r9, SS_R9(r30)
1394: lwz r10, SS_R10(r30)
1395: lwz r11, SS_R11(r30)
1396: lwz r12, SS_R12(r30)
1397: lwz r13, SS_R13(r30)
1398: lwz r14, SS_R14(r30)
1399: lwz r15, SS_R15(r30)
1400: lwz r16, SS_R16(r30)
1401: lwz r17, SS_R17(r30)
1402: lwz r18, SS_R18(r30)
1403: lwz r19, SS_R19(r30)
1404: lwz r20, SS_R20(r30)
1405: lwz r21, SS_R21(r30)
1406: lwz r22, SS_R22(r30)
1407: lwz r23, SS_R23(r30)
1408: lwz r24, SS_R24(r30)
1409: lwz r25, SS_R25(r30)
1410: lwz r26, SS_R26(r30)
1411: lwz r27, SS_R27(r30)
1412: lwz r28, SS_R28(r30)
1413: lwz r29, SS_R29(r30)
1414:
1415: b .L_thread_syscall_return
1416:
1417:
1418:
1419: /*
1420: * thread_bootstrap_return()
1421: *
1422: */
1423: ENTRY(thread_bootstrap_return, TAG_NO_FRAME_USED)
1424:
1425: /* Disable interrupts */
1426: li r3, MSR_SUPERVISOR_INT_OFF
1427: mtmsr r3
1428:
1429: /* Check for any outstanding ASTs and deal with them */
1430:
1431: bl EXT(check_for_ast)
1432:
1433: /*
1434: ** Restore from AST check
1435: */
1436: mfsprg r2, 0 /* HACK - need to get around r2 problem */
1437: lwz r3, PP_CPU_DATA(r2)
1438: lwz r3, CPU_ACTIVE_THREAD(r3)
1439: lwz r3, THREAD_PCB(r3)
1440:
1441: /* Ok, we're all set, jump to thread_return as if we
1442: * were just coming back from a trap (ie. r3 set up to point to pcb)
1443: */
1444:
1445: b thread_return
1446:
1447:
1448:
1449: /*
1450: * ihandler(type)
1451: *
1452: * Entry: VM switched ON
1453: * Interrupts OFF
1454: * original r1-3 saved in sprg1-3
1455: * original srr0 and srr1 saved in per_proc structure
1456: * original cr saved in per_proc structure
1457: * exception type (r3) saved in per_proc structure
1458: * r1 = scratch
1459: * r2 = virt addr of per_proc_info
1460: * r3 = exception type (one of EXC_...) also in per_proc
1461: *
1462: * gdbhandler is a close derivative, bugfixes to one may apply to the other!
1463: */
1464:
1465: /* Build a saved state structure on the interrupt stack and call
1466: * the routine interrupt()
1467: */
1468:
1469: ENTRY(ihandler, TAG_NO_FRAME_USED) /* What tag should this have?! */
1470:
1471: /*
1472: * get the value of istackptr, if it's zero then we're already on the
1473: * interrupt stack, otherwise it points to a saved_state structure
1474: * at the top of the interrupt stack.
1475: */
1476:
1477: addis r1, 0, ha16(EXT(istackptr))
1478: addi r1, r1, lo16(EXT(istackptr)) /* TODO assumes 1 CPU */
1479: lwz r1, 0(r1)
1480: cmpwi CR0, r1, 0
1481: bne CR0, .L_istackfree
1482:
1483: /* We're already on the interrupt stack, get back the old
1484: * stack pointer and make room for a frame
1485: */
1486:
1487: mfsprg r1, 1 /* recover old stack pointer */
1488:
1489: /* Move below the redzone where the interrupted thread may have
1490: * been saving its state and make room for our saved state structure
1491: */
1492: subi r1, r1, FM_REDZONE+SS_SIZE
1493:
1494:
1495:
1496: .L_istackfree:
1497:
1498: /* Once we reach here, r1 contains the adjusted stack pointer
1499: * where we can store a ppc_saved_state structure.
1500: */
1501:
1502: stw r0, SS_R0(r1)
1503:
1504: mfsprg r0, 1
1505: stw r0, SS_R1(r1)
1506:
1507: mfsprg r0, 2
1508: stw r0, SS_R2(r1)
1509:
1510: mfsprg r0, 3
1511: stw r0, SS_R3(r1)
1512:
1513: stw r4, SS_R4(r1)
1514: stw r5, SS_R5(r1)
1515: stw r6, SS_R6(r1)
1516: stw r7, SS_R7(r1)
1517: stw r8, SS_R8(r1)
1518: stw r9, SS_R9(r1)
1519: stw r10, SS_R10(r1)
1520: stw r11, SS_R11(r1)
1521: stw r12, SS_R12(r1)
1522: stw r13, SS_R13(r1)
1523: stw r14, SS_R14(r1)
1524: stw r15, SS_R15(r1)
1525: stw r16, SS_R16(r1)
1526: stw r17, SS_R17(r1)
1527: stw r18, SS_R18(r1)
1528: stw r19, SS_R19(r1)
1529: stw r20, SS_R20(r1)
1530: stw r21, SS_R21(r1)
1531: stw r22, SS_R22(r1)
1532: stw r23, SS_R23(r1)
1533: stw r24, SS_R24(r1)
1534: stw r25, SS_R25(r1)
1535: stw r26, SS_R26(r1)
1536: stw r27, SS_R27(r1)
1537: stw r28, SS_R28(r1)
1538: stw r29, SS_R29(r1)
1539: stw r30, SS_R30(r1)
1540: stw r31, SS_R31(r1)
1541:
1542: /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
1543: * some of this comes back out from the per-processor structure
1544: */
1545:
1546: lwz r0, PP_SAVE_CR(r2)
1547: stw r0, SS_CR(r1)
1548:
1549: lwz r5, PP_SAVE_SRR0(r2) /* r5 holds srr0 used below */
1550: stw r5, SS_SRR0(r1)
1551:
1552: lwz r0, PP_SAVE_SRR1(r2)
1553: stw r0, SS_SRR1(r1)
1554:
1555: mfxer r0
1556: stw r0, SS_XER(r1)
1557:
1558: mflr r0
1559: stw r0, SS_LR(r1)
1560:
1561: mfctr r0
1562: stw r0, SS_CTR(r1)
1563:
1564: /* Don't bother with MQ for now */
1565:
1566: /* Free the reservation whilst saving SR_COPYIN */
1567:
1568: mfsr r0, SR_COPYIN_NAME
1569: li r4, SS_SR_COPYIN
1570: sync /* bug fix for 3.2 processors */
1571: stwcx. r0, r4, r1
1572: stw r0, SS_SR_COPYIN(r1)
1573:
1574: /* Mark that we're occupying the interrupt stack for sure now */
1575:
1576: addis r4, 0, ha16(EXT(istackptr))
1577: addi r4, r4, lo16(EXT(istackptr))
1578: li r0, 0
1579: stw r0, 0(r4) /* TODO assumes 1 CPU */
1580:
1581: /*
1582: * To summarise, when we reach here, we have filled out
1583: * a ppc_saved_state structure on the interrupt stack, and
1584: * the stack is marked as busy. We now generate a small
1585: * stack frame with backpointers to follow the calling
1586: * conventions. We set up the backpointers to the trapped
1587: * routine allowing us to backtrace.
1588: */
1589:
1590: mr r4, r1 /* Preserve saved_state in ARG1 */
1591: subi r1, r1, FM_SIZE
1592: mfsprg r0, 1
1593: stw r0, FM_BACKPTR(r1) /* point back to previous stackptr */
1594:
1595: #if DEBUG
1596: /* If debugging, we need two frames, the first being a dummy
1597: * which links back to the trapped routine. The second is
1598: * that which the C routine below will need
1599: */
1600:
1601: stw r5, FM_LR_SAVE(r1) /* save old instr ptr as LR value */
1602:
1603: //stwu r1, -FM_SIZE(r1) /* Mak new frame for C routine */
1604: stw r1, -FM_SIZE(r1) /* Mak new frame for C routine */
1605: subi r1, r1, FM_SIZE
1606: #endif /* DEBUG */
1607:
1608: /* r3 still holds the reason for the interrupt */
1609: /* and r4 holds a pointer to the saved state */
1610: mfdsisr ARG2
1611: mfdar ARG3
1612:
1613: bl EXT(interrupt)
1614:
1615: /* interrupt() returns a pointer to the saved state in r3
1616: *
1617: * Ok, back from C. Disable interrupts while we restore things
1618: */
1619:
1620: li r0, MSR_SUPERVISOR_INT_OFF
1621: mtmsr r0
1622:
1623: /* Reload the saved state */
1624:
1625: /* r0-2 will be restored last, use as temp for now */
1626:
1627: /* We don't restore r3-5, these are restored differently too.
1628: * see trampoline code TODO NMGS evaluate need for this
1629: */
1630:
1631: lwz r6, SS_R6(r3)
1632: lwz r7, SS_R7(r3)
1633: lwz r8, SS_R8(r3)
1634: lwz r9, SS_R9(r3)
1635: lwz r10, SS_R10(r3)
1636: lwz r11, SS_R11(r3)
1637: lwz r12, SS_R12(r3)
1638: lwz r13, SS_R13(r3)
1639: lwz r14, SS_R14(r3)
1640: lwz r15, SS_R15(r3)
1641: lwz r16, SS_R16(r3)
1642: lwz r17, SS_R17(r3)
1643: lwz r18, SS_R18(r3)
1644: lwz r19, SS_R19(r3)
1645: lwz r20, SS_R20(r3)
1646: lwz r21, SS_R21(r3)
1647: lwz r22, SS_R22(r3)
1648: lwz r23, SS_R23(r3)
1649: lwz r24, SS_R24(r3)
1650: lwz r25, SS_R25(r3)
1651: lwz r26, SS_R26(r3)
1652: lwz r27, SS_R27(r3)
1653: lwz r28, SS_R28(r3)
1654: lwz r29, SS_R29(r3)
1655: lwz r30, SS_R30(r3)
1656: lwz r31, SS_R31(r3)
1657:
1658: lwz r0, SS_XER(r3)
1659: mtxer r0
1660: lwz r0, SS_LR(r3)
1661: mtlr r0
1662: lwz r0, SS_CTR(r3)
1663: mtctr r0
1664: lwz r0, SS_SR_COPYIN(r3)
1665: isync
1666: mtsr SR_COPYIN_NAME, r0
1667: isync
1668:
1669: /* TODO NMGS don't restore mq since we're not 601-specific enough */
1670:
1671: /* Is this the first interrupt on the stack? */
1672:
1673: addis r4, 0, ha16(EXT(intstack_top_ss))
1674: addi r4, r4, lo16(EXT(intstack_top_ss)) /* TODO assumes 1 CPU */
1675: lwz r4, 0(r4)
1676:
1677: cmp CR0,0, r4, r3
1678: bne CR0, .L_notthelast_interrupt
1679:
1680: /* We're the last frame on the stack. Indicate that
1681: * we've freed up the stack by putting our save state ptr in
1682: * istackptr. Clear reservation at same time.
1683: */
1684:
1685: addis r4, 0, ha16(EXT(istackptr))
1686: addi r4, r4, lo16(EXT(istackptr)) /* TODO assumes 1 CPU */
1687: /* we have to use an indirect store to clear reservation */
1688: sync /* bug fix for 3.2 processors */
1689: stwcx. r3, 0, r4 /* clear reservation */
1690: stw r3, 0(r4)
1691:
1692: /* We're the last frame on the stack.
1693: * Check for ASTs if one of the below is true:
1694: * returning to user mode
1695: * returning to a kloaded server
1696: */
1697:
1698: lwz r4, SS_SRR1(r3)
1699: andi. r4, r4, MASK(MSR_PR)
1700: bne+ .L_check_int_ast /* returning to user level, check */
1701: b .L_no_int_ast /* in kernel, no check */
1702:
1703: .L_check_int_ast:
1704:
1705: /*
1706: * There is a pending AST. Massage things to make it look like
1707: * we took a trap and jump into the trap handler. To do this
1708: * we essentially pretend to return from the interrupt but
1709: * at the last minute jump into the trap handler with an AST
1710: * trap instead of performing an rfi.
1711: */
1712:
1713: lwz r0, SS_R1(r3)
1714: mtsprg 1, r0
1715: lwz r0, SS_R2(r3)
1716: mtsprg 2, r0
1717: lwz r0, SS_R3(r3)
1718: mtsprg 3, r0
1719:
1720: lwz r0, SS_CR(r3) /* store state in per_proc struct */
1721: stw r0, PP_SAVE_CR(r2)
1722: lwz r0, SS_SRR0(r3)
1723: stw r0, PP_SAVE_SRR0(r2)
1724: lwz r0, SS_SRR1(r3)
1725: stw r0, PP_SAVE_SRR1(r2)
1726: li r0, EXC_AST
1727: stw r0, PP_SAVE_EXCEPTION_TYPE(r2)
1728:
1729: lwz r0, SS_R0(r3)
1730: lwz r4, SS_R4(r3)
1731: lwz r5, SS_R5(r3)
1732:
1733: /* r2 remains a constant - virt addr of per_proc_info */
1734: li r3, EXC_AST /* TODO r3 isn't used by thandler -optimise? */
1735: b EXT(thandler) /* hyperspace into AST trap */
1736:
1737: .L_no_int_ast:
1738:
1739: /* We're committed to performing the rfi now.
1740: * If returning to the user space, we should restore the user's
1741: * segment registers. We jump via a trampoline in physical mode
1742: * TODO NMGS this trampoline code probably isn't needed
1743: */
1744: lwz r0, SS_SRR1(r3)
1745: andi. r0, r0, MASK(MSR_PR)
1746: beq- .L_interrupt_returns_to_kspace
1747:
1748: /* TODO NMGS would it be better to store SR0 in saved_state
1749: * rather than perform this expensive lookup?
1750: */
1751: lwz r1, PP_CPU_DATA(r2)
1752: lwz r1, CPU_ACTIVE_THREAD(r1)
1753: lwz r1, THREAD_PCB(r1)
1754: lwz r1, PCB_SR0(r1) /* For trampoline */
1755:
1756: lwz r0, SS_CR(r3)
1757: mtcrf 0xFF,r0
1758:
1759: /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
1760: * as arguments */
1761: lwz r0, SS_R1(r3)
1762: mtsprg 1, r0
1763: lwz r0, SS_R2(r3)
1764: mtsprg 2, r0
1765: lwz r0, SS_R3(r3)
1766: mtsprg 3, r0
1767:
1768: lwz r0, SS_R0(r3)
1769: lwz r4, SS_R4(r3)
1770: lwz r5, SS_R5(r3)
1771:
1772: /* Prepare to rfi to the exception exit routine */
1773: addis r2, 0, ha16(EXT(exception_exit))
1774: addi r2, r2, lo16(EXT(exception_exit))
1775: lwz r2, 0(r2)
1776: mtsrr0 r2
1777: li r2, MSR_VM_OFF
1778: mtsrr1 r2
1779:
1780: /* r1 already loaded above */
1781: lwz r2, SS_SRR0(r3) /* For trampoline */
1782: lwz r3, SS_SRR1(r3) /* load the last register... */
1783:
1784: rfi
1785: .L_interrupt_returns_to_kspace:
1786: .L_notthelast_interrupt:
1787: /* If we're not the last interrupt on the interrupt stack
1788: * life is easier, we don't need to switch back into the
1789: * user's segment. we can simply restore the last registers and rfi
1790: */
1791:
1792: lwz r0, SS_CR(r3)
1793: mtcrf 0xFF,r0
1794: lwz r0, SS_SRR0(r3)
1795: mtsrr0 r0
1796: lwz r0, SS_SRR1(r3)
1797: mtsrr1 r0
1798:
1799: lwz r0, SS_R0(r3)
1800: lwz r1, SS_R1(r3)
1801: lwz r2, SS_R2(r3) /* r2 is a constant - why restore?*/
1802: /* r3 restored last */
1803: lwz r4, SS_R4(r3)
1804: lwz r5, SS_R5(r3)
1805: /* and lastly... */
1806: lwz r3, SS_R3(r3)
1807:
1808: rfi /* return to calling context */
1809:
1810: /*
1811: * gdbhandler(type)
1812: *
1813: * Entry: VM switched ON
1814: * Interrupts OFF
1815: * original r1-3 saved in sprg1-3
1816: * original srr0 and srr1 saved in per_proc structure
1817: * original cr saved in per_proc structure
1818: * exception type (r3) saved in per_proc structure
1819: * r1 = scratch
1820: * r2 = virt addr of per_proc_info
1821: * r3 = exception type (one of EXC_...) also in per_proc
1822: *
1823: * Closely based on ihandler - bugfixes to one may apply to the other!
1824: */
1825:
1826: /* build a saved state structure on the debugger stack and call
1827: * the routine enterDebugger()
1828: */
1829:
1830: ENTRY(gdbhandler, TAG_NO_FRAME_USED) /* What tag should this have?! */
1831: #if DEBUG
1832: /*
1833: * get the value of gdbstackptr, if it's zero then we're already on the
1834: * debugger stack, otherwise it points to a saved_state structure
1835: * at the top of the debugger stack.
1836: */
1837:
1838: addis r1, 0, ha16(EXT(gdbstackptr))
1839: addi r1, r1, lo16(EXT(gdbstackptr)) /* TODO assumes 1 CPU */
1840: lwz r1, 0(r1)
1841: cmpwi CR0, r1, 0
1842: bne CR0, .L_gdbstackfree
1843:
1844: /* We're already on the debugger stack, get back the old
1845: * stack pointer and make room for a frame
1846: */
1847:
1848: mfsprg r1, 1 /* recover old stack pointer */
1849:
1850: /* Move below the redzone where the interrupted thread may have
1851: * been saving its state and make room for our saved state structure
1852: */
1853: subi r1, r1, FM_REDZONE+SS_SIZE
1854:
1855: /* TODO NMGS - how about checking for stack overflow, huh?! */
1856:
1857: .L_gdbstackfree:
1858:
1859: /* Once we reach here, r1 contains the adjusted stack pointer
1860: * where we can store a ppc_saved_state structure.
1861: */
1862:
1863: stw r0, SS_R0(r1)
1864:
1865: mfsprg r0, 1
1866: stw r0, SS_R1(r1)
1867:
1868: mfsprg r0, 2
1869: stw r0, SS_R2(r1)
1870:
1871: mfsprg r0, 3
1872: stw r0, SS_R3(r1)
1873:
1874: stw r4, SS_R4(r1)
1875: stw r5, SS_R5(r1)
1876: stw r6, SS_R6(r1)
1877: stw r7, SS_R7(r1)
1878: stw r8, SS_R8(r1)
1879: stw r9, SS_R9(r1)
1880: stw r10, SS_R10(r1)
1881: stw r11, SS_R11(r1)
1882: stw r12, SS_R12(r1)
1883: stw r13, SS_R13(r1)
1884: stw r14, SS_R14(r1)
1885: stw r15, SS_R15(r1)
1886: stw r16, SS_R16(r1)
1887: stw r17, SS_R17(r1)
1888: stw r18, SS_R18(r1)
1889: stw r19, SS_R19(r1)
1890: stw r20, SS_R20(r1)
1891: stw r21, SS_R21(r1)
1892: stw r22, SS_R22(r1)
1893: stw r23, SS_R23(r1)
1894: stw r24, SS_R24(r1)
1895: stw r25, SS_R25(r1)
1896: stw r26, SS_R26(r1)
1897: stw r27, SS_R27(r1)
1898: stw r28, SS_R28(r1)
1899: stw r29, SS_R29(r1)
1900: stw r30, SS_R30(r1)
1901: stw r31, SS_R31(r1)
1902:
1903: /* Save more state - cr,xer,lr,ctr,srr0,srr1,mq
1904: * some of this comes back out from the per-processor structure
1905: */
1906:
1907: lwz r0, PP_SAVE_CR(r2)
1908: stw r0, SS_CR(r1)
1909:
1910: lwz r5, PP_SAVE_SRR0(r2) /* r5 holds srr0 used below */
1911: stw r5, SS_SRR0(r1)
1912:
1913: lwz r0, PP_SAVE_SRR1(r2)
1914: stw r0, SS_SRR1(r1)
1915:
1916: mfxer r0
1917: stw r0, SS_XER(r1)
1918:
1919: mflr r0
1920: stw r0, SS_LR(r1)
1921:
1922: mfctr r0
1923: stw r0, SS_CTR(r1)
1924:
1925: /* Don't bother with MQ for now */
1926:
1927: /* Free the reservation whilst saving SR_COPYIN */
1928:
1929: mfsr r0, SR_COPYIN_NAME
1930: li r4, SS_SR_COPYIN
1931: sync /* bug fix for 3.2 processors */
1932: stwcx. r0, r4, r1
1933: stw r0, SS_SR_COPYIN(r1)
1934:
1935: /* Mark that we're occupying the gdb stack for sure now */
1936:
1937: addis r4, 0, ha16(EXT(gdbstackptr))
1938: addi r4, r4, lo16(EXT(gdbstackptr))
1939: li r0, 0
1940: stw r0, 0(r4) /* TODO assumes 1 CPU */
1941:
1942: /*
1943: * To summarise, when we reach here, we have filled out
1944: * a ppc_saved_state structure on the gdb stack, and
1945: * the stack is marked as busy. We now generate a small
1946: * stack frame with backpointers to follow the calling
1947: * conventions. We set up the backpointers to the trapped
1948: * routine allowing us to backtrace.
1949: *
1950: * This probably isn't needed in gdbhandler, but I've left
1951: * it in place
1952: */
1953:
1954: mr r4, r1 /* Preserve saved_state in ARG1 */
1955: subi r1, r1, FM_SIZE
1956: mfsprg r0, 1
1957: stw r0, FM_BACKPTR(r1) /* point back to previous stackptr */
1958:
1959: #if DEBUG
1960: /* If debugging, we need two frames, the first being a dummy
1961: * which links back to the trapped routine. The second is
1962: * that which the C routine below will need
1963: * TODO NMGS debugging call frame not correct yet
1964: */
1965: stw r5, FM_LR_SAVE(r1) /* save old instr ptr as LR value */
1966: //stwu r1, -FM_SIZE(r1) /* point back to previous frame */
1967: stw r1, -FM_SIZE(r1) /* point back to previous frame */
1968: subi r1, r1, FM_SIZE
1969: #endif /* DEBUG */
1970:
1971: /* r3 still holds the reason for the trap */
1972: /* and r4 holds a pointer to the saved state */
1973:
1974: mfdsisr ARG2
1975:
1976: bl EXT(enterDebugger)
1977:
1978: /* enterDebugger() returns a pointer to the saved state in r3
1979: *
1980: * Ok, back from C. Disable interrupts while we restore things
1981: */
1982:
1983: li r0, MSR_SUPERVISOR_INT_OFF
1984: mtmsr r0
1985:
1986: /* Reload the saved state */
1987:
1988: /* r0-2 will be restored last, use as temp for now */
1989:
1990: /* We do not restore r3-5, these are restored differently too.
1991: * see trampoline code TODO NMGS evaluate need for this
1992: */
1993:
1994: lwz r6, SS_R6(r3)
1995: lwz r7, SS_R7(r3)
1996: lwz r8, SS_R8(r3)
1997: lwz r9, SS_R9(r3)
1998: lwz r10, SS_R10(r3)
1999: lwz r11, SS_R11(r3)
2000: lwz r12, SS_R12(r3)
2001: lwz r13, SS_R13(r3)
2002: lwz r14, SS_R14(r3)
2003: lwz r15, SS_R15(r3)
2004: lwz r16, SS_R16(r3)
2005: lwz r17, SS_R17(r3)
2006: lwz r18, SS_R18(r3)
2007: lwz r19, SS_R19(r3)
2008: lwz r20, SS_R20(r3)
2009: lwz r21, SS_R21(r3)
2010: lwz r22, SS_R22(r3)
2011: lwz r23, SS_R23(r3)
2012: lwz r24, SS_R24(r3)
2013: lwz r25, SS_R25(r3)
2014: lwz r26, SS_R26(r3)
2015: lwz r27, SS_R27(r3)
2016: lwz r28, SS_R28(r3)
2017: lwz r29, SS_R29(r3)
2018: lwz r30, SS_R30(r3)
2019: lwz r31, SS_R31(r3)
2020:
2021: lwz r0, SS_XER(r3)
2022: lwz r5, SS_LR(r3)
2023: mtxer r0
2024: mtlr r5
2025: lwz r0, SS_CTR(r3)
2026: lwz r5, SS_SR_COPYIN(r3)
2027: mtctr r0
2028: isync
2029: mtsr SR_COPYIN_NAME, r5
2030: isync
2031:
2032: /* TODO NMGS don't restore mq since we're not 601-specific enough */
2033:
2034: /* Is this the first frame on the stack? */
2035:
2036: addis r4, 0, ha16(EXT(gdbstack_top_ss))
2037: addi r4, r4, lo16(EXT(gdbstack_top_ss)) /* TODO assumes 1 CPU */
2038: lwz r4, 0(r4)
2039:
2040: cmp CR0, 0, r4, r3
2041: bne CR0, .L_notthelast_gdbframe
2042:
2043: /* We're the last frame on the stack. Indicate that
2044: * we've freed up the stack by putting our save state ptr in
2045: * istackptr. Clear reservation at same time.
2046: */
2047: addis r4, 0, ha16(EXT(gdbstackptr))
2048: addi r4, r4, lo16(EXT(gdbstackptr)) /* TODO assumes 1 CPU */
2049: /* we have to use an indirect store to clear reservation */
2050: sync /* bug fix for 3.2 processors */
2051: stwcx. r3, 0, r4 /* clear reservation */
2052: stw r3, 0(r4)
2053:
2054: /* We may be returning to something in the kernel space.
2055: * If we are, we can skip the trampoline and just rfi,
2056: * since we don't want to restore the user's space regs
2057: */
2058:
2059: lwz r0, SS_SRR1(r3)
2060: andi. r0, r0, MASK(MSR_PR)
2061: beq- .L_gdb_ret_to_kspace
2062:
2063: /* If jumping into user space, we should restore the user's
2064: * segment register 0. We jump via a trampoline in physical mode
2065: * TODO NMGS this trampoline code probably isn't needed
2066: */
2067:
2068: /* TODO NMGS would it be better to store SR0 in saved_state
2069: * rather than perform this expensive lookup?
2070: */
2071: lwz r1, PP_CPU_DATA(r2)
2072: lwz r1, CPU_ACTIVE_THREAD(r1)
2073: lwz r1, THREAD_PCB(r1)
2074: lwz r1, PCB_SR0(r1) /* For trampoline */
2075:
2076: #if DEBUG
2077: /* Assert that PCB_SR0 is not in kernel space */
2078: rlwinm. r0, r1, 0, 8, 27
2079: bne+ .Lbp_skip
2080: BREAKPOINT_TRAP
2081: .Lbp_skip:
2082: #endif /* DEBUG */
2083:
2084: lwz r0, SS_CR(r3)
2085: mtcrf 0xFF,r0
2086:
2087: /* the trampoline code takes r1-r3 from sprg1-3, and uses r1-3
2088: * as arguments
2089: */
2090: lwz r0, SS_R1(r3)
2091: mtsprg 1, r0
2092: lwz r0, SS_R2(r3)
2093: mtsprg 2, r0
2094: lwz r0, SS_R3(r3)
2095: mtsprg 3, r0
2096:
2097: lwz r0, SS_R0(r3)
2098: lwz r4, SS_R4(r3)
2099: lwz r5, SS_R5(r3)
2100:
2101: /* Prepare to rfi to the exception exit routine */
2102: addis r2, 0, ha16(EXT(exception_exit))
2103: addi r2, r2, lo16(EXT(exception_exit))
2104: lwz r2, 0(r2)
2105: mtsrr0 r2
2106: li r2, MSR_VM_OFF
2107: mtsrr1 r2
2108:
2109: /* r1 already loaded above */
2110: lwz r2, SS_SRR0(r3) /* For trampoline */
2111: lwz r3, SS_SRR1(r3) /* load the last register... */
2112:
2113:
2114: rfi
2115:
2116: .L_gdb_ret_to_kspace:
2117: .L_notthelast_gdbframe:
2118: /* If we're not the last frame on the stack
2119: * life is easier, we don't need to switch back into the
2120: * user's segment. we can simply restore the last registers and rfi
2121: */
2122:
2123: lwz r0, SS_CR(r3)
2124: mtcrf 0xFF,r0
2125: lwz r0, SS_SRR0(r3)
2126: mtsrr0 r0
2127: lwz r0, SS_SRR1(r3)
2128: mtsrr1 r0
2129:
2130: lwz r0, SS_R0(r3)
2131: lwz r1, SS_R1(r3)
2132: lwz r2, SS_R2(r3) /* r2 is a constant - why restore?*/
2133: /* r3 restored last */
2134: lwz r4, SS_R4(r3)
2135: lwz r5, SS_R5(r3)
2136: /* and lastly... */
2137: lwz r3, SS_R3(r3)
2138:
2139: rfi /* return to calling context */
2140: #endif /* DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.