|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: ! 26: /* Low level routines dealing with exception entry and exit. ! 27: * There are various types of exception: ! 28: * ! 29: * Interrupt, trap, system call and debugger entry. Each has it's own ! 30: * handler since the state save routine is different for each. The ! 31: * code is very similar (a lot of cut and paste). ! 32: * ! 33: * The code for the FPU disabled handler (lazy fpu) is in cswtch.s ! 34: */ ! 35: ! 36: #include <debug.h> ! 37: #include <mach_assert.h> ! 38: #include <mach/exception_types.h> ! 39: #include <mach/ppc/vm_param.h> ! 40: ! 41: #include <assym.s> ! 42: ! 43: #include <ppc/asm.h> ! 44: #include <ppc/proc_reg.h> ! 45: #include <ppc/trap.h> ! 46: #include <ppc/exception.h> ! 47: #include <ppc/spl.h> ! 48: ! 49: ! 50: #define VERIFYSAVE 0 ! 51: #define FPVECDBG 0 ! 52: ! 53: /* ! 54: * thandler(type) ! 55: * ! 56: * ENTRY: VM switched ON ! 57: * Interrupts OFF ! 58: * R3 contains exception code ! 59: * R4 points to the saved context (virtual address) ! 60: * Everything is saved in savearea ! 61: */ ! 62: ! 63: /* ! 64: * If pcb.ksp == 0 then the kernel stack is already busy, ! 65: * we save ppc_saved state below the current stack pointer, ! 66: * leaving enough space for the `red zone' in case the ! 67: * trapped thread was in the middle of saving state below ! 68: * its stack pointer. ! 69: * ! 70: * otherwise we save a ppc_saved_state in the pcb, and switch to ! 71: * the kernel stack (setting pcb.ksp to 0) ! 72: * ! 73: * on return, we do the reverse, the last state is popped from the pcb ! 74: * and pcb.ksp is set to the top of stack ! 75: */ ! 76: ! 77: ! 78: #if DEBUG ! 79: ! 80: /* TRAP_SPACE_NEEDED is the space assumed free on the kernel stack when ! 81: * another trap is taken. We need at least enough space for a saved state ! 82: * structure plus two small backpointer frames, and we add a few ! 83: * hundred bytes for the space needed by the C (which may be less but ! 84: * may be much more). We're trying to catch kernel stack overflows :-) ! 85: */ ! 86: ! 87: #define TRAP_SPACE_NEEDED FM_REDZONE+(2*FM_SIZE)+256 ! 88: ! 89: #endif /* DEBUG */ ! 90: ! 91: .text ! 92: ! 93: ENTRY(thandler, TAG_NO_FRAME_USED) /* What tag should this have?! */ ! 94: ! 95: mfsprg r25,0 /* Get the per_proc */ ! 96: ! 97: lwz r1,PP_ISTACKPTR(r25) ; Get interrupt stack pointer ! 98: ! 99: ! 100: lwz r6,PP_CPU_DATA(r25) /* Get point to cpu specific data */ ! 101: cmpwi cr0,r1,0 ; Are we on interrupt stack? ! 102: lwz r6,CPU_ACTIVE_THREAD(r6) /* Get the pointer to the currently active thread */ ! 103: beq- cr0,EXT(ihandler) ; Yes, not allowed except when debugger ! 104: ; is active. We will let the ihandler do this... ! 105: lwz r9,THREAD_TOP_ACT(r6) /* Point to the active activation */ ! 106: lwz r26,ACT_MACT_BDA(r9) /* Pick up the pointer to the blue box data area */ ! 107: lwz r8,ACT_MACT_PCB(r9) /* Get the last savearea used */ ! 108: mr. r26,r26 /* Do we have Blue Box Assist active? */ ! 109: lwz r1,ACT_MACT_KSP(r9) /* Get the stack */ ! 110: bnel- checkassist /* See if we should assist this */ ! 111: stw r4,ACT_MACT_PCB(r9) /* Point to our savearea */ ! 112: stw r8,SAVprev(r4) /* Queue the new save area in the front */ ! 113: ! 114: #if VERIFYSAVE ! 115: bl versave ; (TEST/DEBUG) ! 116: #endif ! 117: ! 118: cmpwi cr1,r1, 0 /* zero implies already on kstack */ ! 119: stw r9,SAVact(r4) /* Point the savearea at its activation */ ! 120: bne cr1,.L_kstackfree /* This test is also used below */ ! 121: lwz r1,saver1(r4) /* Get the stack at 'rupt time */ ! 122: ! 123: ! 124: /* On kernel stack, allocate stack frame and check for overflow */ ! 125: #if DEBUG ! 126: /* ! 127: * Test if we will overflow the Kernel Stack. We ! 128: * check that there is at least TRAP_SPACE_NEEDED bytes ! 129: * free on the kernel stack ! 130: */ ! 131: ! 132: lwz r7,THREAD_KERNEL_STACK(r6) ! 133: addi r7,r7,TRAP_SPACE_NEEDED ! 134: cmp cr0,r1,r7 ! 135: bng- EXT(ihandler) ! 136: #endif /* DEBUG */ ! 137: ! 138: subi r1,r1,FM_REDZONE /* Back up stack and leave room for a red zone */ ! 139: ! 140: .L_kstackfree: ! 141: #if 0 ! 142: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 143: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 144: sc /* (TEST/DEBUG) */ ! 145: #endif ! 146: lwz r7,savesrr1(r4) /* Pick up the entry MSR */ ! 147: mfmsr r8 /* Get the kernel's MSR state */ ! 148: li r0,0 /* Make this 0 */ ! 149: rlwimi r8,r7,0,MSR_EE_BIT,MSR_EE_BIT /* Copy in the interrupt mask from the save area */ ! 150: ! 151: beq cr1,.L_state_on_kstack /* using above test for pcb/stack */ ! 152: ! 153: stw r0,ACT_MACT_KSP(r9) /* Show that we have taken the stack */ ! 154: ! 155: .L_state_on_kstack: ! 156: rlwinm. r6,r7,0,MSR_VEC_BIT,MSR_VEC_BIT ; Was vector on? ! 157: lwz r6,saver1(r4) /* Grab interrupt time stack */ ! 158: beq+ tvecoff ; Vector off, do not save vrsave... ! 159: mfspr r7,vrsave ; Get the VRSAVE register ! 160: stw r7,liveVRS(r25) ; Set the live value ! 161: ! 162: tvecoff: subi r1,r1,FM_SIZE /* Push a header onto the current stack */ ! 163: stw r6,FM_BACKPTR(r1) /* Link backwards */ ! 164: ! 165: #if DEBUG ! 166: /* If debugging, we need two frames, the first being a dummy ! 167: * which links back to the trapped routine. The second is ! 168: * that which the C routine below will need ! 169: */ ! 170: lwz r7,savesrr0(r4) /* Get the point of interruption */ ! 171: stw r7,FM_LR_SAVE(r1) /* save old instr ptr as LR value */ ! 172: stwu r1, -FM_SIZE(r1) /* and make new frame */ ! 173: #endif /* DEBUG */ ! 174: ! 175: ! 176: /* call trap handler proper, with ! 177: * ARG0 = type (not yet, holds pcb ptr) ! 178: * ARG1 = saved_state ptr (already there) ! 179: * ARG2 = dsisr (already there) ! 180: * ARG3 = dar (already there) ! 181: */ ! 182: ! 183: lwz r3,saveexception(r4) /* Get the exception code */ ! 184: lwz r5,savedsisr(r4) /* Get the saved DSISR */ ! 185: lwz r6,savedar(r4) /* Get the DAR */ ! 186: ! 187: mtmsr r8 /* Turn on interrupts if enabled at 'rupt time */ ! 188: ! 189: /* syscall exception might warp here if there's nothing left ! 190: * to do except generate a trap ! 191: */ ! 192: ! 193: .L_call_trap: ! 194: #if 0 ! 195: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 196: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 197: sc /* (TEST/DEBUG) */ ! 198: #endif ! 199: ! 200: bl EXT(trap) ! 201: ! 202: /* ! 203: * Ok, return from C function ! 204: * ! 205: * This is also the point where new threads come when they are created. ! 206: * The new thread is setup to look like a thread that took an ! 207: * interrupt and went immediatly into trap. ! 208: * ! 209: */ ! 210: ! 211: thread_return: ! 212: ! 213: lwz r4,SAVprev(r3) /* Pick up the previous savearea */ ! 214: mfmsr r7 /* Get the MSR */ ! 215: lwz r11,SAVflags(r3) /* Get the flags of the current savearea */ ! 216: rlwinm r7,r7,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear the interrupt enable mask */ ! 217: mtmsr r7 /* Disable for interrupts */ ! 218: ! 219: mfsprg r10,0 /* Restore the per_proc info */ ! 220: ! 221: lwz r8,savesrr1(r3) ; Get the MSR we are going to ! 222: lwz r1,PP_CPU_DATA(r10) /* Get the CPU data area */ ! 223: rlwinm r11,r11,0,15,13 /* Clear the syscall flag */ ! 224: lwz r1,CPU_ACTIVE_THREAD(r1) /* and the active thread */ ! 225: rlwinm. r8,r8,0,MSR_PR_BIT,MSR_PR_BIT ; Are we going to the user? ! 226: lwz r8,THREAD_TOP_ACT(r1) /* Now find the current activation */ ! 227: stw r11,SAVflags(r3) /* Save back the flags (with reset stack cleared) */ ! 228: ! 229: #if 0 ! 230: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 231: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 232: sc /* (TEST/DEBUG) */ ! 233: #endif ! 234: stw r4,ACT_MACT_PCB(r8) /* Point to the previous savearea (or 0 if none) */ ! 235: ! 236: beq- chkfac ; We are not leaving the kernel yet... ! 237: ! 238: lwz r5,THREAD_KERNEL_STACK(r1) /* Get the base pointer to the stack */ ! 239: addi r5,r5,KERNEL_STACK_SIZE-FM_SIZE /* Reset to empty */ ! 240: stw r5,ACT_MACT_KSP(r8) /* Save the empty stack pointer */ ! 241: b chkfac /* Go end it all... */ ! 242: ! 243: ! 244: ! 245: /* ! 246: * shandler(type) ! 247: * ! 248: * ENTRY: VM switched ON ! 249: * Interrupts OFF ! 250: * R3 contains exception code ! 251: * R4 points to the saved context (virtual address) ! 252: * Everything is saved in savearea ! 253: */ ! 254: ! 255: /* ! 256: * If pcb.ksp == 0 then the kernel stack is already busy, ! 257: * this is an error - jump to the debugger entry ! 258: * ! 259: * otherwise depending upon the type of ! 260: * syscall, look it up in the kernel table ! 261: * or pass it to the server. ! 262: * ! 263: * on return, we do the reverse, the state is popped from the pcb ! 264: * and pcb.ksp is set to the top of stack. ! 265: */ ! 266: ! 267: ENTRY(shandler, TAG_NO_FRAME_USED) ! 268: ! 269: mfsprg r25,0 /* Get the per proc area */ ! 270: lwz r0,saver0(r4) /* Get the original syscall number */ ! 271: lwz r17,PP_ISTACKPTR(r25) ; Get interrupt stack pointer ! 272: andi. r15,r0,0x7000 /* Isolate the fastpath code */ ! 273: lwz r16,PP_CPU_DATA(r25) /* Assume we need this */ ! 274: mr. r17,r17 ; Are we on interrupt stack? ! 275: lwz r7,savesrr1(r4) ; Get the SRR1 value ! 276: beq- EXT(ihandler) ; On interrupt stack, not allowed... ! 277: lwz r16,CPU_ACTIVE_THREAD(r16) /* Get the thread pointer */ ! 278: ! 279: ! 280: rlwinm. r6,r7,0,MSR_VEC_BIT,MSR_VEC_BIT ; Was vector on? ! 281: beq+ svecoff ; Vector off, do not save vrsave... ! 282: mfspr r7,vrsave ; Get the VRSAVE register ! 283: stw r7,liveVRS(r25) ; Set the live value ! 284: ! 285: svecoff: lwz r13,THREAD_TOP_ACT(r16) /* Pick up the active thread */ ! 286: cmplwi r15,0x7000 /* Do we have a fast path trap? */ ! 287: lwz r14,ACT_MACT_PCB(r13) /* Now point to the PCB */ ! 288: beql+ fastpath /* We think it's a fastpath... */ ! 289: ! 290: lwz r1,ACT_MACT_KSP(r13) /* Get the kernel stack pointer */ ! 291: #if DEBUG ! 292: mr. r1,r1 /* Are we already on the kernel stack? */ ! 293: li r3,T_SYSTEM_CALL /* Yup, pretend we had an interrupt... */ ! 294: beq- EXT(ihandler) /* Bad boy, bad boy... What'cha gonna do when they come for you? */ ! 295: #endif /* DEBUG */ ! 296: ! 297: stw r4,ACT_MACT_PCB(r13) /* Point to our savearea */ ! 298: li r0,0 /* Clear this out */ ! 299: stw r14,SAVprev(r4) /* Queue the new save area in the front */ ! 300: stw r13,SAVact(r4) /* Point the savearea at its activation */ ! 301: ! 302: #if VERIFYSAVE ! 303: bl versave ; (TEST/DEBUG) ! 304: #endif ! 305: ! 306: mr r30,r4 /* Save pointer to the new context savearea */ ! 307: lwz r15,saver1(r4) /* Grab interrupt time stack */ ! 308: stw r0,ACT_MACT_KSP(r13) /* Mark stack as busy with 0 val */ ! 309: stw r15,FM_BACKPTR(r1) /* Link backwards */ ! 310: ! 311: #if DEBUG ! 312: /* If debugging, we need two frames, the first being a dummy ! 313: * which links back to the trapped routine. The second is ! 314: * that which the C routine below will need ! 315: */ ! 316: lwz r8,savesrr0(r30) /* Get the point of interruption */ ! 317: stw r8,FM_LR_SAVE(r1) /* save old instr ptr as LR value */ ! 318: stwu r1, -FM_SIZE(r1) /* and make new frame */ ! 319: #endif /* DEBUG */ ! 320: ! 321: mfmsr r0 /* Get the MSR */ ! 322: lwz r15,SAVflags(r4) /* Get the savearea flags */ ! 323: ori r0,r0,lo16(MASK(MSR_EE)) /* Turn on interruption enabled bit */ ! 324: oris r15,r15,SAVsyscall >> 16 /* Mark that it this is a syscall */ ! 325: stwu r1,-(FM_SIZE+ARG_SIZE)(r1) /* Make a stack frame */ ! 326: stw r15,SAVflags(r30) /* Save syscall marker */ ! 327: ! 328: mtmsr r0 /* Enable interruptions */ ! 329: ! 330: ! 331: /* Call a function that can print out our syscall info */ ! 332: /* Note that we don't care about any volatiles yet */ ! 333: mr r4,r30 ! 334: bl EXT(syscall_trace) ! 335: ! 336: lwz r0,saver0(r30) /* Get the system call selector */ ! 337: mr. r0,r0 /* What kind is it? */ ! 338: blt- .L_kernel_syscall /* -ve syscall - go to kernel */ ! 339: /* +ve syscall - go to server */ ! 340: cmpwi cr0, r0,0x7FFA ! 341: beq- .L_notify_interrupt_syscall ! 342: /* +ve syscall - go to server */ ! 343: #ifdef MACH_BSD ! 344: mr r3,r30 /* Get PCB/savearea */ ! 345: lwz r4,saver4(r30) /* Restore r4 */ ! 346: lwz r5,saver5(r30) /* Restore r5 */ ! 347: lwz r6,saver6(r30) /* Restore r6 */ ! 348: lwz r7,saver7(r30) /* Restore r7 */ ! 349: lwz r8,saver8(r30) /* Restore r8 */ ! 350: lwz r9,saver9(r30) /* Restore r9 */ ! 351: lwz r10,saver10(r30) /* Restore r10 */ ! 352: bl EXT(unix_syscall) /* Check out unix... */ ! 353: #endif ! 354: ! 355: .L_call_server_syscall_exception: ! 356: li r3,EXC_SYSCALL /* doexception(EXC_SYSCALL, num, 1) */ ! 357: ! 358: .L_call_server_exception: ! 359: mr r4,r0 /* Set syscall selector */ ! 360: li r5,1 ! 361: b EXT(doexception) /* Go away, never to return... */ ! 362: ! 363: /* The above, but with EXC_MACH_SYSCALL */ ! 364: .L_call_server_mach_syscall: ! 365: li r3,EXC_MACH_SYSCALL ! 366: b .L_call_server_exception /* Join the common above... */ ! 367: ! 368: .L_notify_interrupt_syscall: ! 369: lwz r3,saver3(r30) ; Get the new PC address to pass in ! 370: bl EXT(syscall_notify_interrupt) ! 371: b .L_syscall_return ! 372: ! 373: ! 374: ! 375: /* Once here, we know that the syscall was -ve ! 376: * we should still have r1=ksp, ! 377: * r16 = pointer to current thread, ! 378: * r13 = pointer to top activation, ! 379: * r0 = syscall number ! 380: * r30 = pointer to saved state (in pcb) ! 381: */ ! 382: .L_kernel_syscall: ! 383: ! 384: /* ! 385: * Are we allowed to do mach system calls? ! 386: */ ! 387: ! 388: addis r31,0,HIGH_ADDR(EXT(realhost)) ! 389: lwz r29,ACT_MACH_EXC_PORT(r13) /* See if we have one of these ports */ ! 390: ori r31,r31,LOW_ADDR(EXT(realhost)) ! 391: lwz r31,HOST_SELF(r31) /* Find ourselves */ ! 392: ! 393: /* If thread_exception_port == realhost->hostname do syscall */ ! 394: cmpw cr1,r29,r31 /* Are we the host? */ ! 395: mr. r29,r29 /* Is our port null? */ ! 396: beq+ cr1,.L_syscall_do_mach_syscall /* We are the host... */ ! 397: bne+ .L_call_server_mach_syscall /* Not host and not null, call the handler... */ ! 398: ! 399: lwz r29,ACT_TASK(r13) /* Get our task */ ! 400: lwz r29,TASK_MACH_EXC_PORT(r29) /* Now get the exception port for it */ ! 401: ! 402: /* If task_exception_port == realhost->hostname do syscall */ ! 403: cmpw cr1,r29,r31 /* Is this the host? */ ! 404: mr. r29,r29 /* Is it null? */ ! 405: beq+ cr1,.L_syscall_do_mach_syscall /* We are the host... */ ! 406: bne+ .L_call_server_mach_syscall /* Not host and not null, call the handler... */ ! 407: ! 408: /* else the syscall has failed, treat as priv instruction trap, ! 409: * set SRR1 to indicate privileged instruction ! 410: */ ! 411: ! 412: li r3,T_PROGRAM ! 413: lwz r29,savesrr1(r30) ! 414: mr r4,r30 ! 415: li r5,0 ! 416: oris r29,r29,MASK(SRR1_PRG_PRV_INS)>>16 ! 417: li r6,0 ! 418: stw r29,savesrr1(r30) ! 419: b .L_call_trap ! 420: ! 421: /* When here, we know that we're allowed to do a mach syscall, ! 422: * and still have syscall number in r0, pcb pointer in r30 ! 423: */ ! 424: ! 425: .L_syscall_do_mach_syscall: ! 426: neg r31, r0 /* Make number +ve and put in r31*/ ! 427: ! 428: #ifdef MACHO_SYSCALL_BEGIN ! 429: /* ! 430: * There's a bit of a problem with supporting both ELF and ! 431: * MACHO generated binaries. Each has their own location for ! 432: * storing the 8th and above arguments on the stack. ! 433: * ! 434: * Current the MACHO generated system calls have a BIT ! 435: * set telling the kernel its a MACHO style ABI. ! 436: */ ! 437: ! 438: li r29,MACHO_SYSCALL_BEGIN ! 439: and. r25,r31,r29 ! 440: beq not_macho ! 441: ! 442: andc r31,r31,r29 /* Clear the bit to get real trap */ ! 443: li r25,FM_MACHO_ARG0-4 ! 444: b continue2 ! 445: ! 446: not_macho: ! 447: li r25,FM_ELF_ARG0-4 ! 448: ! 449: continue2: ! 450: #endif ! 451: ! 452: /* If out of range, call server with syscall exception */ ! 453: addis r29, 0, HIGH_CADDR(EXT(mach_trap_count)) ! 454: addi r29, r29, LOW_ADDR(EXT(mach_trap_count)) ! 455: lwz r29, 0(r29) ! 456: ! 457: cmp cr0, r31, r29 ! 458: bge- cr0, .L_call_server_syscall_exception ! 459: ! 460: addis r29, 0, HIGH_CADDR(EXT(mach_trap_table)) ! 461: addi r29, r29, LOW_ADDR(EXT(mach_trap_table)) ! 462: ! 463: /* multiply the trap number to get offset into table */ ! 464: slwi r31, r31, MACH_TRAP_OFFSET_POW2 ! 465: ! 466: /* r31 now holds offset into table of our trap entry, ! 467: * add on the table base, and it then holds pointer to entry ! 468: */ ! 469: add r31, r31, r29 ! 470: ! 471: /* If the function is kern_invalid, prepare to send an exception. ! 472: This is messy, but parallels the x86. We need it for task_by_pid, ! 473: at least. */ ! 474: lis r29, HIGH_CADDR(EXT(kern_invalid)) ! 475: addi r29, r29, LOW_ADDR(EXT(kern_invalid)) ! 476: lwz r0, MACH_TRAP_FUNCTION(r31) ! 477: cmp cr0, r0, r29 ! 478: beq- .L_call_server_syscall_exception ! 479: ! 480: /* get arg count. If argc > 8 then not all args were in regs, ! 481: * so we must perform copyin. ! 482: */ ! 483: lwz r29, MACH_TRAP_ARGC(r31) ! 484: cmpwi cr0, r29, 8 ! 485: ble+ .L_syscall_got_args ! 486: ! 487: /* argc > 8 - perform a copyin */ ! 488: /* if the syscall came from kernel space, we can just copy */ ! 489: ! 490: lwz r0,savesrr1(r30) /* Pick up exception time MSR */ ! 491: andi. r0,r0,MASK(MSR_PR) /* Check the priv bit */ ! 492: bne+ .L_syscall_arg_copyin /* We're not priviliged... */ ! 493: ! 494: /* we came from a privilaged task, just do a copy */ ! 495: /* get user's stack pointer */ ! 496: ! 497: lwz r28,saver1(r30) /* Get the stack pointer */ ! 498: ! 499: subi r29,r29,8 /* Get the number of arguments to copy */ ! 500: ! 501: #ifdef MACHO_SYSCALL_BEGIN ! 502: add r28,r28,r25 /* Point to source - 4 */ ! 503: #else ! 504: addi r28,r28,COPYIN_ARG0_OFFSET-4 /* Point to source - 4 */ ! 505: #endif ! 506: addi r27,r1,FM_ARG0-4 /* Point to sink - 4 */ ! 507: ! 508: .L_syscall_copy_word_loop: ! 509: addic. r29,r29,-1 /* Count down the number of arguments left */ ! 510: lwz r0,4(r28) /* Pick up the argument from the stack */ ! 511: addi r28,r28,4 /* Point to the next source */ ! 512: stw r0,4(r27) /* Store the argument */ ! 513: addi r27,r27,4 /* Point to the next sink */ ! 514: bne+ .L_syscall_copy_word_loop /* Move all arguments... */ ! 515: b .L_syscall_got_args /* Go call it now... */ ! 516: ! 517: ! 518: /* we came from a user task, pay the price of a real copyin */ ! 519: /* set recovery point */ ! 520: ! 521: .L_syscall_arg_copyin: ! 522: addis r28,0,HIGH_CADDR(.L_syscall_copyin_recover) ! 523: addi r28,r28,LOW_ADDR(.L_syscall_copyin_recover) ! 524: stw r28,THREAD_RECOVER(r16) /* R16 still holds thread ptr */ ! 525: ! 526: /* We can manipulate the COPYIN segment register quite easily ! 527: * here, but we've also got to make sure we don't go over a ! 528: * segment boundary - hence some mess. ! 529: * Registers from 12-29 are free for our use. ! 530: */ ! 531: ! 532: ! 533: lwz r28,saver1(r30) /* Get the stack pointer */ ! 534: subi r29,r29,8 /* Get the number of arguments to copy */ ! 535: mfsr r10,SR_UNUSED_BY_KERN ; Get the user state SR value ! 536: ! 537: #ifdef MACHO_SYSCALL_BEGIN ! 538: add r28,r28,r25 /* Set source in user land */ ! 539: addi r28,r28,4 ! 540: #else ! 541: addi r28,r28,COPYIN_ARG0_OFFSET /* Set source in user land */ ! 542: #endif ! 543: ! 544: /* set up SR_COPYIN to allow us to copy, we may need to loop ! 545: * around if we change segments. We know that this previously ! 546: * pointed to user space, so the sid doesn't need setting. ! 547: */ ! 548: .L_syscall_copyin_seg_loop: ! 549: ! 550: rlwimi r10,r28,24,8,11 ; Blast the segment number into the SR ! 551: rlwinm r26,r28,0,4,31 ; Clear the segment number from source address ! 552: mtsr SR_COPYIN,r10 ; Set the copyin SR ! 553: isync ! 554: ! 555: oris r26,r26,(SR_COPYIN_NUM << (28-16)) ; Insert the copyin segment number into source address ! 556: ! 557: /* Make r27 point to address-4 of where we will store copied args */ ! 558: addi r27,r1,FM_ARG0-4 ! 559: ! 560: .L_syscall_copyin_word_loop: ! 561: ! 562: lwz r0,0(r26) /* MAY CAUSE PAGE FAULT! */ ! 563: subi r29,r29,1 ; Decrement count ! 564: addi r26,r26,4 ; Bump input ! 565: stw r0,4(r27) ; Save the copied in word ! 566: mr. r29,r29 ; Are they all moved? ! 567: addi r27,r27,4 ; Bump output ! 568: beq+ .L_syscall_copyin_done ; Escape if we are done... ! 569: ! 570: rlwinm. r0,r26,0,4,29 ; Did we just step into a new segment? ! 571: addi r28,r28,4 ; Bump up user state address also ! 572: bne+ .L_syscall_copyin_word_loop ; We are still on the same segment... ! 573: b .L_syscall_copyin_seg_loop /* On new segment! remap */ ! 574: ! 575: /* Don't bother restoring SR_COPYIN, we can leave it trashed */ ! 576: /* clear thread recovery as we're done touching user data */ ! 577: ! 578: .L_syscall_copyin_done: ! 579: li r0,0 ! 580: stw r0,THREAD_RECOVER(r16) /* R16 still holds thread ptr */ ! 581: ! 582: .L_syscall_got_args: ! 583: lwz r8,ACT_TASK(r13) /* Get our task */ ! 584: lis r10,hi16(EXT(c_syscalls_mach)) /* Get top half of counter address */ ! 585: lwz r7,TASK_SYSCALLS_MACH(r8) ; Get the current count ! 586: lwz r3,saver3(r30) /* Restore r3 */ ! 587: addi r7,r7,1 ; Bump it ! 588: ori r10,r10,lo16(EXT(c_syscalls_mach)) /* Get low half of counter address */ ! 589: stw r7,TASK_SYSCALLS_MACH(r8) ; Save it ! 590: lwz r4,saver4(r30) /* Restore r4 */ ! 591: lwz r9,0(r10) /* Get counter */ ! 592: lwz r5,saver5(r30) /* Restore r5 */ ! 593: lwz r6,saver6(r30) /* Restore r6 */ ! 594: addi r9,r9,1 /* Add 1 */ ! 595: lwz r7,saver7(r30) /* Restore r7 */ ! 596: lwz r8,saver8(r30) /* Restore r8 */ ! 597: stw r9,0(r10) /* Save it back */ ! 598: lwz r9,saver9(r30) /* Restore r9 */ ! 599: lwz r10,saver10(r30) /* Restore r10 */ ! 600: ! 601: lwz r0,MACH_TRAP_FUNCTION(r31) ! 602: ! 603: /* calling this function, all the callee-saved registers are ! 604: * still valid except for r30 and r31 which are in the PCB ! 605: * r30 holds pointer to saved state (ie. pcb) ! 606: * r31 is scrap ! 607: */ ! 608: mtctr r0 ! 609: bctrl /* perform the actual syscall */ ! 610: ! 611: /* 'standard' syscall returns here - INTERRUPTS ARE STILL ON */ ! 612: ! 613: /* r3 contains value that we're going to return to the user ! 614: */ ! 615: ! 616: /* ! 617: * Ok, return from C function, ARG0 = return value ! 618: * ! 619: * get the active thread's PCB pointer and thus pointer to user state ! 620: * saved state is still in R30 and the active thread is in R16 . ! 621: */ ! 622: ! 623: /* Store return value into saved state structure, since ! 624: * we need to pick up the value from here later - the ! 625: * syscall may perform a thread_set_syscall_return ! 626: * followed by a thread_exception_return, ending up ! 627: * at thread_syscall_return below, with SS_R3 having ! 628: * been set up already ! 629: */ ! 630: ! 631: /* When we are here, r16 should point to the current thread, ! 632: * r30 should point to the current pcb ! 633: */ ! 634: ! 635: /* save off return value, we must load it ! 636: * back anyway for thread_exception_return ! 637: * TODO NMGS put in register? ! 638: */ ! 639: .L_syscall_return: ! 640: mr r31,r16 /* Move the current thread pointer */ ! 641: stw r3,saver3(r30) /* Stash the return code */ ! 642: ! 643: /* Call a function that records the end of */ ! 644: /* the mach system call */ ! 645: mr r4,r30 ! 646: bl EXT(syscall_trace_end) ! 647: ! 648: #if 0 ! 649: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 650: mr r4,r31 /* (TEST/DEBUG) */ ! 651: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 652: mr r5,r30 /* (TEST/DEBUG) */ ! 653: sc /* (TEST/DEBUG) */ ! 654: #endif ! 655: ! 656: .L_thread_syscall_ret_check_ast: ! 657: mfmsr r12 /* Get the current MSR */ ! 658: rlwinm r12,r12,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Turn of interruptions enable bit */ ! 659: mtmsr r12 /* Turn interruptions off */ ! 660: ! 661: mfsprg r10,0 /* Get the per_processor block */ ! 662: ! 663: /* Check to see if there's an outstanding AST */ ! 664: ! 665: lwz r4,PP_NEED_AST(r10) ! 666: lwz r4,0(r4) ! 667: cmpi cr0,r4, 0 ! 668: beq cr0,.L_syscall_no_ast ! 669: ! 670: /* Yes there is, call ast_taken ! 671: * pretending that the user thread took an AST exception here, ! 672: * ast_taken will save all state and bring us back here ! 673: */ ! 674: ! 675: #if DEBUG ! 676: /* debug assert - make sure that we're not returning to kernel */ ! 677: lwz r3,savesrr1(r30) ! 678: andi. r3,r3,MASK(MSR_PR) ! 679: bne+ 0f /* returning to user level, check */ ! 680: ! 681: BREAKPOINT_TRAP ! 682: 0: ! 683: #endif /* DEBUG */ ! 684: ! 685: li r3, 0 ! 686: li r4, AST_ALL ! 687: li r5, 1 ! 688: bl EXT(ast_taken) ! 689: ! 690: b .L_thread_syscall_ret_check_ast ! 691: ! 692: /* thread_exception_return returns to here, almost all ! 693: * registers intact. It expects a full context restore ! 694: * of what it hasn't restored itself (ie. what we use). ! 695: * ! 696: * In particular for us, ! 697: * we still have r31 points to the current thread, ! 698: * r30 points to the current pcb ! 699: */ ! 700: ! 701: .L_syscall_no_ast: ! 702: .L_thread_syscall_return: ! 703: ! 704: mr r3,r30 ; Get savearea to the correct register for common exit ! 705: lwz r8,THREAD_TOP_ACT(r31) /* Now find the current activation */ ! 706: ! 707: lwz r11,SAVflags(r30) /* Get the flags */ ! 708: lwz r5,THREAD_KERNEL_STACK(r31) /* Get the base pointer to the stack */ ! 709: rlwinm r11,r11,0,15,13 /* Clear the syscall flag */ ! 710: lwz r4,SAVprev(r30) ; Get the previous save area ! 711: stw r11,SAVflags(r30) /* Stick back the flags */ ! 712: addi r5,r5,KERNEL_STACK_SIZE-FM_SIZE /* Reset to empty */ ! 713: stw r4,ACT_MACT_PCB(r8) ; Save previous save area ! 714: stw r5,ACT_MACT_KSP(r8) /* Save the empty stack pointer */ ! 715: ! 716: b chkfac ; Go end it all... ! 717: ! 718: ! 719: .L_syscall_copyin_recover: ! 720: ! 721: /* This is the catcher for any data faults in the copyin ! 722: * of arguments from the user's stack. ! 723: * r30 still holds a pointer to the PCB ! 724: * ! 725: * call syscall_error(EXC_BAD_ACCESS, EXC_PPC_VM_PROT_READ, sp, ssp), ! 726: * ! 727: * we already had a frame so we can do this ! 728: */ ! 729: ! 730: li r3,EXC_BAD_ACCESS ! 731: li r4,EXC_PPC_VM_PROT_READ ! 732: lwz r5,saver1(r30) ! 733: mr r6,r30 ! 734: ! 735: bl EXT(syscall_error) ! 736: b .L_syscall_return ! 737: ! 738: ! 739: /* ! 740: * thread_exception_return() ! 741: * ! 742: * Return to user mode directly from within a system call. ! 743: */ ! 744: ! 745: ENTRY(thread_exception_return, TAG_NO_FRAME_USED) ! 746: ! 747: .L_thread_exc_ret_check_ast: ! 748: ! 749: mfmsr r3 /* Get the MSR */ ! 750: rlwinm r3,r3,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear EE */ ! 751: mtmsr r3 /* Disable interrupts */ ! 752: ! 753: /* Check to see if there's an outstanding AST */ ! 754: /* We don't bother establishing a call frame even though CHECK_AST ! 755: can invoke ast_taken(), because it can just borrow our caller's ! 756: frame, given that we're not going to return. ! 757: */ ! 758: ! 759: mfsprg r10,0 /* Get the per_processor block */ ! 760: lwz r4,PP_NEED_AST(r10) ! 761: lwz r4,0(r4) ! 762: cmpi cr0,r4, 0 ! 763: beq cr0,.L_exc_ret_no_ast ! 764: ! 765: /* Yes there is, call ast_taken ! 766: * pretending that the user thread took an AST exception here, ! 767: * ast_taken will save all state and bring us back here ! 768: */ ! 769: ! 770: #if DEBUG ! 771: /* debug assert - make sure that we're not returning to kernel ! 772: * ! 773: * get the active thread's PCB pointer and thus pointer to user state ! 774: */ ! 775: lwz r30,PP_CPU_DATA(r10) ! 776: lwz r30,CPU_ACTIVE_THREAD(r30) ! 777: lwz r30,THREAD_TOP_ACT(r30) ! 778: lwz r30,ACT_MACT_PCB(r30) ! 779: ! 780: lwz r3,savesrr1(r30) ! 781: andi. r3,r3,MASK(MSR_PR) ! 782: bne+ ret_user2 /* returning to user level, check */ ! 783: ! 784: BREAKPOINT_TRAP ! 785: ret_user2: ! 786: #endif /* DEBUG */ ! 787: ! 788: li r3,0 ! 789: li r4,AST_ALL ! 790: li r5,1 ! 791: ! 792: bl EXT(ast_taken) ! 793: b .L_thread_exc_ret_check_ast /* check for a second AST (rare)*/ ! 794: ! 795: /* arriving here, interrupts should be disabled */ ! 796: /* Get the active thread's PCB pointer to restore regs ! 797: */ ! 798: .L_exc_ret_no_ast: ! 799: ! 800: lwz r31,PP_CPU_DATA(r10) ! 801: lwz r31,CPU_ACTIVE_THREAD(r31) ! 802: lwz r30,THREAD_TOP_ACT(r31) ! 803: lwz r30,ACT_MACT_PCB(r30) ! 804: ! 805: /* If the MSR_SYSCALL_MASK isn't set, then we came from a trap, ! 806: * so warp into the return_from_trap (thread_return) routine, ! 807: * which takes PCB pointer in R3, not in r30! ! 808: */ ! 809: lwz r0,SAVflags(r30) ! 810: mr r3,r30 /* Copy pcb pointer into r3 in case */ ! 811: andis. r0,r0,SAVsyscall>>16 /* Are we returning from a syscall? */ ! 812: beq- cr0,thread_return /* Nope, must be a thread return... */ ! 813: b .L_thread_syscall_return ! 814: ! 815: /* ! 816: * thread_bootstrap_return() ! 817: * ! 818: */ ! 819: ! 820: ENTRY(thread_bootstrap_return, TAG_NO_FRAME_USED) ! 821: ! 822: mfmsr r12 /* Get the current MSR */ ! 823: rlwinm r12,r12,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Turn of interruptions enable bit */ ! 824: mtmsr r12 /* Turn interruptions off */ ! 825: ! 826: mfsprg r10,0 /* Get the per_processor block */ ! 827: ! 828: ! 829: #if 0 ! 830: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 831: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 832: sc /* (TEST/DEBUG) */ ! 833: #endif ! 834: ! 835: lwz r31,PP_CPU_DATA(r10) ! 836: ! 837: lwz r31,CPU_ACTIVE_THREAD(r31) ! 838: lwz r31,THREAD_TOP_ACT(r31) ! 839: ! 840: .L_bootstrap_ret_check_ast: ! 841: mfmsr r12 /* Get the current MSR */ ! 842: rlwinm r12,r12,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Turn off interruptions enable bit */ ! 843: mtmsr r12 /* Turn interruptions off */ ! 844: mfsprg r10,0 /* Get the per_processor block */ ! 845: /* Check for any outstanding ASTs and deal with them */ ! 846: lwz r4,PP_NEED_AST(r10) ! 847: lwz r4,0(r4) ! 848: cmpi cr0,r4, 0 ! 849: beq cr0,.L_bootstrap_ret_no_ast ! 850: ! 851: /* we have a pending AST, now is the time to jump, args as below ! 852: * void ast_taken(boolean_t preemption, ast_t mask, boolean_t interrupts) ! 853: */ ! 854: li r3, 0 ! 855: li r4,AST_ALL ! 856: li r5,1 ! 857: ! 858: bl EXT(ast_taken) ! 859: b .L_bootstrap_ret_check_ast /* Check for another AST (rare) */ ! 860: ! 861: ! 862: /* Back from dealing with ASTs, if there were any. ! 863: * r31 still holds pointer to ACT. ! 864: * ! 865: * Time to deal with kloading or kloaded threads ! 866: */ ! 867: .L_bootstrap_ret_no_ast: ! 868: lwz r3,ACT_KLOADING(r31) ! 869: li r0,0 ! 870: cmpi cr0,r3, 0 ! 871: li r9,1 ! 872: beq+ .L_bootstrap_ret_no_kload ! 873: stw r0,ACT_KLOADING(r31) ! 874: lwz r3,PP_ACTIVE_KLOADED(r10) ! 875: stw r0,ACT_KLOADED(r31) ! 876: stw r31,0(r3) ! 877: ! 878: /* Ok, we're all set, jump to thread_return as if we ! 879: * were just coming back from a trap (ie. r3 set up to point to pcb) ! 880: */ ! 881: .L_bootstrap_ret_no_kload: ! 882: ! 883: lwz r3,ACT_MACT_PCB(r31) /* Point to our saved context */ ! 884: #if 0 ! 885: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 886: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 887: sc /* (TEST/DEBUG) */ ! 888: #endif ! 889: ! 890: b thread_return ! 891: ! 892: /* ! 893: * ihandler(type) ! 894: * ! 895: * ENTRY: VM switched ON ! 896: * Interrupts OFF ! 897: * R3 contains exception code ! 898: * R4 points to the saved context (virtual address) ! 899: * Everything is saved in savearea ! 900: * ! 901: */ ! 902: ! 903: ENTRY(ihandler, TAG_NO_FRAME_USED) /* What tag should this have?! */ ! 904: ! 905: /* ! 906: * get the value of istackptr, if it's zero then we're already on the ! 907: * interrupt stack, otherwise it points to a saved_state structure ! 908: * at the top of the interrupt stack. ! 909: */ ! 910: ! 911: lwz r10,savesrr1(r4) /* Get SRR0 */ ! 912: mfsprg r25,0 /* Get the per_proc block */ ! 913: li r14,0 /* Zero this for now */ ! 914: lwz r16,PP_CPU_DATA(r25) /* Assume we need this */ ! 915: rlwinm. r10,r10,0,MSR_VEC_BIT,MSR_VEC_BIT ; Was vector on? ! 916: lwz r1, PP_ISTACKPTR(r25) /* Get the interrupt stack */ ! 917: li r13,0 /* Zero this for now */ ! 918: lwz r16,CPU_ACTIVE_THREAD(r16) /* Get the thread pointer */ ! 919: ! 920: beq+ ivecoff ; Vector off, do not save vrsave... ! 921: mfspr r7,vrsave ; Get the VRSAVE register ! 922: stw r7,liveVRS(r25) ; Set the live value ! 923: ! 924: ivecoff: li r0,0 /* Get a constant 0 */ ! 925: cmplwi cr1,r16,0 /* Are we still booting? */ ! 926: mr. r1,r1 /* Is it active? */ ! 927: beq- cr1,ihboot1 /* We're still coming up... */ ! 928: lwz r13,THREAD_TOP_ACT(r16) /* Pick up the active thread */ ! 929: lwz r14,ACT_MACT_PCB(r13) /* Now point to the PCB */ ! 930: ! 931: ihboot1: lwz r9,saver1(r4) /* Pick up the 'rupt time stack */ ! 932: stw r14,SAVprev(r4) /* Queue the new save area in the front */ ! 933: stw r13,SAVact(r4) /* Point the savearea at its activation */ ! 934: beq- cr1,ihboot4 /* We're still coming up... */ ! 935: stw r4,ACT_MACT_PCB(r13) /* Point to our savearea */ ! 936: ! 937: ihboot4: bne .L_istackfree /* Nope... */ ! 938: ! 939: /* We're already on the interrupt stack, get back the old ! 940: * stack pointer and make room for a frame ! 941: */ ! 942: ! 943: subi r1,r9,FM_REDZONE /* Back up beyond the red zone */ ! 944: b ihsetback /* Go set up the back chain... */ ! 945: ! 946: .L_istackfree: ! 947: lwz r10,SAVflags(r4) ! 948: stw r0,PP_ISTACKPTR(r25) /* Mark the stack in use */ ! 949: oris r10,r10,HIGH_ADDR(SAVrststk) /* Indicate we reset stack when we return from this one */ ! 950: stw r10,SAVflags(r4) /* Stick it back */ ! 951: ! 952: /* ! 953: * To summarise, when we reach here, the state has been saved and ! 954: * the stack is marked as busy. We now generate a small ! 955: * stack frame with backpointers to follow the calling ! 956: * conventions. We set up the backpointers to the trapped ! 957: * routine allowing us to backtrace. ! 958: */ ! 959: ! 960: ihsetback: subi r1,r1,FM_SIZE /* Make a new frame */ ! 961: stw r9,FM_BACKPTR(r1) /* point back to previous stackptr */ ! 962: ! 963: #if VERIFYSAVE ! 964: bl versave ; (TEST/DEBUG) ! 965: #endif ! 966: ! 967: #if DEBUG ! 968: /* If debugging, we need two frames, the first being a dummy ! 969: * which links back to the trapped routine. The second is ! 970: * that which the C routine below will need ! 971: */ ! 972: lwz r5,savesrr0(r4) /* Get interrupt address */ ! 973: stw r5,FM_LR_SAVE(r1) /* save old instr ptr as LR value */ ! 974: stwu r1,-FM_SIZE(r1) /* Make another new frame for C routine */ ! 975: #endif /* DEBUG */ ! 976: ! 977: lwz r5,savedsisr(r4) /* Get the DSISR */ ! 978: lwz r6,savedar(r4) /* Get the DAR */ ! 979: ! 980: bl EXT(interrupt) ! 981: ! 982: ! 983: /* interrupt() returns a pointer to the saved state in r3 ! 984: * ! 985: * Ok, back from C. Disable interrupts while we restore things ! 986: */ ! 987: .globl EXT(ihandler_ret) ! 988: ! 989: LEXT(ihandler_ret) /* Marks our return point from debugger entry */ ! 990: ! 991: mfmsr r0 /* Get our MSR */ ! 992: rlwinm r0,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Flip off the interrupt enabled bit */ ! 993: mtmsr r0 /* Make sure interrupts are disabled */ ! 994: mfsprg r10,0 /* Get the per_proc block */ ! 995: ! 996: lwz r8,PP_CPU_DATA(r10) /* Get the CPU data area */ ! 997: lwz r7,SAVflags(r3) /* Pick up the flags */ ! 998: lwz r8,CPU_ACTIVE_THREAD(r8) /* and the active thread */ ! 999: lwz r9,SAVprev(r3) /* Get previous save area */ ! 1000: cmplwi cr1,r8,0 /* Are we still initializing? */ ! 1001: lwz r12,savesrr1(r3) /* Get the MSR we will load on return */ ! 1002: beq- cr1,ihboot2 /* Skip if we are still in init... */ ! 1003: lwz r8,THREAD_TOP_ACT(r8) /* Pick up the active thread */ ! 1004: ! 1005: ihboot2: andis. r11,r7,HIGH_ADDR(SAVrststk) /* Is this the first on the stack? */ ! 1006: beq- cr1,ihboot3 /* Skip if we are still in init... */ ! 1007: stw r9,ACT_MACT_PCB(r8) /* Point to previous context savearea */ ! 1008: ! 1009: ihboot3: mr r4,r3 /* Move the savearea pointer */ ! 1010: beq .L_no_int_ast2 /* Get going if not the top o' stack... */ ! 1011: ! 1012: ! 1013: /* We're the last frame on the stack. Restore istackptr to empty state. ! 1014: * ! 1015: * Check for ASTs if one of the below is true: ! 1016: * returning to user mode ! 1017: * returning to a kloaded server ! 1018: */ ! 1019: lwz r9,PP_INTSTACK_TOP_SS(r10) /* Get the empty stack value */ ! 1020: andc r7,r7,r11 /* Remove the stack reset bit in case we pass this one */ ! 1021: stw r9,PP_ISTACKPTR(r25) /* Save that saved state ptr */ ! 1022: andi. r6,r12,MASK(MSR_PR) /* Are we going to problem state? (Sorry, ancient IBM term for non-privileged) */ ! 1023: stw r7,SAVflags(r4) /* Save the flags */ ! 1024: beq- .L_no_int_ast ; In kernel space, no AST check... ! 1025: ! 1026: lwz r11,PP_NEED_AST(r10) /* Get the AST request address */ ! 1027: lwz r11,0(r11) /* Get the request */ ! 1028: li r3,T_AST /* Assume the worst */ ! 1029: mr. r11,r11 /* Are there any pending? */ ! 1030: beq .L_no_int_ast /* Nope... */ ! 1031: ! 1032: /* ! 1033: * There is a pending AST. Massage things to make it look like ! 1034: * we took a trap and jump into the trap handler. To do this ! 1035: * we essentially pretend to return from the interrupt but ! 1036: * at the last minute jump into the trap handler with an AST ! 1037: * trap instead of performing an rfi. ! 1038: */ ! 1039: ! 1040: stw r3,saveexception(r4) /* Set the exception code to T_AST */ ! 1041: b EXT(thandler) /* hyperspace into AST trap */ ! 1042: ! 1043: .L_no_int_ast: ! 1044: mr r3,r4 ; Get into the right register for common code ! 1045: .L_no_int_ast2: ! 1046: rlwinm r7,r7,0,15,13 /* Clear the syscall bit */ ! 1047: li r4,0 ; Assume for a moment that we are in init ! 1048: stw r7,SAVflags(r3) /* Set the flags */ ! 1049: beq- cr1,chkfac ; Jump away if we are in init... ! 1050: lwz r4,ACT_MACT_PCB(r8) ; Get the new level marker ! 1051: ! 1052: ! 1053: ; ! 1054: ; This section is common to all exception exits. It throws away vector ! 1055: ; and floating point saveareas as the exception level of a thread is ! 1056: ; exited. ! 1057: ; ! 1058: ; It also enables the facility if its context is live ! 1059: ; Requires: ! 1060: ; R3 = Savearea to be released (virtual) ! 1061: ; R4 = New top of savearea stack (could be 0) ! 1062: ; R8 = pointer to activation ! 1063: ; R10 = per_proc block ! 1064: ; ! 1065: chkfac: mr. r8,r8 ; Are we still in boot? ! 1066: beq- chkenax ; Yeah, skip it all... ! 1067: ! 1068: lwz r20,ACT_MACT_FPUlvl(r8) ; Get the FPU level ! 1069: lwz r12,savesrr1(r3) ; Get the current MSR ! 1070: cmplw r20,r3 ; Are we returning from the active level? ! 1071: lwz r23,PP_FPU_THREAD(r10) ; Get floating point owner ! 1072: rlwinm r12,r12,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Turn off floating point for now ! 1073: cmplw cr1,r23,r8 ; Are we the facility owner? ! 1074: lhz r26,PP_CPU_NUMBER(r10) ; Get the current CPU number ! 1075: beq- chkfpfree ; Leaving active level, can not possibly enable... ! 1076: bne- cr1,chkvec ; Not our facility, nothing to do here... ! 1077: ! 1078: #if FPVECDBG ! 1079: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1080: li r2,0x3301 ; (TEST/DEBUG) ! 1081: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1082: sc ; (TEST/DEBUG) ! 1083: #endif ! 1084: ! 1085: lwz r24,ACT_MACT_FPUcpu(r8) ; Get the CPU this context was enabled on last ! 1086: cmplw r4,r20 ; Are we going to be in the right level? ! 1087: cmplw cr1,r24,r26 ; Are we on the right CPU? ! 1088: li r0,0 ; Get a constant 0 ! 1089: beq+ cr1,chkfpnlvl ; Right CPU... ! 1090: ! 1091: stw r0,PP_FPU_THREAD(r10) ; Show facility unowned so we do not get back here ! 1092: b chkvec ; Go check out the vector facility... ! 1093: ! 1094: chkfpnlvl: bne- chkvec ; Different level, can not enable... ! 1095: lwz r24,ACT_MACT_FPU(r8) ; Get the floating point save area ! 1096: ori r12,r12,lo16(MASK(MSR_FP)) ; Enable facility ! 1097: mr. r24,r24 ; Does the savearea exist? ! 1098: li r0,1 ; Get set to invalidate ! 1099: beq- chkvec ; Nothing to invalidate... ! 1100: lwz r25,SAVlvlfp(r24) ; Get the level of top savearea ! 1101: cmplw r4,r25 ; Is the top one ours? ! 1102: bne+ chkvec ; Not ours... ! 1103: stw r0,SAVlvlfp(r24) ; Invalidate the first one ! 1104: ! 1105: #if 0 ! 1106: mfmsr r0 ; (TEST/DEBUG) ! 1107: ori r0,r0,0x2000 ; (TEST/DEBUG) ! 1108: mtmsr r0 ; (TEST/DEBUG) ! 1109: isync ; (TEST/DEBUG) ! 1110: ! 1111: stfd f0,savevr0(r3) ; (TEST/DEBUG) ! 1112: stfd f1,savevr0+8(r3) ; (TEST/DEBUG) ! 1113: stfd f2,savevr0+0x10(r3) ; (TEST/DEBUG) ! 1114: stfd f3,savevr0+0x18(r3) ; (TEST/DEBUG) ! 1115: stfd f4,savevr0+0x20(r3) ; (TEST/DEBUG) ! 1116: stfd f5,savevr0+0x28(r3) ; (TEST/DEBUG) ! 1117: stfd f6,savevr0+0x30(r3) ; (TEST/DEBUG) ! 1118: stfd f7,savevr0+0x38(r3) ; (TEST/DEBUG) ! 1119: stfd f8,savevr0+0x40(r3) ; (TEST/DEBUG) ! 1120: stfd f9,savevr0+0x48(r3) ; (TEST/DEBUG) ! 1121: stfd f10,savevr0+0x50(r3) ; (TEST/DEBUG) ! 1122: stfd f11,savevr0+0x58(r3) ; (TEST/DEBUG) ! 1123: stfd f12,savevr0+0x60(r3) ; (TEST/DEBUG) ! 1124: stfd f13,savevr0+0x68(r3) ; (TEST/DEBUG) ! 1125: stfd f14,savevr0+0x70(r3) ; (TEST/DEBUG) ! 1126: stfd f15,savevr0+0x78(r3) ; (TEST/DEBUG) ! 1127: stfd f16,savevr0+0x80(r3) ; (TEST/DEBUG) ! 1128: stfd f17,savevr0+0x88(r3 ; (TEST/DEBUG) ! 1129: stfd f18,savevr0+0x90(r3) ; (TEST/DEBUG) ! 1130: stfd f19,savevr0+0x98(r3) ; (TEST/DEBUG) ! 1131: stfd f20,savevr0+0xA0(r3) ; (TEST/DEBUG) ! 1132: stfd f21,savevr0+0xA8(r3) ; (TEST/DEBUG) ! 1133: stfd f22,savevr0+0xB0(r3) ; (TEST/DEBUG) ! 1134: stfd f23,savevr0+0xB8(r3) ; (TEST/DEBUG) ! 1135: stfd f24,savevr0+0xC0(r3) ; (TEST/DEBUG) ! 1136: stfd f25,savevr0+0xC8(r3) ; (TEST/DEBUG) ! 1137: stfd f26,savevr0+0xD0(r3) ; (TEST/DEBUG) ! 1138: stfd f27,savevr0+0xD8(r3) ; (TEST/DEBUG) ! 1139: stfd f28,savevr0+0xE0(r3) ; (TEST/DEBUG) ! 1140: stfd f29,savevr0+0xE8(r3) ; (TEST/DEBUG) ! 1141: stfd f30,savevr0+0xF0(r3) ; (TEST/DEBUG) ! 1142: stfd f31,savevr0+0xF8(r3) ; (TEST/DEBUG) ! 1143: ! 1144: li r2,64 ; (TEST/DEBUG) ! 1145: la r20,savevr0(r3) ; (TEST/DEBUG) ! 1146: la r21,savefp0(r24) ; (TEST/DEBUG) ! 1147: ! 1148: ckmurderdeath2: ! 1149: lwz r22,0(r20) ; (TEST/DEBUG) ! 1150: subic. r2,r2,1 ; (TEST/DEBUG) ! 1151: lwz r23,0(r21) ; (TEST/DEBUG) ! 1152: addi r20,r20,4 ; (TEST/DEBUG) ! 1153: cmplw cr1,r22,r23 ; (TEST/DEBUG) ! 1154: addi r21,r21,4 ; (TEST/DEBUG) ! 1155: bne- cr1,diekilldead2 ; (TEST/DEBUG) ! 1156: bne+ ckmurderdeath2 ; (TEST/DEBUG) ! 1157: b dontdiekilldead2 ; (TEST/DEBUG) ! 1158: ! 1159: diekilldead2: ; (TEST/DEBUG) ! 1160: mr r4,r24 ; (TEST/DEBUG) ! 1161: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1162: ! 1163: dontdiekilldead2: ! 1164: lfd f0,savevr0(r3) ; (TEST/DEBUG) ! 1165: lfd f1,savevr0+8(r3) ; (TEST/DEBUG) ! 1166: #endif ! 1167: ! 1168: ! 1169: ! 1170: b chkvec ; Go check out the vector facility... ! 1171: ! 1172: chkfpfree: li r0,0 ; Clear a register ! 1173: lwz r24,ACT_MACT_FPU(r8) ; Get the floating point save area ! 1174: ! 1175: bne- cr1,chkfpnfr ; Not our facility, do not clear... ! 1176: stw r0,PP_FPU_THREAD(r10) ; Clear floating point owner ! 1177: chkfpnfr: ! 1178: ! 1179: #if FPVECDBG ! 1180: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1181: li r2,0x3302 ; (TEST/DEBUG) ! 1182: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1183: sc ; (TEST/DEBUG) ! 1184: #endif ! 1185: ! 1186: mr. r24,r24 ; Do we even have a savearea? ! 1187: beq+ chkvec ; Nope... ! 1188: ! 1189: #if FPVECDBG ! 1190: rlwinm. r0,r24,0,0,15 ; (TEST/DEBUG) ! 1191: bne+ notbadxxx1 ; (TEST/DEBUG) ! 1192: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1193: notbadxxx1: ; (TEST/DEBUG) ! 1194: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1195: li r2,0x3303 ; (TEST/DEBUG) ! 1196: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1197: sc ; (TEST/DEBUG) ! 1198: #endif ! 1199: ! 1200: lwz r25,SAVlvlfp(r24) ; Get the level of top savearea ! 1201: cmplwi r25,1 ; Is the top area invalid? ! 1202: cmplw cr1,r25,r3 ; Is it for the returned from context? ! 1203: beq fptoss ; It is invalid... ! 1204: bne cr1,chkvec ; Not for the returned context... ! 1205: ! 1206: fptoss: lwz r25,SAVprefp(r24) ; Get previous savearea ! 1207: #if FPVECDBG ! 1208: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1209: li r2,0x3304 ; (TEST/DEBUG) ! 1210: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1211: mr r5,r25 ; (TEST/DEBUG) ! 1212: sc ; (TEST/DEBUG) ! 1213: #endif ! 1214: mr. r25,r25 ; Is there one? ! 1215: stw r25,ACT_MACT_FPU(r8) ; Set the new pointer ! 1216: beq fptoplvl ; Nope, we are at the top... ! 1217: #if FPVECDBG ! 1218: rlwinm. r0,r25,0,0,15 ; (TEST/DEBUG) ! 1219: bne+ notbadxxx2 ; (TEST/DEBUG) ! 1220: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1221: notbadxxx2: ; (TEST/DEBUG) ! 1222: #endif ! 1223: lwz r25,SAVlvlfp(r25) ; Get the new level ! 1224: ! 1225: fptoplvl: lwz r19,SAVflags(r24) ; Get the savearea flags ! 1226: #if FPVECDBG ! 1227: rlwinm. r0,r19,0,1,1 ; (TEST/DEBUG) ! 1228: bne+ donotdie3 ; (TEST/DEBUG) ! 1229: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1230: donotdie3: ; (TEST/DEBUG) ! 1231: #endif ! 1232: ! 1233: #if FPVECDBG ! 1234: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1235: li r2,0x3305 ; (TEST/DEBUG) ! 1236: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1237: sc ; (TEST/DEBUG) ! 1238: #endif ! 1239: rlwinm r22,r24,0,0,19 ; Round down to the base savearea block ! 1240: rlwinm r19,r19,0,2,0 ; Remove the floating point in use flag ! 1241: stw r25,ACT_MACT_FPUlvl(r8) ; Set the new top level ! 1242: andis. r0,r19,hi16(SAVinuse) ; Still in use? ! 1243: stw r19,SAVflags(r24) ; Set the savearea flags ! 1244: bne- chkvec ; Yes, go check out vector... ! 1245: #if FPVECDBG ! 1246: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1247: li r2,0x3306 ; (TEST/DEBUG) ! 1248: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1249: sc ; (TEST/DEBUG) ! 1250: #endif ! 1251: #if FPVECDBG ! 1252: rlwinm. r0,r24,0,0,15 ; (TEST/DEBUG) ! 1253: bne+ notbadxxx3 ; (TEST/DEBUG) ! 1254: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1255: notbadxxx3: ; (TEST/DEBUG) ! 1256: #endif ! 1257: lwz r23,SACvrswap(r22) ; Get the conversion from virtual to real ! 1258: lwz r20,PP_QUICKFRET(r10) ; Get the old quick fret head ! 1259: xor r23,r24,r23 ; Convert to physical ! 1260: stw r20,SAVqfret(r24) ; Back chain the quick release queue ! 1261: stw r23,PP_QUICKFRET(r10) ; Anchor it ! 1262: ! 1263: ; ! 1264: ; Check out vector stuff (and translate savearea to physical for exit) ! 1265: ; ! 1266: chkvec: ! 1267: lwz r20,ACT_MACT_VMXlvl(r8) ; Get the vector level ! 1268: lwz r23,PP_VMX_THREAD(r10) ; Get vector owner ! 1269: cmplw r20,r3 ; Are we returning from the active level? ! 1270: rlwinm r12,r12,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Turn off vector for now ! 1271: cmplw cr1,r23,r8 ; Are we the facility owner? ! 1272: beq- chkvecfree ; Leaving active level, can not possibly enable... ! 1273: bne- cr1,setena ; Not our facility, nothing to do here... ! 1274: ! 1275: #if FPVECDBG ! 1276: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1277: li r2,0x3401 ; (TEST/DEBUG) ! 1278: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1279: sc ; (TEST/DEBUG) ! 1280: #endif ! 1281: ! 1282: lwz r24,ACT_MACT_VMXcpu(r8) ; Get the CPU this context was enabled on last ! 1283: cmplw r4,r20 ; Are we going to be in the right level? ! 1284: cmplw cr1,r24,r26 ; Are we on the right CPU? ! 1285: li r0,0 ; Get a constant 0 ! 1286: beq+ cr1,chkvecnlvl ; Right CPU... ! 1287: ! 1288: stw r0,PP_VMX_THREAD(r10) ; Show facility unowned so we do not get back here ! 1289: b setena ; Go actually exit... ! 1290: ! 1291: chkvecnlvl: bne- setena ; Different level, can not enable... ! 1292: lwz r24,ACT_MACT_VMX(r8) ; Get the vector save area ! 1293: oris r12,r12,hi16(MASK(MSR_VEC)) ; Enable facility ! 1294: mr. r24,r24 ; Does the savearea exist? ! 1295: li r0,1 ; Get set to invalidate ! 1296: beq- setena ; Nothing to invalidate... ! 1297: lwz r25,SAVlvlvec(r24) ; Get the level of top savearea ! 1298: cmplw r4,r25 ; Is the top one ours? ! 1299: bne+ setena ; Not ours... ! 1300: stw r0,SAVlvlvec(r24) ; Invalidate the first one ! 1301: b setena ; Actually exit... ! 1302: ! 1303: chkvecfree: li r0,0 ; Clear a register ! 1304: lwz r24,ACT_MACT_VMX(r8) ; Get the vector save area ! 1305: bne- cr1,chkvecnfr ; Not our facility, do not clear... ! 1306: stw r0,PP_VMX_THREAD(r10) ; Clear vector owner ! 1307: chkvecnfr: ! 1308: ! 1309: #if FPVECDBG ! 1310: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1311: li r2,0x3402 ; (TEST/DEBUG) ! 1312: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1313: sc ; (TEST/DEBUG) ! 1314: #endif ! 1315: ! 1316: mr. r24,r24 ; Do we even have a savearea? ! 1317: beq+ setena ; Nope... ! 1318: ! 1319: #if FPVECDBG ! 1320: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1321: li r2,0x3403 ; (TEST/DEBUG) ! 1322: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1323: sc ; (TEST/DEBUG) ! 1324: #endif ! 1325: lwz r25,SAVlvlvec(r24) ; Get the level ! 1326: cmplwi r25,1 ; Is the top area invalid? ! 1327: cmplw cr1,r25,r3 ; Is it for the returned from context? ! 1328: beq vectoss ; It is invalid... ! 1329: bne cr1,setena ; Not for the returned context... ! 1330: ! 1331: vectoss: lwz r25,SAVprevec(r24) ; Get previous savearea ! 1332: #if FPVECDBG ! 1333: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1334: li r2,0x3504 ; (TEST/DEBUG) ! 1335: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1336: mr r5,r25 ; (TEST/DEBUG) ! 1337: sc ; (TEST/DEBUG) ! 1338: #endif ! 1339: mr. r25,r25 ; Is there one? ! 1340: stw r25,ACT_MACT_VMX(r8) ; Set the new pointer ! 1341: beq vectoplvl ; Nope, we are at the top... ! 1342: lwz r25,SAVlvlvec(r25) ; Get the new level ! 1343: ! 1344: vectoplvl: lwz r19,SAVflags(r24) ; Get the savearea flags ! 1345: ! 1346: #if FPVECDBG ! 1347: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1348: li r2,0x3405 ; (TEST/DEBUG) ! 1349: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1350: sc ; (TEST/DEBUG) ! 1351: #endif ! 1352: rlwinm r22,r24,0,0,19 ; Round down to the base savearea block ! 1353: rlwinm r19,r19,0,3,1 ; Remove the vector in use flag ! 1354: stw r25,ACT_MACT_VMXlvl(r8) ; Set the new top level ! 1355: andis. r0,r19,hi16(SAVinuse) ; Still in use? ! 1356: stw r19,SAVflags(r24) ; Set the savearea flags ! 1357: bne- setena ; Yes, all done... ! 1358: #if FPVECDBG ! 1359: lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) ! 1360: li r2,0x3406 ; (TEST/DEBUG) ! 1361: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) ! 1362: sc ; (TEST/DEBUG) ! 1363: #endif ! 1364: lwz r23,SACvrswap(r22) ; Get the conversion from virtual to real ! 1365: lwz r20,PP_QUICKFRET(r10) ; Get the old quick fret head ! 1366: xor r23,r24,r23 ; Convert to physical ! 1367: stw r20,SAVqfret(r24) ; Back chain the quick release queue ! 1368: stw r23,PP_QUICKFRET(r10) ; Anchor it ! 1369: ! 1370: setena: stw r12,savesrr1(r3) ; Turn facility on or off ! 1371: ! 1372: chkenax: lwz r6,SAVflags(r3) ; Pick up the flags of the old savearea ! 1373: ! 1374: ! 1375: #if DEBUG ! 1376: lwz r20,SAVact(r3) ; (TEST/DEBUG) Make sure our restore ! 1377: lwz r21,PP_CPU_DATA(r10) ; (TEST/DEBUG) context is associated ! 1378: lwz r21,CPU_ACTIVE_THREAD(r21) ; (TEST/DEBUG) with the current act. ! 1379: cmpwi r21,0 ; (TEST/DEBUG) ! 1380: beq- yeswereok ; (TEST/DEBUG) ! 1381: lwz r21,THREAD_TOP_ACT(r21) ; (TEST/DEBUG) ! 1382: cmplw r21,r20 ; (TEST/DEBUG) ! 1383: beq+ yeswereok ; (TEST/DEBUG) ! 1384: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1385: ! 1386: yeswereok: ! 1387: #endif ! 1388: ! 1389: rlwinm r5,r3,0,0,19 ; Round savearea down to page bndry ! 1390: rlwinm r6,r6,0,1,31 ; Mark savearea free ! 1391: lwz r5,SACvrswap(r5) ; Get the conversion from virtual to real ! 1392: stw r6,SAVflags(r3) ; Set savearea flags ! 1393: xor r3,r3,r5 ; Flip to physical address ! 1394: b EXT(exception_exit) ; We are all done now... ! 1395: ! 1396: ! 1397: ! 1398: /* ! 1399: * Here's where we handle the fastpath stuff ! 1400: * We'll do what we can here because registers are already ! 1401: * loaded and it will be less confusing that moving them around. ! 1402: * If we need to though, we'll branch off somewhere's else. ! 1403: * ! 1404: * Registers when we get here: ! 1405: * ! 1406: * r0 = syscall number ! 1407: * r4 = savearea/pcb ! 1408: * r13 = activation ! 1409: * r14 = previous savearea (if any) ! 1410: * r16 = thread ! 1411: * r25 = per_proc ! 1412: */ ! 1413: ! 1414: fastpath: cmplwi cr3,r0,0x7FF1 ; Is it CthreadSetSelfNumber? ! 1415: bnelr- cr3 ; Not a fast path... ! 1416: ! 1417: /* ! 1418: * void cthread_set_self(cproc_t p) ! 1419: * ! 1420: * set's thread state "user_value" ! 1421: * ! 1422: * This op is invoked as follows: ! 1423: * li r0, CthreadSetSelfNumber // load the fast-trap number ! 1424: * sc // invoke fast-trap ! 1425: * blr ! 1426: * ! 1427: */ ! 1428: ! 1429: CthreadSetSelfNumber: ! 1430: ! 1431: lwz r5,saver3(r4) /* Retrieve the self number */ ! 1432: stw r5,CTHREAD_SELF(r13) /* Remember it */ ! 1433: stw r5,UAW(r25) /* Prime the per_proc_info with it */ ! 1434: ! 1435: ! 1436: .globl EXT(fastexit) ! 1437: EXT(fastexit): ! 1438: lwz r8,SAVflags(r4) /* Pick up the flags */ ! 1439: rlwinm r9,r4,0,0,19 /* Round down to the base savearea block */ ! 1440: rlwinm r8,r8,0,1,31 /* Clear the attached bit */ ! 1441: lwz r9,SACvrswap(r9) /* Get the conversion from virtual to real */ ! 1442: stw r8,SAVflags(r4) /* Set the flags */ ! 1443: xor r3,r4,r9 /* Switch savearea to physical addressing */ ! 1444: b EXT(exception_exit) /* Go back to the caller... */ ! 1445: ! 1446: ! 1447: /* ! 1448: * Here's where we check for a hit on the Blue Box Assist ! 1449: * Most registers are non-volatile, so be careful here. If we don't ! 1450: * recognize the trap instruction we go back for regular processing. ! 1451: * Otherwise we transfer to the assist code. ! 1452: */ ! 1453: ! 1454: checkassist: ! 1455: lwz r23,savesrr1(r4) /* Get the interrupted MSR */ ! 1456: lwz r24,ACT_MACT_BTS(r9) /* Get the table start */ ! 1457: rlwinm. r23,r23,0,MSR_PR_BIT,MSR_PR_BIT /* Are we in userland? */ ! 1458: lwz r27,savesrr0(r4) /* Get trapped address */ ! 1459: beqlr- /* No assist in kernel mode... */ ! 1460: ! 1461: checkassistBP: /* Safe place to breakpoint */ ! 1462: ! 1463: sub r24,r27,r24 /* See how far into it we are */ ! 1464: rlwinm r24,r24,PKTDSHIFT,0,27 /* Get displacement to control block */ ! 1465: cmplwi r24,BBMAXTRAP*PKTDSIZE /* Do we fit in the list? */ ! 1466: bgtlr- /* Nope, it's a regular trap... */ ! 1467: b EXT(atomic_switch_trap) /* Go to the assist... */ ! 1468: ! 1469: #if MACH_KDB ! 1470: /* ! 1471: * Here's where we jump into the debugger. This is called from ! 1472: * either an MP signal from another processor, or a command-power NMI ! 1473: * on the main processor. ! 1474: * ! 1475: * Note that somewhere in our stack should be a return into the interrupt ! 1476: * handler. If there isn't, we'll crash off the end of the stack, actually, ! 1477: * it'll just quietly return. hahahahaha. ! 1478: */ ! 1479: ! 1480: ENTRY(kdb_kintr, TAG_NO_FRAME_USED) ! 1481: ! 1482: lis r9,HIGH_ADDR(EXT(ihandler_ret)) /* Top part of interrupt return */ ! 1483: lis r10,HIGH_ADDR(EXT(intercept_ret)) /* Top part of intercept return */ ! 1484: ori r9,r9,LOW_ADDR(EXT(ihandler_ret)) /* Bottom part of interrupt return */ ! 1485: ori r10,r10,LOW_ADDR(EXT(intercept_ret)) /* Bottom part of intercept return */ ! 1486: ! 1487: lwz r8,0(r1) /* Get our caller's stack frame */ ! 1488: ! 1489: srchrets: mr. r8,r8 /* Have we reached the end of our rope? */ ! 1490: beqlr- /* Yeah, just bail... */ ! 1491: lwz r7,FM_LR_SAVE(r8) /* The whoever called them */ ! 1492: cmplw cr0,r9,r7 /* Was it the interrupt handler? */ ! 1493: beq srchfnd /* Yeah... */ ! 1494: lwz r8,0(r8) /* Chain back to the previous frame */ ! 1495: b srchrets /* Ok, check again... */ ! 1496: ! 1497: srchfnd: stw r10,FM_LR_SAVE(r8) /* Modify return to come to us instead */ ! 1498: blr /* Finish up and get back here... */ ! 1499: ! 1500: /* ! 1501: * We come here when we've returned all the way to the interrupt handler. ! 1502: * That way we can enter the debugger with the registers and stack which ! 1503: * existed at the point of interruption. ! 1504: * ! 1505: * R3 points to the saved state at entry ! 1506: */ ! 1507: ! 1508: ENTRY(intercept_ret, TAG_NO_FRAME_USED) ! 1509: ! 1510: lis r6,HIGH_ADDR(EXT(kdb_trap)) /* Get the top part of the KDB enter routine */ ! 1511: mr r5,r3 /* Move saved state to the correct parameter */ ! 1512: ori r6,r6,LOW_ADDR(EXT(kdb_trap)) /* Get the last part of the KDB enter routine */ ! 1513: li r4,0 /* Set a code of 0 */ ! 1514: mr r13,r3 /* Save the saved state pointer in a non-volatile */ ! 1515: mtlr r6 /* Set the routine address */ ! 1516: li r3,-1 /* Show we had an interrupt type */ ! 1517: ! 1518: blrl /* Go enter KDB */ ! 1519: ! 1520: mr r3,r13 /* Put the saved state where expected */ ! 1521: b EXT(ihandler_ret) /* Go return from the interruption... */ ! 1522: ! 1523: #endif ! 1524: ! 1525: #if VERIFYSAVE ! 1526: ; ! 1527: ; Savearea chain verification ! 1528: ; ! 1529: ! 1530: versave: ! 1531: ! 1532: #if 0 ! 1533: ; ! 1534: ; Make sure that only the top FPU savearea is marked invalid ! 1535: ; ! 1536: ! 1537: lis r28,hi16(EXT(default_pset)) ; (TEST/DEBUG) ! 1538: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1539: ori r28,r28,lo16(EXT(default_pset)) ; (TEST/DEBUG) ! 1540: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1541: li r20,0 ; (TEST/DEBUG) ! 1542: lwz r26,0(r27) ; (TEST/DEBUG) ! 1543: lwz r27,psthreadcnt(r28) ; (TEST/DEBUG) ! 1544: mr. r26,r26 ; (TEST/DEBUG) ! 1545: lwz r28,psthreads(r28) ; (TEST/DEBUG) ! 1546: bnelr- ; (TEST/DEBUG) ! 1547: ! 1548: fcknxtth: mr. r27,r27 ; (TEST/DEBUG) ! 1549: beqlr- ; (TEST/DEBUG) ! 1550: ! 1551: lwz r26,THREAD_TOP_ACT(r28) ; (TEST/DEBUG) ! 1552: ! 1553: fckact: mr. r26,r26 ; (TEST/DEBUG) ! 1554: bne+ fckact2 ; (TEST/DEBUG) ! 1555: ! 1556: lwz r28,THREAD_PSTHRN(r28) ; (TEST/DEBUG) Next in line ! 1557: subi r27,r27,1 ; (TEST/DEBUG) ! 1558: b fcknxtth ; (TEST/DEBUG) ! 1559: ! 1560: fckact2: lwz r20,ACT_MACT_FPU(r26) ; (TEST/DEBUG) Get FPU chain ! 1561: mr. r20,r20 ; (TEST/DEBUG) Are there any? ! 1562: beq+ fcknact ; (TEST/DEBUG) No... ! 1563: ! 1564: fckact3: lwz r20,SAVprefp(r20) ; (TEST/DEBUG) Get next in list ! 1565: mr. r20,r20 ; (TEST/DEBUG) Check next savearea ! 1566: beq+ fcknact ; (TEST/DEBUG) No... ! 1567: ! 1568: lwz r29,SAVlvlfp(r20) ; (TEST/DEBUG) Get the level ! 1569: ! 1570: cmplwi r29,1 ; (TEST/DEBUG) Is it invalid?? ! 1571: bne+ fckact3 ; (TEST/DEBUG) Nope... ! 1572: ! 1573: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1574: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1575: stw r27,0(r27) ; (TEST/DEBUG) ! 1576: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1577: ! 1578: fcknact: lwz r26,ACT_LOWER(r26) ; (TEST/DEBUG) Next activation ! 1579: b fckact ; (TEST/DEBUG) ! 1580: #endif ! 1581: ! 1582: #if 1 ! 1583: ; ! 1584: ; Make sure there are no circular links in the float chain ! 1585: ; And that FP is marked busy in it. ! 1586: ; And the only the top is marked invalid. ! 1587: ; And that the owning PCB is correct. ! 1588: ; ! 1589: ! 1590: lis r28,hi16(EXT(default_pset)) ; (TEST/DEBUG) ! 1591: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1592: ori r28,r28,lo16(EXT(default_pset)) ; (TEST/DEBUG) ! 1593: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1594: li r20,0 ; (TEST/DEBUG) ! 1595: lwz r26,0(r27) ; (TEST/DEBUG) ! 1596: lwz r27,psthreadcnt(r28) ; (TEST/DEBUG) ! 1597: mr. r26,r26 ; (TEST/DEBUG) ! 1598: lwz r28,psthreads(r28) ; (TEST/DEBUG) ! 1599: bnelr- ; (TEST/DEBUG) ! 1600: ! 1601: fcknxtth: mr. r27,r27 ; (TEST/DEBUG) ! 1602: beqlr- ; (TEST/DEBUG) ! 1603: ! 1604: lwz r26,THREAD_TOP_ACT(r28) ; (TEST/DEBUG) ! 1605: ! 1606: fckact: mr. r26,r26 ; (TEST/DEBUG) ! 1607: bne+ fckact2 ; (TEST/DEBUG) ! 1608: ! 1609: lwz r28,THREAD_PSTHRN(r28) ; (TEST/DEBUG) Next in line ! 1610: subi r27,r27,1 ; (TEST/DEBUG) ! 1611: b fcknxtth ; (TEST/DEBUG) ! 1612: ! 1613: fckact2: lwz r20,ACT_MACT_FPU(r26) ; (TEST/DEBUG) Get FPU chain ! 1614: li r29,1 ; (TEST/DEBUG) ! 1615: li r22,0 ; (TEST/DEBUG) ! 1616: ! 1617: fckact3: mr. r20,r20 ; (TEST/DEBUG) Are there any? ! 1618: beq+ fckact5 ; (TEST/DEBUG) No... ! 1619: ! 1620: addi r22,r22,1 ; (TEST/DEBUG) Count chain depth ! 1621: ! 1622: lwz r21,SAVflags(r20) ; (TEST/DEBUG) Get the flags ! 1623: rlwinm. r21,r21,0,1,1 ; (TEST/DEBUG) FP busy? ! 1624: bne+ fckact3a ; (TEST/DEBUG) Yeah... ! 1625: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1626: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1627: stw r27,0(r27) ; (TEST/DEBUG) ! 1628: BREAKPOINT_TRAP ; (TEST/DEBUG) Die ! 1629: ! 1630: fckact3a: cmplwi r22,1 ; (TEST/DEBUG) At first SA? ! 1631: beq+ fckact3b ; (TEST/DEBUG) Yeah, invalid is ok... ! 1632: lwz r21,SAVlvlfp(r20) ; (TEST/DEBUG) Get level ! 1633: cmplwi r21,1 ; (TEST/DEBUG) Is it invalid? ! 1634: bne+ fckact3b ; (TEST/DEBUG) Nope, it is ok... ! 1635: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1636: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1637: stw r27,0(r27) ; (TEST/DEBUG) ! 1638: BREAKPOINT_TRAP ; (TEST/DEBUG) Die ! 1639: ! 1640: fckact3b: lwz r21,SAVact(r20) ; (TEST/DEBUG) Get the owner ! 1641: cmplw r21,r26 ; (TEST/DEBUG) Correct activation? ! 1642: beq+ fckact3c ; (TEST/DEBUG) Yup... ! 1643: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1644: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1645: stw r27,0(r27) ; (TEST/DEBUG) ! 1646: BREAKPOINT_TRAP ; (TEST/DEBUG) Die ! 1647: ! 1648: fckact3c: ; (TEST/DEBUG) ! 1649: lbz r21,SAVflags+3(r20) ; (TEST/DEBUG) Pick up the test byte ! 1650: mr. r21,r21 ; (TEST/DEBUG) marked? ! 1651: beq+ fckact4 ; (TEST/DEBUG) No, good... ! 1652: ! 1653: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1654: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1655: stw r27,0(r27) ; (TEST/DEBUG) ! 1656: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1657: ! 1658: fckact4: stb r29,SAVflags+3(r20) ; (TEST/DEBUG) Set the test byte ! 1659: lwz r20,SAVprefp(r20) ; (TEST/DEBUG) Next in list ! 1660: b fckact3 ; (TEST/DEBUG) Try it... ! 1661: ! 1662: fckact5: lwz r20,ACT_MACT_FPU(r26) ; (TEST/DEBUG) Get FPU chain ! 1663: li r29,0 ; (TEST/DEBUG) ! 1664: ! 1665: fckact6: mr. r20,r20 ; (TEST/DEBUG) Are there any? ! 1666: beq+ fcknact ; (TEST/DEBUG) No... ! 1667: ! 1668: stb r29,SAVflags+3(r20) ; (TEST/DEBUG) Clear the test byte ! 1669: lwz r20,SAVprefp(r20) ; (TEST/DEBUG) Next in list ! 1670: b fckact6 ; (TEST/DEBUG) Try it... ! 1671: ! 1672: fcknact: lwz r26,ACT_LOWER(r26) ; (TEST/DEBUG) Next activation ! 1673: b fckact ; (TEST/DEBUG) ! 1674: #endif ! 1675: ! 1676: ! 1677: #if 0 ! 1678: ; ! 1679: ; Make sure in use count matches found savearea. This is ! 1680: ; not always accurate. There is a variable "fuzz" factor in count. ! 1681: ! 1682: lis r28,hi16(EXT(default_pset)) ; (TEST/DEBUG) ! 1683: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1684: ori r28,r28,lo16(EXT(default_pset)) ; (TEST/DEBUG) ! 1685: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1686: li r20,0 ; (TEST/DEBUG) ! 1687: lwz r26,0(r27) ; (TEST/DEBUG) ! 1688: lwz r27,psthreadcnt(r28) ; (TEST/DEBUG) ! 1689: mr. r26,r26 ; (TEST/DEBUG) ! 1690: lwz r28,psthreads(r28) ; (TEST/DEBUG) ! 1691: bnelr- ; (TEST/DEBUG) ! 1692: ! 1693: cknxtth: mr. r27,r27 ; (TEST/DEBUG) ! 1694: beq- cktotal ; (TEST/DEBUG) ! 1695: ! 1696: lwz r26,THREAD_TOP_ACT(r28) ; (TEST/DEBUG) ! 1697: ! 1698: ckact: mr. r26,r26 ; (TEST/DEBUG) ! 1699: bne+ ckact2 ; (TEST/DEBUG) ! 1700: ! 1701: lwz r28,THREAD_PSTHRN(r28) ; (TEST/DEBUG) Next in line ! 1702: subi r27,r27,1 ; (TEST/DEBUG) ! 1703: b cknxtth ; (TEST/DEBUG) ! 1704: ! 1705: ckact2: lwz r29,ACT_MACT_PCB(r26) ; (TEST/DEBUG) ! 1706: ! 1707: cknorm: mr. r29,r29 ; (TEST/DEBUG) ! 1708: beq- cknormd ; (TEST/DEBUG) ! 1709: ! 1710: addi r20,r20,1 ; (TEST/DEBUG) Count normal savearea ! 1711: ! 1712: lwz r29,SAVprev(r29) ; (TEST/DEBUG) ! 1713: b cknorm ; (TEST/DEBUG) ! 1714: ! 1715: cknormd: lwz r29,ACT_MACT_FPU(r26) ; (TEST/DEBUG) ! 1716: ! 1717: ckfpu: mr. r29,r29 ; (TEST/DEBUG) ! 1718: beq- ckfpud ; (TEST/DEBUG) ! 1719: ! 1720: lwz r21,SAVflags(r29) ; (TEST/DEBUG) ! 1721: rlwinm. r21,r21,0,0,0 ; (TEST/DEBUG) See if already counted ! 1722: bne- cknfpu ; (TEST/DEBUG) ! 1723: ! 1724: addi r20,r20,1 ; (TEST/DEBUG) Count fpu savearea ! 1725: ! 1726: cknfpu: lwz r29,SAVprefp(r29) ; (TEST/DEBUG) ! 1727: b ckfpu ; (TEST/DEBUG) ! 1728: ! 1729: ckfpud: lwz r29,ACT_MACT_VMX(r26) ; (TEST/DEBUG) ! 1730: ! 1731: ckvmx: mr. r29,r29 ; (TEST/DEBUG) ! 1732: beq- ckvmxd ; (TEST/DEBUG) ! 1733: ! 1734: lwz r21,SAVflags(r29) ; (TEST/DEBUG) ! 1735: rlwinm. r21,r21,0,0,1 ; (TEST/DEBUG) See if already counted ! 1736: bne- cknvmx ; (TEST/DEBUG) ! 1737: ! 1738: addi r20,r20,1 ; (TEST/DEBUG) Count vector savearea ! 1739: ! 1740: cknvmx: lwz r29,SAVprevec(r29) ; (TEST/DEBUG) ! 1741: b ckvmx ; (TEST/DEBUG) ! 1742: ! 1743: ckvmxd: lwz r26,ACT_LOWER(r26) ; (TEST/DEBUG) Next activation ! 1744: b ckact ; (TEST/DEBUG) ! 1745: ! 1746: cktotal: lis r28,hi16(EXT(saveanchor)) ; (TEST/DEBUG) ! 1747: lis r27,hi16(EXT(real_ncpus)) ; (TEST/DEBUG) ! 1748: ori r28,r28,lo16(EXT(saveanchor)) ; (TEST/DEBUG) ! 1749: ori r27,r27,lo16(EXT(real_ncpus)) ; (TEST/DEBUG) ! 1750: ! 1751: lwz r21,SVinuse(r28) ; (TEST/DEBUG) ! 1752: lwz r27,0(r27) ; (TEST/DEBUG) Get the number of CPUs ! 1753: sub. r29,r21,r20 ; (TEST/DEBUG) Get number accounted for ! 1754: blt- badsave ; (TEST/DEBUG) Have too many in use... ! 1755: sub r26,r29,r27 ; (TEST/DEBUG) Should be 1 unaccounted for for each processor ! 1756: cmpwi r26,10 ; (TEST/DEBUG) Allow a 10 area slop factor ! 1757: bltlr+ ; (TEST/DEBUG) ! 1758: ! 1759: badsave: lis r27,hi16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1760: ori r27,r27,lo16(EXT(DebugWork)) ; (TEST/DEBUG) ! 1761: stw r27,0(r27) ; (TEST/DEBUG) ! 1762: BREAKPOINT_TRAP ; (TEST/DEBUG) ! 1763: #endif ! 1764: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.