|
|
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: #include <debug.h> ! 27: #include <ppc/asm.h> ! 28: #include <ppc/proc_reg.h> ! 29: #include <mach/ppc/vm_param.h> ! 30: #include <assym.s> ! 31: #include <sys/errno.h> ! 32: ! 33: /* ! 34: * void pmap_zero_page(vm_offset_t pa) ! 35: * ! 36: * zero a page of physical memory. ! 37: */ ! 38: ! 39: #if DEBUG ! 40: /* C debug stub in pmap.c calls this */ ! 41: ENTRY(pmap_zero_page_assembler, TAG_NO_FRAME_USED) ! 42: #else ! 43: ENTRY(pmap_zero_page, TAG_NO_FRAME_USED) ! 44: #endif /* DEBUG */ ! 45: ! 46: mfmsr r6 /* Get the MSR */ ! 47: rlwinm r7, r6, 0, MSR_DR_BIT+1, MSR_DR_BIT-1 /* Turn off DR */ ! 48: rlwinm r7,r7,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Disable interruptions ! 49: li r4,PPC_PGBYTES-CACHE_LINE_SIZE /* Point to the end of the page */ ! 50: mtmsr r7 /* Set MSR to DR off */ ! 51: isync /* Ensure data translations are off */ ! 52: ! 53: ! 54: .L_phys_zero_loop: ! 55: subic. r5,r4,CACHE_LINE_SIZE /* Point to the next one */ ! 56: dcbz r4, r3 /* Clear the whole thing to 0s */ ! 57: subi r4,r5,CACHE_LINE_SIZE /* Point to the next one */ ! 58: dcbz r5, r3 /* Clear the next to zeros */ ! 59: bgt+ .L_phys_zero_loop /* Keep going until we do the page... */ ! 60: ! 61: sync /* Make sure they're all done */ ! 62: li r4,PPC_PGBYTES-CACHE_LINE_SIZE /* Point to the end of the page */ ! 63: ! 64: .L_inst_inval_loop: ! 65: subic. r5,r4,CACHE_LINE_SIZE /* Point to the next one */ ! 66: icbi r4, r3 /* Clear the whole thing to 0s */ ! 67: subi r4,r5,CACHE_LINE_SIZE /* Point to the next one */ ! 68: icbi r5, r3 /* Clear the next to zeros */ ! 69: bgt+ .L_inst_inval_loop /* Keep going until we do the page... */ ! 70: ! 71: sync /* Make sure they're all done */ ! 72: ! 73: mtmsr r6 /* Restore original translations */ ! 74: isync /* Ensure data translations are on */ ! 75: ! 76: blr ! 77: ! 78: /* void ! 79: * phys_copy(src, dst, bytecount) ! 80: * vm_offset_t src; ! 81: * vm_offset_t dst; ! 82: * int bytecount ! 83: * ! 84: * This routine will copy bytecount bytes from physical address src to physical ! 85: * address dst. ! 86: */ ! 87: ! 88: ENTRY(phys_copy, TAG_NO_FRAME_USED) ! 89: ! 90: /* Switch off data translations */ ! 91: mfmsr r6 ! 92: rlwinm r7, r6, 0, MSR_DR_BIT+1, MSR_DR_BIT-1 ! 93: rlwinm r7, r7, 0, MSR_EE_BIT+1, MSR_EE_BIT-1 ! 94: mtmsr r7 ! 95: isync /* Ensure data translations are off */ ! 96: ! 97: subi r3, r3, 4 ! 98: subi r4, r4, 4 ! 99: ! 100: cmpwi r5, 3 ! 101: ble- .L_phys_copy_bytes ! 102: .L_phys_copy_loop: ! 103: lwz r0, 4(r3) ! 104: addi r3, r3, 4 ! 105: subi r5, r5, 4 ! 106: stw r0, 4(r4) ! 107: addi r4, r4, 4 ! 108: cmpwi r5, 3 ! 109: bgt+ .L_phys_copy_loop ! 110: ! 111: /* If no leftover bytes, we're done now */ ! 112: cmpwi r5, 0 ! 113: beq+ .L_phys_copy_done ! 114: ! 115: .L_phys_copy_bytes: ! 116: addi r3, r3, 3 ! 117: addi r4, r4, 3 ! 118: .L_phys_copy_byte_loop: ! 119: lbz r0, 1(r3) ! 120: addi r3, r3, 1 ! 121: subi r5, r5, 1 ! 122: stb r0, 1(r4) ! 123: addi r4, r4, 1 ! 124: cmpwi r5, 0 ! 125: bne+ .L_phys_copy_byte_loop ! 126: ! 127: .L_phys_copy_done: ! 128: mtmsr r6 /* Restore original translations */ ! 129: isync /* Ensure data translations are off */ ! 130: ! 131: blr ! 132: ! 133: /* void ! 134: * pmap_copy_page(src, dst) ! 135: * vm_offset_t src; ! 136: * vm_offset_t dst; ! 137: * ! 138: * This routine will copy the physical page src to physical page dst ! 139: * ! 140: * This routine assumes that the src and dst are page aligned and that the ! 141: * destination is cached. ! 142: * ! 143: * We also must assume that noone will be executing within the destination ! 144: * page. We also assume that this will be used for paging ! 145: * ! 146: */ ! 147: ! 148: #if DEBUG ! 149: /* if debug, we have a little piece of C around this ! 150: * in pmap.c that gives some trace ability ! 151: */ ! 152: ENTRY(pmap_copy_page_assembler, TAG_NO_FRAME_USED) ! 153: #else ! 154: ENTRY(pmap_copy_page, TAG_NO_FRAME_USED) ! 155: #endif /* DEBUG */ ! 156: ! 157: #if 0 ! 158: mfpvr r9 ; Get the PVR ! 159: rlwinm r9,r9,16,16,31 ; Isolate the PPC processor ! 160: cmplwi r9,PROCESSOR_VERSION_Max ; Do we have Altivec? ! 161: beq+ wegotaltivec ; Yeah... ! 162: #endif ! 163: ! 164: mfmsr r9 ; Get the MSR ! 165: stwu r1,-(FM_SIZE+32)(r1) ; Make a frame for us ! 166: rlwinm r7,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Disable interruptions ! 167: ori r7,r7,lo16(MASK(MSR_FP)) ; Turn on the FPU ! 168: mtmsr r7 ; Disable rupts and enable FPU ! 169: isync ! 170: ! 171: stfd f0,FM_SIZE+0(r1) ; Save an FP register ! 172: rlwinm r7,r7,0,MSR_DR_BIT+1,MSR_DR_BIT-1 ; Clear the DDAT bit ! 173: stfd f1,FM_SIZE+8(r1) ; Save an FP register ! 174: addi r6,r3,PPC_PGBYTES ; Point to the start of the next page ! 175: stfd f2,FM_SIZE+16(r1) ; Save an FP register ! 176: mr r8,r4 ; Save the destination ! 177: stfd f3,FM_SIZE+24(r1) ; Save an FP register ! 178: ! 179: mtmsr r7 ; Set the new MSR ! 180: isync ; Ensure data translations are off ! 181: ! 182: dcbt br0, r3 /* Start in first input line */ ! 183: li r5, CACHE_LINE_SIZE /* Get the line size */ ! 184: ! 185: .L_pmap_copy_page_loop: ! 186: dcbz 0, r4 /* Allocate a line for the output */ ! 187: lfd f0, 0(r3) /* Get first 8 */ ! 188: lfd f1, 8(r3) /* Get second 8 */ ! 189: lfd f2, 16(r3) /* Get third 8 */ ! 190: stfd f0, 0(r4) /* Put first 8 */ ! 191: dcbt r5, r3 /* Start next line coming in */ ! 192: lfd f3, 24(r3) /* Get fourth 8 */ ! 193: stfd f1, 8(r4) /* Put second 8 */ ! 194: addi r3,r3,CACHE_LINE_SIZE /* Point to the next line in */ ! 195: stfd f2, 16(r4) /* Put third 8 */ ! 196: cmplw cr0,r3,r6 /* See if we're finished yet */ ! 197: stfd f3, 24(r4) /* Put fourth 8 */ ! 198: dcbst br0,r4 /* Force it out */ ! 199: addi r4,r4,CACHE_LINE_SIZE /* Point to the next line out */ ! 200: blt+ .L_pmap_copy_page_loop /* Copy the whole page */ ! 201: ! 202: sync /* Make sure they're all done */ ! 203: li r4,PPC_PGBYTES-CACHE_LINE_SIZE /* Point to the end of the page */ ! 204: ! 205: invalinst: ! 206: subic. r5,r4,CACHE_LINE_SIZE /* Point to the next one */ ! 207: icbi r4, r8 /* Trash the i-cache */ ! 208: subi r4,r5,CACHE_LINE_SIZE /* Point to the next one */ ! 209: icbi r5, r8 /* Trash the i-cache */ ! 210: bgt+ invalinst /* Keep going until we do the page... */ ! 211: ! 212: rlwimi r7,r9,0,MSR_DR_BIT,MSR_DR_BIT ; Set DDAT if on ! 213: sync ; Make sure all invalidates done ! 214: ! 215: mtmsr r7 ; Set DDAT correctly ! 216: isync ! 217: ! 218: lfd f0,FM_SIZE+0(r1) ; Restore an FP register ! 219: lfd f1,FM_SIZE+8(r1) ; Restore an FP register ! 220: lfd f2,FM_SIZE+16(r1) ; Restore an FP register ! 221: lfd f3,FM_SIZE+24(r1) ; Restore an FP register ! 222: ! 223: lwz r1,0(r1) ; Pop up the stack ! 224: ! 225: mtmsr r9 ; Turn off FPU now and maybe rupts back on ! 226: isync ! 227: blr ! 228: ! 229: #if 1 ! 230: ; ! 231: ; This is not very optimal. We just do it here for a test of ! 232: ; Altivec in the kernel. ! 233: ; ! 234: wegotaltivec: ! 235: mfmsr r9 ; Get the MSR ! 236: lis r8,hi16(0xC0000000) ; Make sure we keep the first 2 vector registers ! 237: rlwinm r7,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Disable interruptions ! 238: lis r6,lo16(2*256+128) ; Specify 128 blocks of 2 vectors each ! 239: rlwinm r7,r7,0,MSR_DR_BIT+1,MSR_DR_BIT-1 ; Clear the DDAT bit ! 240: ori r6,r6,32 ; Set a 32-byte stride ! 241: mtsprg 256,r8 ; Set VRSave ! 242: mtmsr r7 ; Disable rupts and turn xlate off ! 243: isync ! 244: ! 245: dstt r3,r6,3 ; Stream in the page ! 246: addi r11,r3,4096 ; Point to the next page ! 247: li r10,16 ; Get vector size ! 248: ! 249: avmovepg: lvxl v0,br0,r3 ; Get first half of line ! 250: dcba br0,r4 ; Allocate output ! 251: lvxl v1,r10,r3 ; Get second half of line ! 252: stvxl v0,br0,r4 ; Save first half of line ! 253: addi r3,r3,32 ; Point to the next line ! 254: icbi br0,r4 ; Make the icache go away also ! 255: stvxl v1,r10,r4 ; Save second half of line ! 256: cmplw r3,r11 ; Have we reached the next page? ! 257: dcbst br0,r4 ; Make sure the line is on its way out ! 258: addi r4,r4,32 ; Point to the next line ! 259: blt+ avmovepg ; Move the next line... ! 260: ! 261: li r8,0 ; Clear this ! 262: sync ; Make sure all the memory stuff is done ! 263: mtsprg 256,r8 ; Show we are not using VRs any more ! 264: mtmsr r9 ; Translation and interruptions back on ! 265: isync ! 266: blr ! 267: #endif ! 268: ! 269: ! 270: ! 271: ! 272: /* ! 273: * int ! 274: * copyin(src, dst, count) ! 275: * vm_offset_t src; ! 276: * vm_offset_t dst; ! 277: * int count; ! 278: * ! 279: */ ! 280: ! 281: ENTRY2(copyin, copyinmsg, TAG_NO_FRAME_USED) ! 282: ! 283: /* Preamble allowing us to call a sub-function */ ! 284: mflr r0 ! 285: stw r0,FM_LR_SAVE(r1) ! 286: stwu r1,-(FM_SIZE+16)(r1) ! 287: ! 288: mfmsr r0 /* Get the MSR */ ! 289: rlwinm r6,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear 'rupts */ ! 290: mtmsr r6 /* Disable 'rupts */ ! 291: ! 292: mfsprg r6,0 /* Get the per_proc */ ! 293: lwz r6,PP_CPU_DATA(r6) ! 294: cmpli cr0,r5,0 ! 295: lwz r10,CPU_ACTIVE_THREAD(r6) ! 296: mtmsr r0 /* Set 'rupts back */ ! 297: ble- cr0,.L_copyinout_trivial ! 298: ! 299: /* we know we have a valid copyin to do now */ ! 300: /* Set up thread_recover in case we hit an illegal address */ ! 301: ! 302: lwz r8,THREAD_TOP_ACT(r10) ! 303: lis r11,hi16(.L_copyinout_error) ! 304: lis r7,SEG_REG_PROT>>16 /* Top byte of SR value */ ! 305: lwz r8,ACT_VMMAP(r8) ! 306: ori r11,r11,lo16(.L_copyinout_error) ! 307: add r9,r3,r5 /* Get the end of the source */ ! 308: lwz r8,VMMAP_PMAP(r8) ! 309: subi r9,r9,1 /* Make sure we don't go too far */ ! 310: rlwimi r7,r3,24,8,11 /* Insert seg number */ ! 311: stw r11,THREAD_RECOVER(r10) ! 312: xor r9,r9,r3 /* Smoosh 'em together */ ! 313: lwz r8,PMAP_SPACE(r8) ! 314: rlwinm r3,r3,0,4,31 ! 315: rlwimi r7,r8,0,12,31 /* Insert space */ ! 316: oris r3,r3,(SR_COPYIN_NUM << (28-16)) /* Set the copyin segment as the source */ ! 317: rlwinm. r9,r9,0,1,3 /* Top nybble equal? */ ! 318: mtsr SR_COPYIN,r7 ! 319: isync ! 320: ! 321: #if 0 ! 322: lis r0,HIGH_ADDR(EXT(dbgRegsCall)) /* (TEST/DEBUG) */ ! 323: ori r0,r0,LOW_ADDR(EXT(dbgRegsCall)) /* (TEST/DEBUG) */ ! 324: sc /* (TEST/DEBUG) */ ! 325: #endif ! 326: ! 327: /* For optimisation, we check if the copyin lies on a segment ! 328: * boundary. If it doesn't, we can use a simple copy. If it ! 329: * does, we split it into two separate copies in some C code. ! 330: */ ! 331: ! 332: bne- .L_call_copyin_multiple /* Nope, we went past the segment boundary... */ ! 333: ! 334: bl EXT(bcopy) ! 335: ! 336: /* Now that copyin is done, we don't need a recovery point */ ! 337: mfmsr r7 /* Get the MSR */ ! 338: rlwinm r6,r7,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear 'rupts */ ! 339: mtmsr r6 /* Disable 'rupts */ ! 340: ! 341: mfsprg r6,0 /* Get the per_proc */ ! 342: ! 343: lwz r6,PP_CPU_DATA(r6) ! 344: addi r1,r1,FM_SIZE+16 ! 345: lwz r10,CPU_ACTIVE_THREAD(r6) ! 346: mtmsr r7 ; Restore interrupts ! 347: li r3,0 ! 348: lwz r0,FM_LR_SAVE(r1) ! 349: stw r3,THREAD_RECOVER(r10) /* Clear recovery */ ! 350: mtlr r0 ! 351: blr ! 352: ! 353: /* we get here via the exception handler if an illegal ! 354: * user memory reference was made. ! 355: */ ! 356: .L_copyinout_error: ! 357: ! 358: /* Now that copyin is done, we don't need a recovery point */ ! 359: ! 360: mfmsr r7 /* Get the MSR */ ! 361: rlwinm r6,r7,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear 'rupts */ ! 362: mtmsr r6 /* Disable 'rupts */ ! 363: ! 364: mfsprg r6,0 /* Get the per_proc */ ! 365: ! 366: lwz r6,PP_CPU_DATA(r6) ! 367: addi r1,r1,FM_SIZE+16 ! 368: lwz r10,CPU_ACTIVE_THREAD(r6) ! 369: mtmsr r7 ; Restore interrupts ! 370: li r4,0 ! 371: lwz r0,FM_LR_SAVE(r1) ! 372: stw r4,THREAD_RECOVER(r10) /* Clear recovery */ ! 373: mtlr r0 ! 374: li r3,EFAULT ; Indicate error (EFAULT) ! 375: blr ! 376: ! 377: .L_copyinout_trivial: ! 378: /* The copyin/out was for either 0 bytes or a negative ! 379: * number of bytes, return an appropriate value (0 == SUCCESS). ! 380: * cr0 still contains result of comparison of len with 0. ! 381: */ ! 382: li r3, 0 ! 383: beq+ cr0, .L_copyinout_negative ! 384: li r3, 1 ! 385: .L_copyinout_negative: ! 386: ! 387: /* unwind the stack */ ! 388: addi r1, r1, FM_SIZE+16 ! 389: lwz r0, FM_LR_SAVE(r1) ! 390: mtlr r0 ! 391: ! 392: blr ! 393: ! 394: .L_call_copyin_multiple: ! 395: ! 396: /* unwind the stack */ ! 397: addi r1, r1, FM_SIZE+16 ! 398: lwz r0, FM_LR_SAVE(r1) ! 399: mtlr r0 ! 400: ! 401: b EXT(copyin_multiple) /* not a call - a jump! */ ! 402: ! 403: /* ! 404: * int ! 405: * copyout(src, dst, count) ! 406: * vm_offset_t src; ! 407: * vm_offset_t dst; ! 408: * int count; ! 409: * ! 410: */ ! 411: ! 412: ENTRY2(copyout, copyoutmsg, TAG_NO_FRAME_USED) ! 413: ! 414: /* Preamble allowing us to call a sub-function */ ! 415: ! 416: mflr r0 ! 417: stw r0,FM_LR_SAVE(r1) ! 418: stwu r1,-(FM_SIZE+16)(r1) ! 419: ! 420: #if 0 ! 421: stw r3,FM_SIZE+0(r1) /* (TEST/DEBUG) */ ! 422: stw r4,FM_SIZE+4(r1) /* (TEST/DEBUG) */ ! 423: stw r5,FM_SIZE+8(r1) /* (TEST/DEBUG) */ ! 424: mr r6,r0 /* (TEST/DEBUG) */ ! 425: ! 426: bl EXT(tracecopyout) /* (TEST/DEBUG) */ ! 427: ! 428: lwz r3,FM_SIZE+0(r1) /* (TEST/DEBUG) */ ! 429: lwz r4,FM_SIZE+4(r1) /* (TEST/DEBUG) */ ! 430: lwz r5,FM_SIZE+8(r1) /* (TEST/DEBUG) */ ! 431: #endif ! 432: ! 433: mfmsr r7 /* Get the MSR */ ! 434: rlwinm r6,r7,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear 'rupts */ ! 435: mtmsr r6 /* Disable 'rupts */ ! 436: ! 437: mfsprg r6,0 /* Get the per_proc */ ! 438: ! 439: lwz r6,PP_CPU_DATA(r6) ! 440: cmpli cr0,r5,0 ! 441: lwz r10,CPU_ACTIVE_THREAD(r6) ! 442: mtmsr r7 /* Restore 'rupts */ ! 443: ble- cr0,.L_copyinout_trivial ! 444: /* we know we have a valid copyout to do now */ ! 445: /* Set up thread_recover in case we hit an illegal address */ ! 446: ! 447: ! 448: lwz r8,THREAD_TOP_ACT(r10) ! 449: lis r11,HIGH_ADDR(.L_copyinout_error) ! 450: lis r7,SEG_REG_PROT>>16 /* Top byte of SR value */ ! 451: lwz r8,ACT_VMMAP(r8) ! 452: ori r11,r11,LOW_ADDR(.L_copyinout_error) ! 453: add r9,r4,r5 /* Get the end of the destination */ ! 454: lwz r8,VMMAP_PMAP(r8) ! 455: rlwimi r7,r4,24,8,11 /* Insert seg number */ ! 456: subi r9,r9,1 /* Make sure we don't go too far */ ! 457: stw r11,THREAD_RECOVER(r10) ! 458: xor r9,r9,r4 /* Smoosh 'em together */ ! 459: lwz r8,PMAP_SPACE(r8) ! 460: rlwinm r4,r4,0,4,31 ! 461: rlwimi r7,r8,0,12,31 /* Insert space */ ! 462: oris r4,r4,(SR_COPYIN_NUM << (28-16)) /* Set the copyin segment as the source */ ! 463: rlwinm. r9,r9,0,1,3 /* Top nybble equal? */ ! 464: mtsr SR_COPYIN,r7 ! 465: isync ! 466: ! 467: ! 468: /* For optimisation, we check if the copyout lies on a segment ! 469: * boundary. If it doesn't, we can use a simple copy. If it ! 470: * does, we split it into two separate copies in some C code. ! 471: */ ! 472: ! 473: bne- .L_call_copyout_multiple /* Nope, we went past the segment boundary... */ ! 474: ! 475: bl EXT(bcopy) ! 476: ! 477: /* Now that copyout is done, we don't need a recovery point */ ! 478: mfmsr r7 /* Get the MSR */ ! 479: rlwinm r6,r7,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear 'rupts */ ! 480: mtmsr r6 /* Disable 'rupts */ ! 481: ! 482: mfsprg r6,0 /* Get the per_proc */ ! 483: ! 484: lwz r6,PP_CPU_DATA(r6) ! 485: addi r1,r1,FM_SIZE+16 ! 486: lwz r10,CPU_ACTIVE_THREAD(r6) ! 487: mtmsr r7 ; Restore interrupts ! 488: li r3,0 ! 489: lwz r0,FM_LR_SAVE(r1) ! 490: stw r3,THREAD_RECOVER(r10) /* Clear recovery */ ! 491: mtlr r0 ! 492: blr ! 493: ! 494: .L_call_copyout_multiple: ! 495: /* unwind the stack */ ! 496: addi r1, r1, FM_SIZE+16 ! 497: lwz r0, FM_LR_SAVE(r1) ! 498: mtlr r0 ! 499: ! 500: b EXT(copyout_multiple) /* not a call - a jump! */ ! 501: ! 502: /* ! 503: * boolean_t ! 504: * copyinstr(src, dst, count, maxcount) ! 505: * vm_offset_t src; ! 506: * vm_offset_t dst; ! 507: * vm_size_t maxcount; ! 508: * vm_size_t* count; ! 509: * ! 510: * Set *count to the number of bytes copied ! 511: * ! 512: * If dst == NULL, don't copy, just count bytes. ! 513: * Only currently called from klcopyinstr. ! 514: */ ! 515: ! 516: ENTRY(copyinstr, TAG_NO_FRAME_USED) ! 517: ! 518: /* Preamble allowing us to call a sub-function */ ! 519: mflr r0 ! 520: stw r0,FM_LR_SAVE(r1) ! 521: stwu r1,-(FM_SIZE+16)(r1) ! 522: ! 523: #if 0 ! 524: stw r3,FM_SIZE+0(r1) /* (TEST/DEBUG) */ ! 525: stw r4,FM_SIZE+4(r1) /* (TEST/DEBUG) */ ! 526: stw r5,FM_SIZE+8(r1) /* (TEST/DEBUG) */ ! 527: stw r6,FM_SIZE+12(r1) /* (TEST/DEBUG) */ ! 528: mr r7,r0 /* (TEST/DEBUG) */ ! 529: ! 530: bl EXT(tracecopystr) /* (TEST/DEBUG) */ ! 531: ! 532: lwz r3,FM_SIZE+0(r1) /* (TEST/DEBUG) */ ! 533: lwz r4,FM_SIZE+4(r1) /* (TEST/DEBUG) */ ! 534: lwz r5,FM_SIZE+8(r1) /* (TEST/DEBUG) */ ! 535: stw r6,FM_SIZE+12(r1) /* (TEST/DEBUG) */ ! 536: #endif ! 537: ! 538: mfmsr r0 /* Get the MSR */ ! 539: rlwinm r7,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear 'rupts */ ! 540: mtmsr r7 /* Disable 'rupts */ ! 541: ! 542: mfsprg r7,0 /* Get the per_proc */ ! 543: lwz r7,PP_CPU_DATA(r7) ! 544: cmpli cr0,r5,0 ! 545: lwz r10,CPU_ACTIVE_THREAD(r7) ! 546: mtmsr r0 /* Restore 'rupts */ ! 547: ble- cr0,.L_copyinout_trivial ! 548: ! 549: /* we know we have a valid copyin to do now */ ! 550: /* Set up thread_recover in case we hit an illegal address */ ! 551: ! 552: li r0,0 ! 553: lwz r8,THREAD_TOP_ACT(r10) ! 554: stw r0,0(r6) /* Clear result length */ ! 555: lis r11,HIGH_ADDR(.L_copyinout_error) ! 556: lis r7,SEG_REG_PROT>>16 /* Top byte of SR value */ ! 557: lwz r8,ACT_VMMAP(r8) ! 558: ori r11,r11,LOW_ADDR(.L_copyinout_error) ! 559: lwz r8,VMMAP_PMAP(r8) ! 560: rlwimi r7,r3,24,8,11 /* Insert seg number */ ! 561: stw r11,THREAD_RECOVER(r10) ! 562: lwz r8,PMAP_SPACE(r8) ! 563: rlwinm r3,r3,0,4,31 ! 564: rlwimi r7,r8,0,12,31 /* Insert space */ ! 565: oris r3,r3,(SR_COPYIN_NUM << (28-16)) /* Set the copyin segment as the source */ ! 566: ! 567: /* Copy byte by byte for now - TODO NMGS speed this up with ! 568: * some clever (but fairly standard) logic for word copies. ! 569: * We don't use a copyinstr_multiple since copyinstr is called ! 570: * with INT_MAX in the linux server. Eugh. ! 571: */ ! 572: ! 573: li r9,0 /* Clear byte counter */ ! 574: ! 575: /* If the destination is NULL, don't do writes, ! 576: * just count bytes. We set CR7 outside the loop to save time ! 577: */ ! 578: cmpwi cr7,r4,0 /* Is the destination null? */ ! 579: ! 580: nxtseg: mtsr SR_COPYIN,r7 /* Set the source SR */ ! 581: isync ! 582: ! 583: .L_copyinstr_loop: ! 584: lbz r0,0(r3) /* Get the source */ ! 585: addic. r5,r5,-1 /* Have we gone far enough? */ ! 586: addi r3,r3,1 /* Bump source pointer */ ! 587: ! 588: cmpwi cr1,r0,0 /* Did we hit a null? */ ! 589: ! 590: beq cr7,.L_copyinstr_no_store /* If we are just counting, skip the store... */ ! 591: ! 592: stb r0,0(r4) /* Move to sink */ ! 593: addi r4,r4,1 /* Advance sink pointer */ ! 594: ! 595: .L_copyinstr_no_store: ! 596: ! 597: addi r9,r9,1 /* Count the character */ ! 598: beq- cr1,.L_copyinstr_done /* We're done if we did a null... */ ! 599: beq- cr0,L_copyinstr_toobig /* Also if we maxed the count... */ ! 600: ! 601: /* Check to see if the copyin pointer has moved out of the ! 602: * copyin segment, if it has we must remap. ! 603: */ ! 604: ! 605: rlwinm. r0,r3,0,4,31 /* Did we wrap around to 0? */ ! 606: bne+ cr0,.L_copyinstr_loop /* Nope... */ ! 607: ! 608: oris r3,r0,(SR_COPYIN_NUM << (28-16)) /* Reset the segment number */ ! 609: addis r7,r7,0x0010 /* Yeah, we did, so bump the segment */ ! 610: b nxtseg /* Keep going... */ ! 611: ! 612: L_copyinstr_toobig: ! 613: li r3,ENAMETOOLONG ! 614: b L_copyinstr_return ! 615: .L_copyinstr_done: ! 616: li r3,0 /* Normal return */ ! 617: L_copyinstr_return: ! 618: li r4,0 /* to clear thread_recover */ ! 619: stw r9,0(r6) /* Set how many bytes we did */ ! 620: stw r4,THREAD_RECOVER(r10) /* Clear recovery exit */ ! 621: ! 622: addi r1, r1, FM_SIZE+16 ! 623: lwz r0, FM_LR_SAVE(r1) ! 624: mtlr r0 ! 625: blr
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.