|
|
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: #include <assym.s> ! 23: #include <debug.h> ! 24: #include <cpus.h> ! 25: #include <db_machine_commands.h> ! 26: #include <mach_rt.h> ! 27: ! 28: #include <mach_debug.h> ! 29: #include <ppc/asm.h> ! 30: #include <ppc/proc_reg.h> ! 31: #include <ppc/exception.h> ! 32: #include <ppc/Performance.h> ! 33: #include <ppc/exception.h> ! 34: #include <ppc/pmap_internals.h> ! 35: #include <mach/ppc/vm_param.h> ! 36: ! 37: .text ! 38: ! 39: /* ! 40: * This routine will add a savearea block to the free list. ! 41: * Note really well: we can take NO exceptions of any kind, ! 42: * including a PTE miss once the savearea lock is held. That's ! 43: * a guaranteed deadlock. That means we must disable for interrutions ! 44: * and turn all translation off. ! 45: * ! 46: * Note that the savearea list should NEVER be empty ! 47: */ ! 48: ! 49: ENTRY(save_queue,TAG_NO_FRAME_USED) ! 50: ! 51: ! 52: mfmsr r12 /* Get the MSR */ ! 53: lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ ! 54: andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */ ! 55: ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ ! 56: mtmsr r11 /* Make the MSR current */ ! 57: ! 58: isync ! 59: ! 60: #if 0 ! 61: rlwinm. r3,r3,0,0,19 /* (TEST/DEBUG) */ ! 62: bne+ notraceit /* (TEST/DEBUG) */ ! 63: BREAKPOINT_TRAP /* (TEST/DEBUG) */ ! 64: notraceit: /* (TEST/DEBUG) */ ! 65: #else ! 66: rlwinm r3,r3,0,0,19 /* Make sure it's clean and tidy */ ! 67: #endif ! 68: ! 69: lwarx r9,0,r10 ; ? ! 70: ! 71: sqlck: lwarx r9,0,r10 /* Grab the lock value */ ! 72: li r8,1 /* Use part of the delay time */ ! 73: mr. r9,r9 /* Is it locked? */ ! 74: bne- sqlcks /* Yeah, wait for it to clear... */ ! 75: stwcx. r8,0,r10 /* Try to seize that there durn lock */ ! 76: beq+ sqlckd /* Got it... */ ! 77: b sqlck /* Collision, try again... */ ! 78: ! 79: sqlcks: lwz r9,SVlock(r10) /* Get that lock in here */ ! 80: mr. r9,r9 /* Is it free yet? */ ! 81: beq+ sqlck /* Yeah, try for it again... */ ! 82: b sqlcks /* Sniff away... */ ! 83: ! 84: sqlckd: isync /* Make sure translation is off */ ! 85: lwz r7,SVfree(r10) /* Get the free save area list anchor */ ! 86: lwz r6,SVcount(r10) /* Get the total count of saveareas */ ! 87: stw r3,SVfree(r10) /* Queue in the new one */ ! 88: addi r6,r6,sac_cnt /* Count the ones we are linking in */ ! 89: stw r7,SACnext(r3) /* Queue the old first one off of us */ ! 90: li r8,0 /* Get a free lock value */ ! 91: stw r6,SVcount(r10) /* Save the new count */ ! 92: ! 93: sync /* Make sure everything is done */ ! 94: stw r8,SVlock(r10) /* Unlock the savearea chain */ ! 95: ! 96: mtmsr r12 /* Restore interrupts and translation */ ! 97: isync /* Dump any speculations */ ! 98: ! 99: #if 0 ! 100: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 101: li r2,0x2201 ; (TEST/DEBUG) ! 102: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 103: sc /* (TEST/DEBUG) */ ! 104: #endif ! 105: ! 106: blr /* Leave... */ ! 107: ! 108: ! 109: /* ! 110: * This routine will find and remove an empty savearea block from the free list. ! 111: * Note really well: we can take NO exceptions of any kind, ! 112: * including a PTE miss once the savearea lock is held. That's ! 113: * a guaranteed deadlock. That means we must disable for interrutions ! 114: * and turn all translation off. ! 115: * ! 116: * We pass back the virtual address of the one we just released ! 117: * or a zero if none to free. ! 118: * ! 119: * Note that the savearea list should NEVER be empty ! 120: */ ! 121: ! 122: ENTRY(save_dequeue,TAG_NO_FRAME_USED) ! 123: ! 124: ! 125: mfmsr r12 /* Get the MSR */ ! 126: lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ ! 127: andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */ ! 128: ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ ! 129: mtmsr r11 /* Make the MSR current */ ! 130: isync /* Make sure translation is off */ ! 131: ! 132: lwarx r9,0,r10 ; ? ! 133: ! 134: sdqlck: lwarx r9,0,r10 /* Grab the lock value */ ! 135: li r8,1 /* Use part of the delay time */ ! 136: mr. r9,r9 /* Is it locked? */ ! 137: bne- sdqlcks /* Yeah, wait for it to clear... */ ! 138: stwcx. r8,0,r10 /* Try to seize that there durn lock */ ! 139: beq+ sdqlckd /* Got it... */ ! 140: b sdqlck /* Collision, try again... */ ! 141: ! 142: sdqlcks: lwz r9,SVlock(r10) /* Get that lock in here */ ! 143: mr. r9,r9 /* Is it free yet? */ ! 144: beq+ sdqlck /* Yeah, try for it again... */ ! 145: b sdqlcks /* Sniff away... */ ! 146: ! 147: ! 148: sdqlckd: lwz r3,SVfree(r10) /* Get the free save area list anchor */ ! 149: la r5,SVfree(r10) /* Remember that the we're just starting out */ ! 150: lwz r6,SVcount(r10) /* Get the total count of saveareas for later */ ! 151: lis r8,sac_empty>>16 /* Get the empty block indication */ ! 152: ! 153: sdqchk: lwz r4,SACalloc(r3) /* Get the allocation flags */ ! 154: lwz r9,SACflags(r3) /* Get the flags */ ! 155: lwz r7,SACnext(r3) /* Point on to the next one */ ! 156: andis. r9,r9,hi16(sac_perm) /* Is this permanently allocated? */ ! 157: cmplw cr1,r4,r8 /* Does this look empty? */ ! 158: bne- sdqperm /* It's permanent, can't release... */ ! 159: beq- cr1,sdqfnd /* Yeah, empty... */ ! 160: ! 161: sdqperm: la r5,SACnext(r3) /* Remember the last guy */ ! 162: mr. r3,r7 /* Any more left? */ ! 163: bne+ sdqchk /* Yeah... */ ! 164: b sdqunlk /* Nope, just go unlock and leave... */ ! 165: ! 166: sdqfnd: subi r6,r6,sac_cnt /* Back off the number of saveareas in here */ ! 167: stw r7,0(r5) /* Dequeue our guy */ ! 168: lwz r9,SACvrswap(r3) /* Get addressing conversion */ ! 169: stw r6,SVcount(r10) /* Back off the count for this block */ ! 170: xor r3,r3,r9 /* Flip to virtual addressing */ ! 171: ! 172: sdqunlk: li r8,0 /* Get a free lock value */ ! 173: sync /* Make sure everything is done */ ! 174: stw r8,SVlock(r10) /* Unlock the savearea chain */ ! 175: ! 176: mtmsr r12 /* Restore interrupts and translation */ ! 177: isync /* Dump any speculations */ ! 178: ! 179: #if 0 ! 180: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 181: li r2,0x2202 ; (TEST/DEBUG) ! 182: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 183: sc /* (TEST/DEBUG) */ ! 184: #endif ! 185: ! 186: blr /* Leave... */ ! 187: ! 188: ! 189: ! 190: /* ! 191: * This routine will obtain a savearea from the free list. ! 192: * Note really well: we can take NO exceptions of any kind, ! 193: * including a PTE miss once the savearea lock is held. That's ! 194: * a guaranteed deadlock. That means we must disable for interrutions ! 195: * and turn all translation off. ! 196: * ! 197: * We pass back the virtual address of the one we just obtained ! 198: * or a zero if none to allocate. ! 199: * ! 200: * Note that the savearea list should NEVER be empty ! 201: * NOTE!!! NEVER USE R0, R2, or R12 IN HERE THAT WAY WE DON'T NEED A ! 202: * STACK FRAME IN FPU_SAVE, FPU_SWITCH, VEC_SAVE, OR VEC_SWITCH. ! 203: */ ! 204: ! 205: ENTRY(save_get_phys,TAG_NO_FRAME_USED) ! 206: ! 207: cmplw cr1,r1,r1 ; Set CR1_eq to indicate we want physical address ! 208: b csaveget ; Join the common... ! 209: ! 210: ENTRY(save_get,TAG_NO_FRAME_USED) ! 211: ! 212: cmplwi cr1,r1,0 ; Set CR1_ne to indicate we want virutal address ! 213: ! 214: csaveget: mfmsr r11 /* Get the MSR */ ! 215: lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ ! 216: andi. r8,r11,0x7FCF /* Turn off all translation and 'rupts */ ! 217: ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ ! 218: mtmsr r8 /* Make the MSR current */ ! 219: isync ; Make sure it is done ! 220: ! 221: lwarx r9,0,r10 ; ? ! 222: ! 223: sglck: lwarx r9,0,r10 /* Grab the lock value */ ! 224: li r7,1 /* Use part of the delay time */ ! 225: mr. r9,r9 /* Is it locked? */ ! 226: bne- sglcks /* Yeah, wait for it to clear... */ ! 227: stwcx. r7,0,r10 /* Try to seize that there durn lock */ ! 228: beq+ sglckd /* Got it... */ ! 229: b sglck /* Collision, try again... */ ! 230: ! 231: sglcks: lwz r9,SVlock(r10) /* Get that lock in here */ ! 232: mr. r9,r9 /* Is it free yet? */ ! 233: beq+ sglck /* Yeah, try for it again... */ ! 234: b sglcks /* Sniff away... */ ! 235: ! 236: sglckd: isync /* Make sure translation is off */ ! 237: lwz r8,SVfree(r10) /* Get the head of the save area list */ ! 238: lwz r9,SVinuse(r10) /* Get the inuse field */ ! 239: ! 240: lwz r7,SACalloc(r8) /* Pick up the allocation bits */ ! 241: lwz r5,SACvrswap(r8) /* Get real to virtual translation */ ! 242: mr. r7,r7 /* Can we use the first one? */ ! 243: blt use1st /* Yeah... */ ! 244: ! 245: andis. r7,r7,0x8000 /* Show we used the second and remember if it was the last */ ! 246: addi r3,r8,0x0800 /* Point to the first one */ ! 247: b gotsave /* We have the area now... */ ! 248: ! 249: use1st: andis. r7,r7,0x4000 /* Mark first gone and remember if empty */ ! 250: mr r3,r8 /* Set the save area */ ! 251: ! 252: gotsave: stw r7,SACalloc(r8) /* Put back the allocation bits */ ! 253: bne nodqsave /* There's still an empty slot, don't dequeue... */ ! 254: ! 255: lwz r4,SACnext(r8) /* Get the next in line */ ! 256: stw r4,SVfree(r10) /* Dequeue our now empty save area block */ ! 257: ! 258: nodqsave: lis r6,HIGH_ADDR(SAVattach) /* Show that it is attached for now */ ! 259: li r4,0 /* Clear this for the lock */ ! 260: stw r6,SAVflags(r3) /* Set the flags to attached */ ! 261: addi r9,r9,1 /* Bump up the inuse count */ ! 262: stw r4,SAVprev(r3) /* Make sure that backchain is clear */ ! 263: stw r9,SVinuse(r10) /* Set the inuse field */ ! 264: sync /* Make sure all stores are done */ ! 265: stw r4,SVlock(r10) /* Unlock both save and trace areas */ ! 266: mtmsr r11 /* Restore translation and exceptions */ ! 267: isync /* Make sure about it */ ! 268: ! 269: #if 0 ! 270: mr r11,r0 /* (TEST/DEBUG) */ ! 271: mr r7,r2 /* (TEST/DEBUG) */ ! 272: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 273: li r2,0x2203 ; (TEST/DEBUG) ! 274: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 275: sc /* (TEST/DEBUG) */ ! 276: mr r0,r11 /* (TEST/DEBUG) */ ! 277: mr r2,r7 /* (TEST/DEBUG) */ ! 278: #endif ! 279: ! 280: li r7,0 ; NOTE WELL: we set R7 to zero for vector and float saving code in cswtch.s ! 281: beqlr- cr1 ; Return now if we want the physical address ! 282: xor r3,r3,r5 /* Get the virtual address */ ! 283: blr /* Leave... */ ! 284: ! 285: ! 286: /* ! 287: * This routine will return a savearea to the free list. ! 288: * Note really well: we can take NO exceptions of any kind, ! 289: * including a PTE miss once the savearea lock is held. That's ! 290: * a guaranteed deadlock. That means we must disable for interrutions ! 291: * and turn all translation off. ! 292: * ! 293: * We take a virtual address. ! 294: * ! 295: */ ! 296: ! 297: ENTRY(save_ret,TAG_NO_FRAME_USED) ! 298: ! 299: #if 0 ! 300: cmplwi r3,0x1000 ; (TEST/DEBUG) ! 301: bgt+ notpage0 ; (TEST/DEBUG) ! 302: BREAKPOINT_TRAP /* (TEST/DEBUG) */ ! 303: ! 304: notpage0: rlwinm r6,r3,0,0,19 /* (TEST/DEBUG) */ ! 305: rlwinm r7,r3,21,31,31 /* (TEST/DEBUG) */ ! 306: lis r8,0x8000 /* (TEST/DEBUG) */ ! 307: lwz r6,SACalloc(r6) /* (TEST/DEBUG) */ ! 308: srw r8,r8,r7 /* (TEST/DEBUG) */ ! 309: and. r8,r8,r6 /* (TEST/DEBUG) */ ! 310: beq+ nodoublefret /* (TEST/DEBUG) */ ! 311: BREAKPOINT_TRAP /* (TEST/DEBUG) */ ! 312: ! 313: nodoublefret: /* (TEST/DEBUG) */ ! 314: #endif ! 315: ! 316: lwz r7,SAVflags(r3) /* Get the flags */ ! 317: rlwinm r6,r3,0,0,19 /* Round back down to the savearea page block */ ! 318: andis. r7,r7,HIGH_ADDR(SAVinuse) /* Still in use? */ ! 319: mfmsr r12 /* Get the MSR */ ! 320: bnelr- /* Still in use, just leave... */ ! 321: lwz r5,SACvrswap(r6) /* Get the conversion to real */ ! 322: lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ ! 323: andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */ ! 324: ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ ! 325: mtmsr r11 /* Make the MSR current */ ! 326: isync /* Make sure translation is off */ ! 327: ! 328: mfsprg r11,1 /* Get the active save area */ ! 329: xor r3,r3,r5 /* Get the real address of the savearea */ ! 330: cmplw r11,r3 /* Are we trying to toss the active one? */ ! 331: xor r6,r6,r5 /* Make the savearea block real also */ ! 332: beq- srbigtimepanic /* This is a no-no... */ ! 333: ! 334: rlwinm r7,r3,21,31,31 /* Get position of savearea in block */ ! 335: lis r8,0x8000 /* Build a bit mask and assume first savearea */ ! 336: srw r8,r8,r7 /* Get bit position of do deallocate */ ! 337: ! 338: lwarx r11,0,r10 ; ? ! 339: ! 340: srlck: lwarx r11,0,r10 /* Grab the lock value */ ! 341: li r7,1 /* Use part of the delay time */ ! 342: mr. r11,r11 /* Is it locked? */ ! 343: bne- srlcks /* Yeah, wait for it to clear... */ ! 344: stwcx. r7,0,r10 /* Try to seize that there durn lock */ ! 345: beq+ srlckd /* Got it... */ ! 346: b srlck /* Collision, try again... */ ! 347: ! 348: srlcks: lwz r11,SVlock(r10) /* Get that lock in here */ ! 349: mr. r11,r11 /* Is it free yet? */ ! 350: beq+ srlck /* Yeah, try for it again... */ ! 351: b srlcks /* Sniff away... */ ! 352: ! 353: srlckd: isync /* Toss preexecutions */ ! 354: lwz r11,SACalloc(r6) /* Get the allocation for this block */ ! 355: lwz r7,SVinuse(r10) /* Get the in use count */ ! 356: or r11,r11,r8 /* Turn on our bit */ ! 357: subi r7,r7,1 /* We released one, adjust count */ ! 358: cmplw r11,r8 /* Is our's the only one free? */ ! 359: stw r7,SVinuse(r10) /* Save out count */ ! 360: stw r11,SACalloc(r6) /* Save it out */ ! 361: bne+ srtrest /* Nope, then the block is already on the free list */ ! 362: ! 363: lwz r11,SVfree(r10) /* Get the old head of the free list */ ! 364: stw r6,SVfree(r10) /* Point the head at us now */ ! 365: stw r11,SACnext(r6) /* Point us at the old last */ ! 366: ! 367: srtrest: li r8,0 /* Get set to clear the savearea lock */ ! 368: sync /* Make sure it's all out there */ ! 369: stw r8,SVlock(r10) /* Unlock it */ ! 370: mtmsr r12 /* Restore interruptions and translation */ ! 371: isync ! 372: ! 373: #if 0 ! 374: lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 375: li r2,0x2204 ; (TEST/DEBUG) ! 376: oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ ! 377: sc /* (TEST/DEBUG) */ ! 378: #endif ! 379: ! 380: blr /* Go away... */ ! 381: ! 382: srbigtimepanic: ! 383: lis r6,HIGH_ADDR(EXT(panic)) /* First half of panic call */ ! 384: lis r3,HIGH_ADDR(EXT(srfreeactive)) /* First half of panic string */ ! 385: ori r6,r6,LOW_ADDR(EXT(panic)) /* Second half of panic call */ ! 386: ori r3,r3,LOW_ADDR(EXT(srfreeactive)) /* Second half of panic string */ ! 387: mtlr r6 /* Get the address of the panic routine */ ! 388: mtmsr r12 /* Restore interruptions and translation */ ! 389: isync ! 390: blrl /* Panic... */ ! 391: ! 392: .data ! 393: EXT(srfreeactive): ! 394: STRINGD "save_ret: Attempting to release the active savearea!!!!" ! 395: .text ! 396: ! 397: ! 398: /* ! 399: * This routine will return the virtual address of the first free savearea ! 400: * block and disable for interruptions. ! 401: * Note really well: this is only for debugging, don't expect it to always work! ! 402: * ! 403: * We take a virtual address in R4 to save the original MSR, and ! 404: * return the virtual address. ! 405: * ! 406: */ ! 407: ! 408: ENTRY(save_deb,TAG_NO_FRAME_USED) ! 409: ! 410: mfmsr r12 /* Get the MSR */ ! 411: lis r10,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor */ ! 412: stw r12,0(r3) /* Save it */ ! 413: andi. r11,r12,0x7FCF /* Turn off all translation and 'rupts */ ! 414: ori r10,r10,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ ! 415: mtmsr r11 /* Make the MSR current */ ! 416: isync /* Make sure translation is off */ ! 417: lwz r3,SVfree(r10) /* Get the physical first in list */ ! 418: andi. r11,r12,0x7FFF /* Clear only interruption */ ! 419: lwz r5,SACvrswap(r3) /* Get the conversion to virtual */ ! 420: mtmsr r11 /* Restore DAT but not INT */ ! 421: xor r3,r3,r5 /* Make it virtual */ ! 422: isync ! 423: blr ! 424: ! 425: ! 426: ! 427: ! 428:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.