|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * HISTORY ! 27: * 25-Feb-1998 Umesh Vaishampayan ([email protected]) ! 28: * Optimized flush_cache(), flush_cache_v(). ! 29: * Moved kdp_flush_icache() to this file. ! 30: * ! 31: * Revision 1.1.1.1 1997/09/30 02:45:20 wsanchez ! 32: * Import of kernel from umeshv/kernel ! 33: * ! 34: * Revision 1.1.1.1 1997/05/15 22:25:00 rvega ! 35: * Remove invalidate_tlb. cleanupuse of sync/isync ! 36: * [1997/05/15 22:25:00 rvega] ! 37: * ! 38: * Revision 1.1.1.1 1997/04/30 15:55:55 rvega ! 39: * Add required context synchronization around tlbie. Remove unnecessary ! 40: * sr diddling. ! 41: * [1997/04/30 16:55:55 rvega] ! 42: * ! 43: */ ! 44: ! 45: /* ! 46: * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 ! 47: * All Rights Reserved ! 48: * ! 49: * Permission to use, copy, modify, and distribute this software and ! 50: * its documentation for any purpose and without fee is hereby granted, ! 51: * provided that the above copyright notice appears in all copies and ! 52: * that both the copyright notice and this permission notice appear in ! 53: * supporting documentation. ! 54: * ! 55: * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 56: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ! 57: * FOR A PARTICULAR PURPOSE. ! 58: * ! 59: * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR ! 60: * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 61: * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, ! 62: * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION ! 63: * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ! 64: */ ! 65: /* ! 66: * MKLINUX-1.0DR2 ! 67: */ ! 68: ! 69: #include <machdep/ppc/asm.h> ! 70: #include <machdep/ppc/proc_reg.h> ! 71: #include <cpus.h> ! 72: #include <assym.h> ! 73: #include <mach/ppc/vm_param.h> ! 74: ! 75: /* ! 76: * extern void flush_cache(vm_offset_t pa, unsigned count); ! 77: * ! 78: * flush_cache takes a physical address and count to flush, thus ! 79: * must not be called for multiple virtual pages. ! 80: * ! 81: * it flushes the data cache and invalidates the instruction ! 82: * cache for the address range in question ! 83: */ ! 84: ! 85: ENTRY(flush_cache, TAG_NO_FRAME_USED) ! 86: ! 87: /* Switch off data translations */ ! 88: mfmsr r6 ! 89: rlwinm r7, r6, 0, MSR_DR_BIT+1, MSR_DR_BIT-1 ! 90: mtmsr r7 ! 91: isync ! 92: ! 93: /* Check to see if the address is aligned. */ ! 94: add r8, ARG0,ARG1 ! 95: andi. r8,r8,(CACHE_LINE_SIZE-1) ! 96: beq- L_flush_check ! 97: addi ARG1,ARG1,CACHE_LINE_SIZE ! 98: ! 99: L_flush_check: ! 100: /* Make ctr hold count of how many times we should loop */ ! 101: srwi. r8, ARG1, CACHE_LINE_POW2 ! 102: /* If less than 32 to do, jump over loop */ ! 103: beq- L_flush_cache_done ! 104: mr r7, r8 /* remember r8 for the icbi loop */ ! 105: mr r9, ARG1 /* remember ARG1 for icbi loop */ ! 106: mtctr r8 /* the loop count */ ! 107: ! 108: L_flush_loop: ! 109: subic ARG1, ARG1, CACHE_LINE_SIZE ! 110: #ifndef UNCACHED_DATA_604 ! 111: //dcbf ARG0, ARG1 ! 112: dcbst ARG0, ARG1 ! 113: #endif /* UNCACHED_DATA_604 */ ! 114: bdnz L_flush_loop ! 115: sync ! 116: ! 117: mr ARG1, r9 /* restore ARG1 */ ! 118: mtctr r7 /* restore the loop count */ ! 119: L_invalidate_loop: ! 120: subic ARG1, ARG1, CACHE_LINE_SIZE ! 121: #ifndef UNCACHED_INST_604 ! 122: icbi ARG0, ARG1 ! 123: #endif /* UNCACHED_INST_604 */ ! 124: bdnz L_invalidate_loop ! 125: sync ! 126: isync ! 127: ! 128: L_flush_cache_done: ! 129: #ifndef UNCACHED_DATA_604 ! 130: //dcbf 0,ARG0 ! 131: dcbst 0,ARG0 ! 132: sync ! 133: #endif /* UNCACHED_DATA_604 */ ! 134: #ifndef UNCACHED_INST_604 ! 135: icbi 0,ARG0 ! 136: ! 137: sync /* Finish physical writes */ ! 138: isync /* Ensure data translations are on */ ! 139: #endif /* UNCACHED_INST_604 */ ! 140: ! 141: mtmsr r6 /* Restore original translations */ ! 142: isync /* Ensure data translations are on */ ! 143: ! 144: blr ! 145: ! 146: /* ! 147: * extern void flush_cache_v(vm_offset_t pa, unsigned count); ! 148: * ! 149: * flush_cache_v takes a virtual address and count to flush, thus ! 150: * can be called for multiple virtual pages. ! 151: * ! 152: * it flushes the data cache and invalidates the instruction ! 153: * cache for the address range in question ! 154: */ ! 155: ! 156: ENTRY(flush_cache_v, TAG_NO_FRAME_USED) ! 157: /* Check to see if the address is aligned. */ ! 158: add r8, ARG0,ARG1 ! 159: andi. r8,r8,(CACHE_LINE_SIZE-1) ! 160: beq- L_flushv_check ! 161: addi ARG1,ARG1,CACHE_LINE_SIZE ! 162: ! 163: L_flushv_check: ! 164: /* Make ctr hold count of how many times we should loop */ ! 165: srwi. r8, ARG1, CACHE_LINE_POW2 ! 166: /* If less than 32 to do, jump over loop */ ! 167: beq- L_flush_cache_v_done ! 168: mr r7, r8 /* remember r8 for the icbi loop */ ! 169: mr r9, ARG1 /* remember ARG1 for icbi loop */ ! 170: mtctr r8 ! 171: ! 172: L_flushv_loop: ! 173: subic ARG1, ARG1, CACHE_LINE_SIZE ! 174: #ifndef UNCACHED_DATA_604 ! 175: //dcbf ARG0, ARG1 ! 176: dcbst ARG0, ARG1 ! 177: #endif /* UNCACHED_DATA_604 */ ! 178: bdnz L_flushv_loop ! 179: sync ! 180: ! 181: mr ARG1, r9 /* restore ARG1 */ ! 182: mtctr r7 /* restore the loop count */ ! 183: L_cachev_invalidate_loop: ! 184: subic ARG1, ARG1, CACHE_LINE_SIZE ! 185: #ifndef UNCACHED_INST_604 ! 186: icbi ARG0, ARG1 ! 187: #endif /* UNCACHED_INST_604 */ ! 188: bdnz L_cachev_invalidate_loop ! 189: sync ! 190: isync ! 191: ! 192: L_flush_cache_v_done: ! 193: #ifndef UNCACHED_DATA_604 ! 194: //dcbf 0,ARG0 ! 195: dcbst 0,ARG0 ! 196: sync ! 197: #endif /* UNCACHED_DATA_604 */ ! 198: #ifndef UNCACHED_INST_604 ! 199: icbi 0,ARG0 ! 200: ! 201: sync /* make sure flushes have completed */ ! 202: isync ! 203: #endif /* UNCACHED_INST_604 */ ! 204: ! 205: blr ! 206: ! 207: /* ! 208: * extern void invalidate_cache_v(vm_offset_t pa, unsigned count); ! 209: */ ! 210: ! 211: ENTRY(invalidate_cache_v, TAG_NO_FRAME_USED) ! 212: /* Check to see if the address is aligned. */ ! 213: add r8, ARG0,ARG1 ! 214: andi. r8,r8,(CACHE_LINE_SIZE-1) ! 215: beq- L_invalidate_checkv ! 216: addi ARG1,ARG1,CACHE_LINE_SIZE ! 217: ! 218: L_invalidate_checkv: ! 219: /* Make ctr hold count of how many times we should loop */ ! 220: srwi. r8, ARG1, CACHE_LINE_POW2 ! 221: /* If less than 32 to do, jump over loop */ ! 222: beq- L_invalidate_cache_v_done ! 223: mr r7, r8 /* remember r8 for the icbi loop */ ! 224: mr r9, ARG1 /* remember ARG1 for icbi loop */ ! 225: mtctr r8 ! 226: ! 227: L_invalidatev_loop: ! 228: subic ARG1, ARG1, CACHE_LINE_SIZE ! 229: #ifndef UNCACHED_DATA_604 ! 230: dcbi ARG0, ARG1 ! 231: dcbi ARG0, ARG1 /* fix for dcbi bug */ ! 232: #endif /* UNCACHED_DATA_604 */ ! 233: bdnz L_invalidatev_loop ! 234: sync ! 235: ! 236: mr ARG1, r9 /* restore ARG1 */ ! 237: mtctr r7 /* restore the loop count */ ! 238: L_invalidatev_loop2: ! 239: subic ARG1, ARG1, CACHE_LINE_SIZE ! 240: #ifndef UNCACHED_INST_604 ! 241: icbi ARG0, ARG1 ! 242: #endif /* UNCACHED_INST_604 */ ! 243: bdnz L_invalidatev_loop2 ! 244: sync ! 245: isync ! 246: ! 247: L_invalidate_cache_v_done: ! 248: #ifndef UNCACHED_DATA_604 ! 249: dcbi 0,ARG0 ! 250: dcbi 0,ARG0 /* fix for dcbi bug */ ! 251: sync ! 252: #endif /* UNCACHED_DATA_604 */ ! 253: #ifndef UNCACHED_INST_604 ! 254: icbi 0,ARG0 ! 255: ! 256: sync /* make sure invalidates have completed */ ! 257: isync ! 258: #endif /* UNCACHED_INST_604 */ ! 259: ! 260: blr ! 261: ! 262: ! 263: /* ! 264: * void kdp_flush_icache(caddr_t addr, unsigned count) ! 265: * ! 266: * Flush the data cache, invalidate the code cache for all cache lines in the ! 267: * specified range. This enables execution of the instructions stored via the ! 268: * data cache (e.g. code read in by noncoherent logical I/O or code generated ! 269: * "on-the-fly"). ! 270: * ! 271: * NOTE: The dcbf instruction takes a logical address. This means that addr ! 272: * must be valid in the current address space. Further, it "acts as a store ! 273: * to the addressed byte with respect to address translation and protection. ! 274: * The reference and changed bits are set accordingly." So, make sure the ! 275: * page is not read-only! Use the static mapping. ! 276: */ ! 277: .set kLog2CacheLineSize, 5 ! 278: .set kCacheLineSize, 32 ! 279: ! 280: ENTRY(kdp_flush_icache, TAG_NO_FRAME_USED) ! 281: cmpi CR0,0,r4,0 // is this zero length? ! 282: add r4,r3,r4 // calculate last byte + 1 ! 283: subi r4,r4,1 // calculate last byte ! 284: ! 285: srwi r5,r3,kLog2CacheLineSize // calc first cache line index ! 286: srwi r4,r4,kLog2CacheLineSize // calc last cache line index ! 287: beq cr0, LdataToCodeDone // done if zero length ! 288: ! 289: subf r4,r5,r4 // calc diff (# lines minus 1) ! 290: addi r4,r4,1 // # of cache lines to flush ! 291: slwi r5,r5,kLog2CacheLineSize // calc addr of first cache line ! 292: ! 293: // flush the data cache lines ! 294: mr r3,r5 // starting address for loop ! 295: mtctr r4 // loop count ! 296: LdataToCodeFlushLoop: ! 297: #ifndef UNCACHED_DATA_604 ! 298: //dcbf 0, r3 // flush the data cache line ! 299: dcbst 0, r3 // flush the data cache line ! 300: #endif ! 301: addi r3,r3,kCacheLineSize // advance to next cache line ! 302: bdnz LdataToCodeFlushLoop // loop until count is zero ! 303: sync // wait until RAM is valid ! 304: ! 305: // invalidate the code cache lines ! 306: mr r3,r5 // starting address for loop ! 307: mtctr r4 // loop count ! 308: LdataToCodeInvalidateLoop: ! 309: #ifndef UNCACHED_INST_604 ! 310: icbi 0, r3 // invalidate code cache line ! 311: #endif ! 312: addi r3,r3,kCacheLineSize // advance to next cache line ! 313: bdnz LdataToCodeInvalidateLoop // loop until count is zero ! 314: sync // wait until last icbi completes ! 315: isync // discard prefetched instructions, too ! 316: ! 317: LdataToCodeDone: ! 318: blr // return nothing
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.