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