|
|
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.