|
|
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: #define PERFTIMES 0
38:
39: .text
40:
41: /*
42: *
43: * Random notes and musings...
44: *
45: * Access to mappings via the PTEG hash must be done with the list locked.
46: * Access via the physical entries is controlled by the physent lock.
47: * Access to mappings is controlled by the PTEG lock once they are queued.
48: * If they are not on the list, they don't really exist, so
49: * only one processor at a time can find them, so no access control is needed.
50: *
51: * The second half of the PTE is kept in the physical entry. It is done this
52: * way, because there may be multiple mappings that refer to the same physical
53: * page (i.e., address aliases or synonymns). We must do it this way, because
54: * maintenance of the reference and change bits becomes nightmarish if each mapping
55: * has its own. One side effect of this, and not necessarily a bad one, is that
56: * all mappings for a single page can have a single WIMG, protection state, and RC bits.
57: * The only "bad" thing, is the reference bit. With a single copy, we can not get
58: * a completely accurate working set calculation, i.e., we can't tell which mapping was
59: * used to reference the page, all we can tell is that the physical page was
60: * referenced.
61: *
62: * The master copys of the reference and change bits are kept in the phys_entry.
63: * Other than the reference and change bits, changes to the phys_entry are not
64: * allowed if it has any mappings. The master reference and change bits must be
65: * changed via atomic update.
66: *
67: * Invalidating a PTE merges the RC bits into the phys_entry.
68: *
69: * Before checking the reference and/or bits, ALL mappings to the physical page are
70: * invalidated.
71: *
72: * PTEs are never explicitly validated, they are always faulted in. They are also
73: * not visible outside of the hw_vm modules. Complete seperation of church and state.
74: *
75: * Removal of a mapping is invalidates its PTE.
76: *
77: * So, how do we deal with mappings to I/O space? We don't have a physent for it.
78: * Within the mapping is a copy of the second half of the PTE. This is used
79: * ONLY when there is no physical entry. It is swapped into the PTE whenever
80: * it is built. There is no need to swap it back out, because RC is not
81: * maintained for these mappings.
82: *
83: * So, I'm starting to get concerned about the number of lwarx/stcwx loops in
84: * this. Satisfying a mapped address with no stealing requires one lock. If we
85: * steal an entry, there's two locks and an atomic update. Invalidation of an entry
86: * takes one lock and, if there is a PTE, another lock and an atomic update. Other
87: * operations are multiples (per mapping) of the above. Maybe we should look for
88: * an alternative. So far, I haven't found one, but I haven't looked hard.
89: */
90:
91:
92: /* hw_add_map(struct mapping *mp, space_t space, vm_offset_t va) - Adds a mapping
93: *
94: * Adds a mapping to the PTEG hash list.
95: *
96: * Interrupts must be disabled before calling.
97: *
98: * Using the space and the virtual address, we hash into the hash table
99: * and get a lock on the PTEG hash chain. Then we chain the
100: * mapping to the front of the list.
101: *
102: */
103:
104: .align 5
105: .globl EXT(hw_add_map)
106:
107: LEXT(hw_add_map)
108:
109: #if PERFTIMES && DEBUG
110: mr r7,r3
111: mflr r11
112: li r3,20
113: bl EXT(dbgLog2) ; Start of hw_add_map
114: mr r3,r7
115: mtlr r11
116: #endif
117:
118: mfmsr r0 /* Get the MSR */
119: eqv r6,r6,r6 /* Fill the bottom with foxes */
120: rlwinm r11,r4,6,6,25 /* Position the space for the VSID */
121: mfspr r10,sdr1 /* Get hash table base and size */
122: rlwimi r11,r5,30,2,5 /* Insert the segment no. to make a VSID */
123: rlwimi r6,r10,16,0,15 /* Make table size -1 out of mask */
124: rlwinm r7,r5,26,10,25 /* Isolate the page index */
125: or r8,r10,r6 /* Point to the last byte in table */
126: rlwinm r9,r5,4,0,3 ; Move nybble 1 up to 0
127: xor r7,r7,r11 /* Get primary hash */
128: andi. r12,r0,0x7FCF /* Disable translation and interruptions */
129: rlwinm r11,r11,1,1,24 /* Position VSID for pte ID */
130: addi r8,r8,1 /* Point to the PTEG Control Area */
131: xor r9,r9,r5 ; Splooch vaddr nybble 0 and 1 together
132: and r7,r7,r6 /* Wrap the hash */
133: rlwimi r11,r5,10,26,31 /* Move API into pte ID */
134: rlwinm r9,r9,6,27,29 ; Get splooched bits in place
135: add r8,r8,r7 /* Point to our PCA entry */
136: rlwinm r10,r4,2,27,29 ; Get low 3 bits of the VSID for look-aside hash
137: mtmsr r12 /* Get the stuff disabled */
138: la r4,PCAhash(r8) /* Point to the mapping hash area */
139: xor r9,r9,r10 ; Finish splooching nybble 0, 1, and the low bits of the VSID
140: isync /* Get rid of anything prefetched before we ref storage */
141: /*
142: * We've now got the address of our PCA, the hash chain anchor, our API subhash,
143: * and word 0 of the PTE (the virtual part).
144: *
145: * Now, we just lock the PCA.
146: */
147:
148: li r12,1 /* Get the locked value */
149: dcbt 0,r4 /* We'll need the hash area in a sec, so get it */
150: add r4,r4,r9 /* Point to the right mapping hash slot */
151:
152: lwarx r10,0,r8 ; ?
153:
154: ptegLckx: lwarx r10,0,r8 /* Get the PTEG lock */
155: mr. r10,r10 /* Is it locked? */
156: bne- ptegLckwx /* Yeah... */
157: stwcx. r12,0,r8 /* Take take it */
158: bne- ptegLckx /* Someone else was trying, try again... */
159: b ptegSXgx /* All done... */
160:
161: .align 4
162:
163: ptegLckwx: mr. r10,r10 /* Check if it's already held */
164: beq+ ptegLckx /* It's clear... */
165: lwz r10,0(r8) /* Get lock word again... */
166: b ptegLckwx /* Wait... */
167:
168: .align 4
169:
170: ptegSXgx: isync /* Make sure we haven't used anything yet */
171:
172: lwz r7,0(r4) /* Pick up the anchor of hash list */
173: stw r3,0(r4) /* Save the new head */
174: stw r7,mmhashnext(r3) /* Chain in the old head */
175:
176: stw r4,mmPTEhash(r3) /* Point to the head of the hash list */
177:
178: sync /* Make sure the chain is updated */
179: stw r10,0(r8) /* Unlock the hash list */
180: mtmsr r0 /* Restore translation and interruptions */
181: isync /* Toss anything doe with DAT off */
182: #if PERFTIMES && DEBUG
183: mflr r11
184: mr r4,r3
185: li r3,21
186: bl EXT(dbgLog2) ; end of hw_add_map
187: mr r3,r4
188: mtlr r11
189: #endif
190: blr /* Leave... */
191:
192:
193: /* mp=hw_lock_phys_vir(space, va) - Finds and locks a physical entry by vaddr.
194: *
195: * Returns the mapping with the associated physent locked if found, or a
196: * zero and no lock if not. It we timed out trying to get a the lock on
197: * the physical entry, we retun a 1. A physical entry can never be on an
198: * odd boundary, so we can distinguish between a mapping and a timeout code.
199: *
200: * Interrupts must be disabled before calling.
201: *
202: * Using the space and the virtual address, we hash into the hash table
203: * and get a lock on the PTEG hash chain. Then we search the chain for the
204: * mapping for our virtual address. From there, we extract the pointer to
205: * the physical entry.
206: *
207: * Next comes a bit of monkey business. we need to get a lock on the physical
208: * entry. But, according to our rules, we can't get it after we've gotten the
209: * PTEG hash lock, we could deadlock if we do. So, we need to release the
210: * hash lock. The problem is, though, that as soon as we release it, some
211: * other yahoo may remove our mapping between the time that we release the
212: * hash lock and obtain the phys entry lock. So, we can't count on the
213: * mapping once we release the lock. Instead, after we lock the phys entry,
214: * we search the mapping list (phys_link) for our translation. If we don't find it,
215: * we unlock the phys entry, bail out, and return a 0 for the mapping address. If we
216: * did find it, we keep the lock and return the address of the mapping block.
217: *
218: * What happens when a mapping is found, but there is no physical entry?
219: * This is what happens when there is I/O area mapped. It one of these mappings
220: * is found, the mapping is returned, as is usual for this call, but we don't
221: * try to lock anything. There could possibly be some problems here if another
222: * processor releases the mapping while we still alre using it. Hope this
223: * ain't gonna happen.
224: *
225: * Taaa-dahhh! Easy as pie, huh?
226: *
227: * So, we have a few hacks hacks for running translate off in here.
228: * First, when we call the lock routine, we have carnel knowlege of the registers is uses.
229: * That way, we don't need a stack frame, which we can't have 'cause the stack is in
230: * virtual storage. But wait, as if that's not enough... We need one more register. So,
231: * we cram the LR into the CTR and return from there.
232: *
233: */
234:
235: .align 5
236: .globl EXT(hw_lock_phys_vir)
237:
238: LEXT(hw_lock_phys_vir)
239:
240: #if PERFTIMES && DEBUG
241: mflr r11
242: mr r5,r3
243: li r3,22
244: bl EXT(dbgLog2) ; Start of hw_add_map
245: mr r3,r5
246: mtlr r11
247: #endif
248: mfmsr r12 /* Get the MSR */
249: eqv r6,r6,r6 /* Fill the bottom with foxes */
250: rlwinm r11,r3,6,6,25 /* Position the space for the VSID */
251: mfspr r5,sdr1 /* Get hash table base and size */
252: rlwimi r11,r4,30,2,5 /* Insert the segment no. to make a VSID */
253: rlwimi r6,r5,16,0,15 /* Make table size -1 out of mask */
254: andi. r0,r12,0x7FCF /* Disable translation and interruptions */
255: rlwinm r9,r4,4,0,3 ; Move nybble 1 up to 0
256: rlwinm r7,r4,26,10,25 /* Isolate the page index */
257: or r8,r5,r6 /* Point to the last byte in table */
258: xor r7,r7,r11 /* Get primary hash */
259: rlwinm r11,r11,1,1,24 /* Position VSID for pte ID */
260: addi r8,r8,1 /* Point to the PTEG Control Area */
261: xor r9,r9,r4 ; Splooch vaddr nybble 0 and 1 together
262: and r7,r7,r6 /* Wrap the hash */
263: rlwimi r11,r4,10,26,31 /* Move API into pte ID */
264: rlwinm r9,r9,6,27,29 ; Get splooched bits in place
265: add r8,r8,r7 /* Point to our PCA entry */
266: rlwinm r10,r3,2,27,29 ; Get low 3 bits of the VSID for look-aside hash
267: mtmsr r0 /* Get the trans and intr off */
268: la r3,PCAhash(r8) /* Point to the mapping hash area */
269: xor r9,r9,r10 ; Finish splooching nybble 0, 1, and the low bits of the VSID
270: isync /* Make sure translation is off before we ref storage */
271:
272: /*
273: * We've now got the address of our PCA, the hash chain anchor, our API subhash,
274: * and word 0 of the PTE (the virtual part).
275: *
276: * Now, we just lock the PCA and find our mapping, if it exists.
277: */
278:
279: dcbt 0,r3 /* We'll need the hash area in a sec, so get it */
280: add r3,r3,r9 /* Point to the right mapping hash slot */
281:
282: lwarx r10,0,r8 ; ?
283:
284: ptegLcka: lwarx r10,0,r8 /* Get the PTEG lock */
285: li r5,1 /* Get the locked value */
286: mr. r10,r10 /* Is it locked? */
287: bne- ptegLckwa /* Yeah... */
288: stwcx. r5,0,r8 /* Take take it */
289: bne- ptegLcka /* Someone else was trying, try again... */
290: b ptegSXga /* All done... */
291:
292: .align 4
293:
294: ptegLckwa: mr. r10,r10 /* Check if it's already held */
295: beq+ ptegLcka /* It's clear... */
296: lwz r10,0(r8) /* Get lock word again... */
297: b ptegLckwa /* Wait... */
298:
299: .align 4
300:
301: ptegSXga: isync /* Make sure we haven't used anything yet */
302:
303: mflr r0 /* Get the LR */
304: lwz r9,0(r3) /* Pick up the first mapping block */
305: mtctr r0 /* Stuff it into the CTR */
306:
307: findmapa:
308:
309: mr. r3,r9 /* Did we hit the end? */
310: bne+ chkmapa /* Nope... */
311:
312: stw r3,0(r8) /* Unlock the PTEG lock
313: Note: we never saved anything while we
314: had the lock, so we don't need a sync
315: before we unlock it */
316:
317: vbail: mtmsr r12 /* Restore translation and interruptions */
318: isync /* Make sure translation is cool */
319: #if PERFTIMES && DEBUG
320: mflr r11
321: mr r4,r3
322: li r3,23
323: bl EXT(dbgLog2) ; Start of hw_add_map
324: mr r3,r4
325: mtlr r11
326: #endif
327: bctr /* Return in abject failure... */
328:
329: .align 4
330:
331: chkmapa: lwz r10,mmPTEv(r3) /* Pick up our virtual ID */
332: lwz r9,mmhashnext(r3) /* Pick up next mapping block */
333: cmplw r10,r11 /* Have we found ourself? */
334: bne- findmapa /* Nope, still wandering... */
335:
336: lwz r9,mmphysent(r3) /* Get our physical entry pointer */
337: li r5,0 /* Clear this out */
338: mr. r9,r9 /* Is there, like, a physical entry? */
339: stw r5,0(r8) /* Unlock the PTEG lock
340: Note: we never saved anything while we
341: had the lock, so we don't need a sync
342: before we unlock it */
343:
344: beq- vbail /* If there is no physical entry, it's time
345: to leave... */
346:
347: /* Here we want to call hw_lock_bit. We don't want to use the stack, 'cause it's
348: * in virtual storage, and we're in real. So, we've carefully looked at the code
349: * in hw_lock_bit (and unlock) and cleverly don't use any of the registers that it uses.
350: * Be very, very aware of how you change this code. By the way, it uses:
351: * R0, R6, R7, R8, and R9. R3, R4, and R5 contain parameters
352: * Unfortunatly, we need to stash R9 still. So... Since we know we will not be interrupted
353: * ('cause we turned off interruptions and translation is off) we will use SPRG3...
354: */
355:
356: lwz r10,mmPTEhash(r3) /* Save the head of the hash-alike chain. We need it to find ourselves later */
357: lis r5,HIGH_ADDR(EXT(LockTimeOut)) /* Get address of timeout value */
358: la r3,pephyslink(r9) /* Point to the lock word */
359: ori r5,r5,LOW_ADDR(EXT(LockTimeOut)) /* Get second half of address */
360: li r4,PHYS_LOCK /* Get the lock bit value */
361: lwz r5,0(r5) /* Pick up the timeout value */
362: mtsprg 3,r9 /* Save R9 in SPRG3 */
363:
364: bl EXT(hw_lock_bit) /* Go do the lock */
365:
366: mfsprg r9,3 /* Restore pointer to the phys_entry */
367: mr. r3,r3 /* Did we timeout? */
368: lwz r4,pephyslink(r9) /* Pick up first mapping block */
369: beq- penterr /* Bad deal, we timed out... */
370:
371: rlwinm r4,r4,0,0,26 ; Clear out the flags from first link
372:
373: findmapb: mr. r3,r4 /* Did we hit the end? */
374: bne+ chkmapb /* Nope... */
375:
376: la r3,pephyslink(r9) /* Point to where the lock is */
377: li r4,PHYS_LOCK /* Get the lock bit value */
378: bl EXT(hw_unlock_bit) /* Go unlock the physentry */
379:
380: li r3,0 /* Say we failed */
381: b vbail /* Return in abject failure... */
382:
383: penterr: li r3,1 /* Set timeout */
384: b vbail /* Return in abject failure... */
385:
386: .align 5
387:
388: chkmapb: lwz r6,mmPTEv(r3) /* Pick up our virtual ID */
389: lwz r4,mmnext(r3) /* Pick up next mapping block */
390: cmplw r6,r11 /* Have we found ourself? */
391: lwz r5,mmPTEhash(r3) /* Get the start of our hash chain */
392: bne- findmapb /* Nope, still wandering... */
393: cmplw r5,r10 /* On the same hash chain? */
394: bne- findmapb /* Nope, keep looking... */
395:
396: b vbail /* Return in glorious triumph... */
397:
398:
399: /*
400: * hw_rem_map(mapping) - remove a mapping from the system.
401: *
402: * Upon entry, R3 contains a pointer to a mapping block and the associated
403: * physical entry is locked if there is one.
404: *
405: * If the mapping entry indicates that there is a PTE entry, we invalidate
406: * if and merge the reference and change information into the phys_entry.
407: *
408: * Next, we remove the mapping from the phys_ent and the PTEG hash list.
409: *
410: * Unlock any locks that are left, and exit.
411: *
412: * Note that this must be done with both interruptions off and VM off
413: *
414: * Note that this code depends upon the VSID being of the format 00SXXXXX
415: * where S is the segment number.
416: *
417: *
418: */
419:
420: .align 5
421: .globl EXT(hw_rem_map)
422:
423: LEXT(hw_rem_map)
424: #if PERFTIMES && DEBUG
425: mflr r11
426: mr r4,r3
427: li r3,24
428: bl EXT(dbgLog2) ; Start of hw_add_map
429: mr r3,r4
430: mtlr r11
431: #endif
432: mfmsr r0 /* Save the MSR */
433: rlwinm r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear interruptions */
434: rlwinm r12,r12,0,28,25 /* Clear IR and DR */
435: mtmsr r12 /* Clear interruptions and turn off translation */
436: isync /* Make sure that translation is off */
437:
438: lwz r6,mmPTEhash(r3) /* Get pointer to hash list anchor */
439: lwz r5,mmPTEv(r3) /* Get the VSID */
440: dcbt 0,r6 /* We'll need that chain in a bit */
441:
442: rlwinm r7,r6,0,0,25 /* Round hash list down to PCA boundary */
443: li r12,1 /* Get the locked value */
444: subi r6,r6,mmhashnext /* Make the anchor look like an entry */
445:
446: lwarx r10,0,r7 ; ?
447:
448: ptegLck1: lwarx r10,0,r7 /* Get the PTEG lock */
449: mr. r10,r10 /* Is it locked? */
450: bne- ptegLckw1 /* Yeah... */
451: stwcx. r12,0,r7 /* Try to take it */
452: bne- ptegLck1 /* Someone else was trying, try again... */
453: b ptegSXg1 /* All done... */
454:
455: .align 4
456:
457: ptegLckw1: mr. r10,r10 /* Check if it's already held */
458: beq+ ptegLck1 /* It's clear... */
459: lwz r10,0(r7) /* Get lock word again... */
460: b ptegLckw1 /* Wait... */
461:
462: .align 4
463:
464: ptegSXg1: isync /* Make sure we haven't used anything yet */
465:
466: lwz r12,mmhashnext(r3) /* Prime with our forward pointer */
467: lwz r4,mmPTEent(r3) /* Get the pointer to the PTE now that the lock's set */
468:
469: srchmaps: mr. r10,r6 /* Save the previous entry */
470: bne+ mapok /* No error... */
471:
472: lis r0,HIGH_ADDR(Choke) /* We have a kernel choke!!! */
473: ori r0,r0,LOW_ADDR(Choke)
474: sc /* Firmware Heimlich manuever */
475:
476: .align 4
477:
478: mapok: lwz r6,mmhashnext(r6) /* Look at the next one */
479: cmplwi cr5,r4,0 /* Is there a PTE? */
480: cmplw r6,r3 /* Have we found ourselves? */
481: bne+ srchmaps /* Nope, get your head together... */
482:
483: stw r12,mmhashnext(r10) /* Remove us from the queue */
484: rlwinm r9,r5,1,0,3 /* Move in the segment */
485:
486: rlwinm r8,r4,6,4,19 /* Line PTEG disp up to a page */
487: rlwinm r11,r5,5,4,19 /* Line up the VSID */
488: lwz r10,mmphysent(r3) /* Point to the physical entry */
489:
490: beq+ cr5,nopte /* There's no PTE to invalidate... */
491:
492: xor r8,r8,r11 /* Back hash to virt index */
493: lis r12,HIGH_ADDR(EXT(tlb_system_lock)) /* Get the TLBIE lock */
494: rlwimi r9,r5,22,4,9 /* Move in the API */
495: ori r12,r12,LOW_ADDR(EXT(tlb_system_lock)) /* Grab up the bottom part */
496: mfspr r11,pvr /* Find out what kind of machine we are */
497: rlwimi r9,r8,0,10,19 /* Create the virtual address */
498: rlwinm r11,r11,16,16,31 /* Isolate CPU type */
499:
500: stw r5,0(r4) /* Make the PTE invalid */
501:
502: cmplwi cr1,r11,3 /* Is this a 603? */
503: sync /* Make sure the invalid is stored */
504:
505: lwarx r5,0,r12 ; ?
506:
507: tlbhang1: lwarx r5,0,r12 /* Get the TLBIE lock */
508: rlwinm r11,r4,29,29,31 /* Get the bit position of entry */
509: mr. r5,r5 /* Is it locked? */
510: lis r6,0x8000 /* Start up a bit mask */
511: li r5,1 /* Get our lock word */
512: bne- tlbhang1 /* It's locked, go wait... */
513: stwcx. r5,0,r12 /* Try to get it */
514: bne- tlbhang1 /* We was beat... */
515:
516: srw r6,r6,r11 /* Make a "free slot" mask */
517: lwz r5,PCAallo(r7) /* Get the allocation control bits */
518: rlwinm r11,r6,24,8,15 /* Make the autogen bit to turn off */
519: or r5,r5,r6 /* turn on the free bit */
520: rlwimi r11,r11,24,16,23 /* Get lock bit mask to turn it off */
521:
522: andc r5,r5,r11 /* Turn off the lock and autogen bits in allocation flags */
523: li r11,0 /* Lock clear value */
524:
525: tlbie r9 /* Invalidate it everywhere */
526:
527:
528: beq- cr1,its603a /* It's a 603, skip the tlbsync... */
529:
530: eieio /* Make sure that the tlbie happens first */
531: tlbsync /* wait for everyone to catch up */
532:
533: its603a: sync /* Make sure of it all */
534: stw r11,0(r12) /* Clear the tlbie lock */
535: eieio /* Make sure those RC bit are loaded */
536: stw r5,PCAallo(r7) /* Show that the slot is free */
537: stw r11,mmPTEent(r3) /* Clear the pointer to the PTE */
538:
539: nopte: mr. r10,r10 /* See if there is a physical entry */
540: la r9,pephyslink(r10) /* Point to the physical mapping chain */
541: beq- nophys /* No physical entry, we're done... */
542: beq- cr5,nadamrg /* Not PTE to merge... */
543:
544: lwz r6,4(r4) /* Get the latest reference and change bits */
545: la r12,pepte1(r10) /* Point right at the master copy */
546: rlwinm r6,r6,0,23,24 /* Extract just the RC bits */
547:
548: lwarx r8,0,r12 ; ?
549:
550: mrgrc: lwarx r8,0,r12 /* Get the master copy */
551: or r8,r8,r6 /* Merge in latest RC */
552: stwcx. r8,0,r12 /* Save it back */
553: bne- mrgrc /* If it changed, try again... */
554:
555: nadamrg: li r11,0 /* Clear this out */
556: lwz r12,mmnext(r3) /* Prime with our next */
557: stw r11,0(r7) /* Unlock the hash chain now so we don't
558: lock out another processor during the
559: our next little search */
560:
561:
562: srchpmap: mr. r10,r9 /* Save the previous entry */
563: bne+ mapok1 /* No error... */
564:
565: lis r0,HIGH_ADDR(Choke) /* We have a kernel choke!!! */
566: ori r0,r0,LOW_ADDR(Choke)
567: sc /* Firmware Heimlich maneuver */
568:
569: .align 4
570:
571: mapok1: lwz r9,mmnext(r9) /* Look at the next one */
572: rlwinm r9,r9,0,0,26 ; Clear out the flags from first link
573: cmplw r9,r3 /* Have we found ourselves? */
574: bne+ srchpmap /* Nope, get your head together... */
575:
576: stw r12,mmnext(r10) /* Remove us from the queue */
577:
578: mtmsr r0 /* Interrupts and translation back on */
579: isync
580: #if PERFTIMES && DEBUG
581: mflr r11
582: li r3,25
583: bl EXT(dbgLog2) ; Start of hw_add_map
584: mtlr r11
585: #endif
586: blr /* Return... */
587:
588: .align 4
589:
590: nophys: li r4,0 /* Make sure this is 0 */
591: sync /* Make sure that chain is updated */
592: stw r4,0(r7) /* Unlock the hash chain */
593: mtmsr r0 /* Interrupts and translation back on */
594: isync
595: #if PERFTIMES && DEBUG
596: mflr r11
597: li r3,25
598: bl EXT(dbgLog2) ; Start of hw_add_map
599: mtlr r11
600: #endif
601: blr /* Return... */
602:
603:
604: /*
605: * hw_prot(physent, prot) - Change the protection of a physical page
606: *
607: * Upon entry, R3 contains a pointer to a physical entry which is locked.
608: * R4 contains the PPC protection bits.
609: *
610: * The first thing we do is to slam the new protection into the phys entry.
611: * Then we scan the mappings and process each one.
612: *
613: * Acquire the lock on the PTEG hash list for the mapping being processed.
614: *
615: * If the current mapping has a PTE entry, we invalidate
616: * it and merge the reference and change information into the phys_entry.
617: *
618: * Next, slam the protection bits into the entry and unlock the hash list.
619: *
620: * Note that this must be done with both interruptions off and VM off
621: *
622: *
623: */
624:
625: .align 5
626: .globl EXT(hw_prot)
627:
628: LEXT(hw_prot)
629: #if PERFTIMES && DEBUG
630: mflr r11
631: mr r7,r3
632: // lwz r5,4(r3)
633: li r5,0x1111
634: li r3,26
635: bl EXT(dbgLog2) ; Start of hw_add_map
636: mr r3,r7
637: mtlr r11
638: #endif
639: mfmsr r0 /* Save the MSR */
640: rlwinm r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear interruptions */
641: li r5,pepte1 /* Get displacement to the second word of master pte */
642: rlwinm r12,r12,0,28,25 /* Clear IR and DR */
643:
644: mtmsr r12 /* Clear interruptions and turn off translation */
645: /* NOTE: we can get away with just turning the
646: instruction translation off here because we
647: are running with virtual = real. If not,
648: there would be an "implied branch", which wouldn't
649: be too good. */
650:
651: isync /* Make sure that translation is off */
652:
653: lwz r10,pephyslink(r3) /* Get the first mapping block */
654: rlwinm r10,r10,0,0,26 ; Clear out the flags from first link
655:
656: /*
657: * Note that we need to to do the interlocked update here because another processor
658: * can be updating the reference and change bits even though the physical entry
659: * is locked. All modifications to the PTE portion of the physical entry must be
660: * done via interlocked update.
661: */
662:
663: lwarx r8,r5,r3 ; ?
664:
665: protcng: lwarx r8,r5,r3 /* Get the master copy */
666: rlwimi r8,r4,0,30,31 /* Move in the protection bits */
667: stwcx. r8,r5,r3 /* Save it back */
668: bne- protcng /* If it changed, try again... */
669:
670:
671:
672: protnext: mr. r10,r10 /* Are there any more mappings? */
673: beq- protdone /* Naw... */
674:
675: lwz r7,mmPTEhash(r10) /* Get pointer to hash list anchor */
676: lwz r5,mmPTEv(r10) /* Get the virtual address */
677: rlwinm r7,r7,0,0,25 /* Round hash list down to PCA boundary */
678:
679: li r12,1 /* Get the locked value */
680:
681: lwarx r11,0,r7 ; ?
682:
683: protLck1: lwarx r11,0,r7 /* Get the PTEG lock */
684: mr. r11,r11 /* Is it locked? */
685: bne- protLckw1 /* Yeah... */
686: stwcx. r12,0,r7 /* Try to take it */
687: bne- protLck1 /* Someone else was trying, try again... */
688: b protSXg1 /* All done... */
689:
690: .align 4
691:
692: protLckw1: mr. r11,r11 /* Check if it's already held */
693: beq+ protLck1 /* It's clear... */
694: lwz r11,0(r7) /* Get lock word again... */
695: b protLckw1 /* Wait... */
696:
697: .align 4
698:
699: protSXg1: isync /* Make sure we haven't used anything yet */
700:
701: lwz r6,mmPTEent(r10) /* Get the pointer to the PTE now that the lock's set */
702:
703: rlwinm r9,r5,1,0,3 /* Move in the segment */
704: mr. r6,r6 /* See if there is a PTE here */
705: rlwinm r8,r5,31,2,25 /* Line it up and check if empty */
706:
707: beq+ protul /* There's no PTE to invalidate... */
708:
709: xor r8,r8,r6 /* Back hash to virt index */
710: rlwimi r9,r5,22,4,9 /* Move in the API */
711: lis r12,HIGH_ADDR(EXT(tlb_system_lock)) /* Get the TLBIE lock */
712: rlwinm r5,r5,0,1,31 /* Clear the valid bit */
713: ori r12,r12,LOW_ADDR(EXT(tlb_system_lock)) /* Grab up the bottom part */
714: mfspr r11,pvr /* Find out what kind of machine we are */
715: rlwimi r9,r8,6,10,19 /* Create the virtual address */
716: rlwinm r11,r11,16,16,31 /* Isolate CPU type */
717:
718: stw r5,0(r6) /* Make the PTE invalid */
719: cmplwi cr1,r11,3 /* Is this a 603? */
720: sync /* Make sure the invalid is stored */
721:
722: lwarx r11,0,r12 ; ?
723:
724: tlbhangp: lwarx r11,0,r12 /* Get the TLBIE lock */
725: rlwinm r8,r6,29,29,31 /* Get the bit position of entry */
726: mr. r11,r11 /* Is it locked? */
727: lis r5,0x8000 /* Start up a bit mask */
728: li r11,1 /* Get our lock word */
729: bne- tlbhangp /* It's locked, go wait... */
730: stwcx. r11,0,r12 /* Try to get it */
731: bne- tlbhangp /* We was beat... */
732:
733: li r11,0 /* Lock clear value */
734:
735: tlbie r9 /* Invalidate it everywhere */
736:
737: beq- cr1,its603p /* It's a 603, skip the tlbsync... */
738:
739: eieio /* Make sure that the tlbie happens first */
740: tlbsync /* wait for everyone to catch up */
741:
742: its603p: stw r11,0(r12) /* Clear the lock */
743: srw r5,r5,r8 /* Make a "free slot" mask */
744: sync /* Make sure of it all */
745:
746: lwz r6,4(r6) /* Get the latest reference and change bits */
747: stw r11,mmPTEent(r10) /* Clear the pointer to the PTE */
748: rlwinm r6,r6,0,23,24 /* Extract the RC bits */
749: lwz r9,PCAallo(r7) /* Get the allocation control bits */
750: rlwinm r8,r5,24,8,15 /* Make the autogen bit to turn off */
751: or r9,r9,r5 /* Set the slot free */
752: rlwimi r8,r8,24,16,23 /* Get lock bit mask to turn it off */
753: andc r9,r9,r8 /* Clear the auto and lock bits */
754: li r5,pepte1 /* Get displacement to the second word of master pte */
755: stw r9,PCAallo(r7) /* Store the allocation controls */
756:
757: lwarx r11,r5,r3 ; ?
758:
759: protmod: lwarx r11,r5,r3 /* Get the master copy */
760: or r11,r11,r6 /* Merge in latest RC */
761: stwcx. r11,r5,r3 /* Save it back */
762: bne- protmod /* If it changed, try again... */
763:
764: sync /* Make sure that chain is updated */
765:
766: protul: li r4,0 /* Get a 0 */
767: lwz r10,mmnext(r10) /* Get the next */
768: stw r4,0(r7) /* Unlock the hash chain */
769: b protnext /* Go get the next one */
770:
771: .align 4
772:
773: protdone: mtmsr r0 /* Interrupts and translation back on */
774: isync
775: #if PERFTIMES && DEBUG
776: mflr r11
777: li r3,27
778: bl EXT(dbgLog2) ; Start of hw_add_map
779: mtlr r11
780: #endif
781: blr /* Return... */
782:
783:
784: /*
785: * hw_pte_comm(physent) - Do something to the PTE pointing to a physical page
786: *
787: * Upon entry, R3 contains a pointer to a physical entry which is locked.
788: * Note that this must be done with both interruptions off and VM off
789: *
790: * First, we set up CRs 5 and 7 to indicate which of the 7 calls this is.
791: *
792: * Now we scan the mappings to invalidate any with and active PTE.
793: *
794: * Acquire the lock on the PTEG hash list for the mapping being processed.
795: *
796: * If the current mapping has a PTE entry, we invalidate
797: * it and merge the reference and change information into the phys_entry.
798: *
799: * Next, unlock the hash list and go on to the next mapping.
800: *
801: *
802: *
803: */
804:
805: .align 5
806: .globl EXT(hw_inv_all)
807:
808: LEXT(hw_inv_all)
809:
810: li r9,0x800 /* Indicate invalidate all */
811: b hw_pte_comm /* Join in the fun... */
812:
813:
814: .align 5
815: .globl EXT(hw_tst_mod)
816:
817: LEXT(hw_tst_mod)
818:
819: lwz r8,pepte1(r3) ; Get the saved PTE image
820: li r9,0x400 /* Indicate test modify */
821: rlwinm. r8,r8,25,31,31 ; Make change bit into return code
822: beq+ hw_pte_comm ; Assume we do not know if it is set...
823: mr r3,r8 ; Set the return code
824: blr ; Return quickly...
825:
826: .align 5
827: .globl EXT(hw_tst_ref)
828:
829: LEXT(hw_tst_ref)
830: lwz r8,pepte1(r3) ; Get the saved PTE image
831: li r9,0x200 /* Indicate test reference bit */
832: rlwinm. r8,r8,24,31,31 ; Make reference bit into return code
833: beq+ hw_pte_comm ; Assume we do not know if it is set...
834: mr r3,r8 ; Set the return code
835: blr ; Return quickly...
836:
837: /*
838: * Note that the following are all in one CR for ease of use later
839: */
840: .align 4
841: .globl EXT(hw_set_mod)
842:
843: LEXT(hw_set_mod)
844:
845: li r9,0x008 /* Indicate set modify bit */
846: b hw_pte_comm /* Join in the fun... */
847:
848:
849: .align 4
850: .globl EXT(hw_clr_mod)
851:
852: LEXT(hw_clr_mod)
853:
854: li r9,0x004 /* Indicate clear modify bit */
855: b hw_pte_comm /* Join in the fun... */
856:
857:
858: .align 4
859: .globl EXT(hw_set_ref)
860:
861: LEXT(hw_set_ref)
862:
863: li r9,0x002 /* Indicate set reference */
864: b hw_pte_comm /* Join in the fun... */
865:
866: .align 5
867: .globl EXT(hw_clr_ref)
868:
869: LEXT(hw_clr_ref)
870:
871: li r9,0x001 /* Indicate clear reference bit */
872: b hw_pte_comm /* Join in the fun... */
873:
874:
875: /*
876: * This is the common stuff.
877: */
878:
879: .align 5
880:
881: hw_pte_comm: /* Common routine for pte tests and manips */
882:
883: #if PERFTIMES && DEBUG
884: mflr r11
885: mr r7,r3
886: lwz r4,4(r3)
887: mr r5,r9
888: li r3,28
889: bl EXT(dbgLog2) ; Start of hw_add_map
890: mr r3,r7
891: mtlr r11
892: #endif
893: lwz r10,pephyslink(r3) /* Get the first mapping block */
894: mfmsr r0 /* Save the MSR */
895: rlwinm. r10,r10,0,0,26 ; Clear out the flags from first link and see if we are mapped
896: rlwinm r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear interruptions */
897: mtcrf 0x05,r9 /* Set the call type flags into cr5 and 7 */
898: rlwinm r12,r12,0,28,25 /* Clear IR and DR */
899: beq- comnmap ; No mapping
900: dcbt br0,r10 ; Touch the first mapping in before the isync
901:
902: comnmap: mtmsr r12 /* Clear interruptions and turn off translation */
903: /* NOTE: we can get away with just turning the
904: instruction translation off here because we
905: are running with virtual equals real. If not,
906: there would be an "implied branch", which wouldn't
907: be too good. */
908:
909: isync /* Make sure that translation is off */
910: beq- commdone ; Nothing us mapped to this page...
911: b commnext ; Jump to first pass (jump here so we can align loop)
912:
913: .align 5
914:
915: commnext: lwz r11,mmnext(r10) ; Get the pointer to the next mapping (if any)
916: lwz r7,mmPTEhash(r10) /* Get pointer to hash list anchor */
917: lwz r5,mmPTEv(r10) /* Get the virtual address */
918: mr. r11,r11 ; More mappings to go?
919: rlwinm r7,r7,0,0,25 /* Round hash list down to PCA boundary */
920: beq- commnxtch ; No more mappings...
921: dcbt br0,r11 ; Touch the next mapping
922:
923: commnxtch: li r12,1 /* Get the locked value */
924:
925: lwarx r11,0,r7 ; ?
926:
927: commLck1: lwarx r11,0,r7 /* Get the PTEG lock */
928: mr. r11,r11 /* Is it locked? */
929: bne- commLckw1 /* Yeah... */
930: stwcx. r12,0,r7 /* Try to take it */
931: bne- commLck1 /* Someone else was trying, try again... */
932: b commSXg1 /* All done... */
933:
934: .align 4
935:
936: commLckw1: mr. r11,r11 /* Check if it's already held */
937: beq+ commLck1 /* It's clear... */
938: lwz r11,0(r7) /* Get lock word again... */
939: b commLckw1 /* Wait... */
940:
941: .align 4
942:
943: commSXg1: isync /* Make sure we haven't used anything yet */
944:
945: lwz r6,mmPTEent(r10) /* Get the pointer to the PTE now that the lock's set */
946:
947: rlwinm r9,r5,1,0,3 /* Move in the segment */
948: mr. r6,r6 /* See if there is a PTE entry here */
949: rlwinm r8,r5,31,2,25 /* Line it up and check if empty */
950:
951: beq+ commul /* There's no PTE to invalidate... */
952:
953: xor r8,r8,r6 /* Back hash to virt index */
954: rlwimi r9,r5,22,4,9 /* Move in the API */
955: lis r12,HIGH_ADDR(EXT(tlb_system_lock)) /* Get the TLBIE lock */
956: rlwinm r5,r5,0,1,31 /* Clear the valid bit */
957: ori r12,r12,LOW_ADDR(EXT(tlb_system_lock)) /* Grab up the bottom part */
958: rlwimi r9,r8,6,10,19 /* Create the virtual address */
959:
960: stw r5,0(r6) /* Make the PTE invalid */
961: mfspr r4,pvr /* Find out what kind of machine we are */
962: sync /* Make sure the invalid is stored */
963:
964: lwarx r11,0,r12 ; ?
965:
966: tlbhangco: lwarx r11,0,r12 /* Get the TLBIE lock */
967: rlwinm r8,r6,29,29,31 /* Get the bit position of entry */
968: mr. r11,r11 /* Is it locked? */
969: lis r5,0x8000 /* Start up a bit mask */
970: li r11,1 /* Get our lock word */
971: bne- tlbhangco /* It's locked, go wait... */
972: stwcx. r11,0,r12 /* Try to get it */
973: bne- tlbhangco /* We was beat... */
974:
975: rlwinm r4,r4,16,16,31 /* Isolate CPU type */
976: li r11,0 /* Lock clear value */
977: cmplwi r4,3 /* Is this a 603? */
978:
979: tlbie r9 /* Invalidate it everywhere */
980:
981: beq- its603co /* It's a 603, skip the tlbsync... */
982:
983: eieio /* Make sure that the tlbie happens first */
984: tlbsync /* wait for everyone to catch up */
985:
986: its603co: stw r11,0(r12) /* Clear the lock */
987: srw r5,r5,r8 /* Make a "free slot" mask */
988: sync /* Make sure of it all */
989:
990: lwz r6,4(r6) /* Get the latest reference and change bits */
991: lwz r9,PCAallo(r7) /* Get the allocation control bits */
992: stw r11,mmPTEent(r10) /* Clear the pointer to the PTE */
993: rlwinm r8,r5,24,8,15 /* Make the autogen bit to turn off */
994: or r9,r9,r5 /* Set the slot free */
995: rlwimi r8,r8,24,16,23 /* Get lock bit mask to turn it off */
996: rlwinm r4,r6,0,23,24 /* Extract the RC bits */
997: andc r9,r9,r8 /* Clear the auto and lock bits */
998: li r5,pepte1 /* Get displacement to the second word of master pte */
999: stw r9,PCAallo(r7) /* Store the allocation controls */
1000:
1001: lwarx r11,r5,r3 ; ?
1002:
1003: commmod: lwarx r11,r5,r3 /* Get the master copy */
1004: or r11,r11,r4 /* Merge in latest RC */
1005: stwcx. r11,r5,r3 /* Save it back */
1006: bne- commmod /* If it changed, try again... */
1007:
1008: sync /* Make sure that chain is updated */
1009:
1010: commul: lwz r10,mmnext(r10) /* Get the next */
1011: li r4,0 /* Make sure this is 0 */
1012: mr. r10,r10 ; Is there another mapping?
1013: stw r4,0(r7) /* Unlock the hash chain */
1014: bne+ commnext ; Go get the next if there is one...
1015:
1016: /*
1017: * Now that all PTEs have been invalidated and the master RC bits are updated,
1018: * we go ahead and figure out what the original call was and do that. Note that
1019: * another processor could be messing around and may have entered one of the
1020: * PTEs we just removed into the hash table. Too bad... You takes yer chances.
1021: * If there's a problem with that, it's because some higher level was trying to
1022: * do something with a mapping that it shouldn't. So, the problem's really
1023: * there, nyaaa, nyaaa, nyaaa... nyaaa, nyaaa... nyaaa! So there!
1024: */
1025:
1026: commdone: li r5,pepte1 /* Get displacement to the second word of master pte */
1027: blt cr5,commfini /* We're finished, it was invalidate all... */
1028: bgt cr5,commtst /* It was a test modified... */
1029: beq cr5,commtst /* It was a test reference... */
1030:
1031: /*
1032: * Note that we need to to do the interlocked update here because another processor
1033: * can be updating the reference and change bits even though the physical entry
1034: * is locked. All modifications to the PTE portion of the physical entry must be
1035: * done via interlocked update.
1036: */
1037:
1038: lwarx r8,r5,r3 ; ?
1039:
1040: commcng: lwarx r8,r5,r3 /* Get the master copy */
1041:
1042: bng cr7,commclrr /* Jump if not clear change bit... */
1043: rlwinm r8,r8,0,25,23 /* Clear the change bit */
1044: b commsave /* Go save the new version... */
1045:
1046: .align 4
1047:
1048: commclrr: bns cr7,commsetm /* Jump away if not clear reference... */
1049: rlwinm r8,r8,0,24,22 /* Clear the change bit */
1050: b commsave /* Go save the new version... */
1051:
1052: .align 4
1053:
1054: commsetm: bnl cr7,commsetr /* Jump away if not set modified... */
1055: ori r8,r8,0x0080 /* Set the modified bit */
1056: b commsave /* Go save the new version... */
1057:
1058: .align 4
1059:
1060: commsetr: ori r8,r8,0x0100 /* Set the referenced bit */
1061:
1062: commsave: stwcx. r8,r5,r3 /* Save it back */
1063: bne- commcng /* If it changed, try again... */
1064:
1065: mtmsr r0 /* Interrupts and translation back on */
1066: isync
1067: #if PERFTIMES && DEBUG
1068: mflr r11
1069: mr r4,r3
1070: li r3,29
1071: bl EXT(dbgLog2) ; Start of hw_add_map
1072: mr r3,r4
1073: mtlr r11
1074: #endif
1075: blr /* Return... */
1076:
1077: .align 4
1078:
1079: commtst: lwz r8,pepte1(r3) /* Get the PTE */
1080: bne- cr5,commtcb ; This is for the change bit...
1081: mtmsr r0 ; Interrupts and translation back on
1082: rlwinm r3,r8,24,31,31 ; Copy reference bit to bit 31
1083: isync ; Toss prefetching
1084: #if PERFTIMES && DEBUG
1085: mflr r11
1086: mr r4,r3
1087: li r3,29
1088: bl EXT(dbgLog2) ; Start of hw_add_map
1089: mr r3,r4
1090: mtlr r11
1091: #endif
1092: blr ; Return...
1093:
1094: .align 4
1095:
1096: commtcb: rlwinm r3,r8,25,31,31 ; Copy change bit to bit 31
1097:
1098: commfini: mtmsr r0 ; Interrupts and translation back on
1099: isync ; Toss prefetching
1100:
1101: #if PERFTIMES && DEBUG
1102: mflr r11
1103: mr r4,r3
1104: li r3,29
1105: bl EXT(dbgLog2) ; Start of hw_add_map
1106: mr r3,r4
1107: mtlr r11
1108: #endif
1109: blr ; Return...
1110:
1111: /*
1112: * hw_phys_attr(struct phys_entry *pp, vm_prot_t prot, unsigned int wimg) - Sets the default physical page attributes
1113: *
1114: * Note that this must be done with both interruptions off and VM off
1115: * Move the passed in attributes into the pte image in the phys entry
1116: *
1117: *
1118: */
1119:
1120: .align 5
1121: .globl EXT(hw_phys_attr)
1122:
1123: LEXT(hw_phys_attr)
1124:
1125: #if PERFTIMES && DEBUG
1126: mflr r11
1127: mr r8,r3
1128: mr r7,r5
1129: mr r5,r4
1130: // lwz r4,4(r3)
1131: li r4,0x1111
1132: li r3,30
1133: bl EXT(dbgLog2) ; Start of hw_add_map
1134: mr r3,r8
1135: mr r4,r5
1136: mr r5,r7
1137: mtlr r11
1138: #endif
1139: mfmsr r0 /* Save the MSR */
1140: andi. r5,r5,0x0078 /* Clean up the WIMG */
1141: rlwinm r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear interruptions */
1142: rlwimi r5,r4,0,30,31 /* Move the protection into the wimg register */
1143: la r6,pepte1(r3) /* Point to the default pte */
1144: rlwinm r12,r12,0,28,25 /* Clear IR and DR */
1145:
1146: mtmsr r12 /* Clear interruptions and turn off translation */
1147: /* NOTE: we can get away with just turning the
1148: instruction translation off here because we
1149: are running with virtual equals real. If not,
1150: there would be an "implied branch", which wouldn't
1151: be too good. */
1152:
1153: isync /* Make sure that translation is off */
1154:
1155: lwarx r10,0,r6 ; ?
1156:
1157: atmattr: lwarx r10,0,r6 /* Get the pte */
1158: rlwimi r10,r5,0,25,31 /* Move in the new attributes */
1159: stwcx. r10,0,r6 /* Try it on for size */
1160: bne- atmattr /* Someone else was trying, try again... */
1161:
1162: mtmsr r0 /* Interrupts and translation back on */
1163: isync
1164: #if PERFTIMES && DEBUG
1165: mflr r11
1166: mr r4,r10
1167: li r3,31
1168: bl EXT(dbgLog2) ; Start of hw_add_map
1169: mtlr r11
1170: #endif
1171: blr /* All done... */
1172:
1173:
1174:
1175: /*
1176: * handlePF - handle a page fault interruption
1177: *
1178: * If the fault can be handled, this routine will RFI directly,
1179: * otherwise it will return with all registers as in entry.
1180: *
1181: * Upon entry, state and all registers have been saved in savearea.
1182: * This is pointed to by R13.
1183: * IR and DR are off, interrupts are masked,
1184: * Floating point be disabled.
1185: * R3 is the interrupt code.
1186: *
1187: * If we bail, we must restore cr5, and all registers except 6 and
1188: * 3.
1189: *
1190: */
1191:
1192: .align 5
1193: .globl EXT(handlePF)
1194:
1195: LEXT(handlePF)
1196:
1197: /*
1198: * This first part does a quick check to see if we can handle the fault.
1199: * We can't handle any kind of protection exceptions here, so we pass
1200: * them up to the next level.
1201: *
1202: * The mapping lists are kept in MRS (most recently stolen)
1203: * order on queues anchored within from the
1204: * PTEG to which the virtual address hashes. This is further segregated by
1205: * the low-order 3 bits of the VSID XORed with the segment number and XORed
1206: * with bits 4-7 of the vaddr in an attempt to keep the searches
1207: * short.
1208: *
1209: * MRS is handled by moving the entry to the head of its list when stolen in the
1210: * assumption that it will be revalidated soon. Entries are created on the head
1211: * of the list because they will be used again almost immediately.
1212: *
1213: * We need R13 set to the savearea, R3 set to the interrupt code, and R2
1214: * set to the per_proc.
1215: *
1216: * NOTE: In order for a page-fault redrive to work, the translation miss
1217: * bit must be set in the DSISR (or SRR1 for IFETCH). That must occur
1218: * before we come here.
1219: */
1220:
1221: cmplwi r3,T_INSTRUCTION_ACCESS /* See if this is for the instruction */
1222: lwz r8,savesrr1(r13) ; Get the MSR to determine mode
1223: beq- gotIfetch ; We have an IFETCH here...
1224:
1225: lwz r7,savedsisr(r13) /* Get the DSISR */
1226: lwz r6,savedar(r13) /* Get the fault address */
1227: b ckIfProt ; Go check if this is a protection fault...
1228:
1229: gotIfetch: mr r7,r8 ; IFETCH info is in SRR1
1230: lwz r6,savesrr0(r13) /* Get the instruction address */
1231:
1232: ckIfProt: rlwinm. r7,r7,0,1,1 ; Is this a protection exception?
1233: beqlr- ; Yes... (probably not though)
1234:
1235: /*
1236: * We will need to restore registers if we bail after this point.
1237: * Note that at this point several SRs have been changed to the kernel versions.
1238: * Therefore, for these we must build these values.
1239: */
1240:
1241: #if PERFTIMES && DEBUG
1242: mflr r11
1243: mr r5,r6
1244: mr r4,r3
1245: li r3,32
1246: bl EXT(dbgLog2) ; Start of hw_add_map
1247: mr r3,r4
1248: mtlr r11
1249: mfsprg r2,0
1250: #endif
1251: lwz r3,PP_USERSPACE(r2) ; Get the user space
1252: rlwinm. r8,r8,0,MSR_PR_BIT,MSR_PR_BIT ; Supervisor state access?
1253: eqv r1,r1,r1 /* Fill the bottom with foxes */
1254: rlwimi r3,r6,24,8,11 ; Insert the segment number into the VSID to make the user VSID
1255: bne+ notsuper ; If user access, we have the VSID already...
1256:
1257: mfsrin r3,r6 ; Get the faulting segment reg for kernel accesses
1258:
1259: notsuper: mfspr r5,sdr1 /* Get hash table base and size */
1260: rlwinm r9,r6,2,2,5 ; Move nybble 1 up to 0 (keep aligned with VSID)
1261: rlwinm r3,r3,6,2,25 /* Position the space for the VSID */
1262: rlwimi r1,r5,16,0,15 /* Make table size -1 out of mask */
1263: rlwinm r7,r6,26,10,25 /* Isolate the page index */
1264: xor r9,r9,r3 ; Splooch vaddr nybble 0 (from VSID) and 1 together
1265: or r8,r5,r1 /* Point to the last byte in table */
1266: xor r7,r7,r3 /* Get primary hash */
1267: rlwinm r3,r3,1,1,24 /* Position VSID for pte ID */
1268: addi r8,r8,1 /* Point to the PTEG Control Area */
1269: rlwinm r9,r9,8,27,29 ; Get splooched bits in place
1270: and r7,r7,r1 /* Wrap the hash */
1271: rlwimi r3,r6,10,26,31 /* Move API into pte ID */
1272: add r8,r8,r7 /* Point to our PCA entry */
1273: rlwinm r12,r3,27,27,29 ; Get low 3 bits of the VSID for look-aside hash
1274: la r11,PCAhash(r8) /* Point to the mapping hash area */
1275: xor r9,r9,r12 ; Finish splooching nybble 0, 1, and the low bits of the VSID
1276:
1277:
1278: /*
1279: * We have about as much as we need to start searching the autogen
1280: * and mappings. From here on, any kind of failure will bail, and
1281: * contention will either bail or restart from here.
1282: *
1283: *
1284: */
1285:
1286: li r12,1 /* Get the locked value */
1287: dcbt 0,r11 /* We'll need the hash area in a sec, so get it */
1288: add r11,r11,r9 /* Point to the right mapping hash slot */
1289:
1290: lwarx r10,0,r8 ; ?
1291:
1292: ptegLck: lwarx r10,0,r8 /* Get the PTEG lock */
1293: mr. r10,r10 /* Is it locked? */
1294: bne- ptegLckw /* Yeah... */
1295: stwcx. r12,0,r8 /* Take take it */
1296: bne- ptegLck /* Someone else was trying, try again... */
1297: b ptegSXg /* All done... */
1298:
1299: .align 4
1300:
1301: ptegLckw: mr. r10,r10 /* Check if it's already held */
1302: beq+ ptegLck /* It's clear... */
1303: lwz r10,0(r8) /* Get lock word again... */
1304: b ptegLckw /* Wait... */
1305:
1306: .align 5
1307:
1308: nop ; Force ISYNC to last instruction in IFETCH
1309: nop
1310: nop
1311:
1312: ptegSXg: isync /* Make sure we haven't used anything yet */
1313:
1314: lwz r9,0(r11) /* Pick up first mapping block */
1315: mr r5,r11 /* Get the address of the anchor */
1316: mr r7,r9 /* Save the first in line */
1317: b findmap ; Take space and force loop to cache line
1318:
1319: findmap: mr. r12,r9 /* Are there more? */
1320: beq- tryAuto /* Nope, nothing in mapping list for us... */
1321:
1322: lwz r10,mmPTEv(r12) /* Get unique PTE identification */
1323: lwz r9,mmhashnext(r12) /* Get the chain, just in case */
1324: cmplw r10,r3 /* Did we hit our PTE? */
1325: lwz r6,mmPTEent(r12) /* Get the pointer to the hash table entry */
1326: mr r5,r12 /* Save the current as previous */
1327: bne- findmap ; Nothing here, try the next...
1328:
1329: ; Cache line bounary here
1330:
1331: cmplwi cr1,r6,0 /* Is there actually a PTE entry in the hash? */
1332: lwz r2,mmphysent(r12) /* Get the physical entry */
1333: bne- cr1,MustBeOK /* There's an entry in the hash table, so, this must
1334: have been taken care of already... */
1335: cmplwi cr2,r2,0 /* Is there a physical entry? */
1336: li r0,0x0100 /* Force on the reference bit whenever we make a PTE valid */
1337: addi r2,r2,pepte1 /* Point to the second half of PTE in physent */
1338: lis r4,0x8000 /* Tell, PTE inserter that this wasn't an auto */
1339: bne+ cr2,gotphys /* Skip down if we have a physical entry */
1340: la r2,mmPTEr(r12) /* Point to the PTE in the mapping */
1341: li r0,0x0180 /* When there is no physical entry, force on
1342: both R and C bits to keep hardware from
1343: updating the PTE to set them. We don't
1344: keep track of RC for I/O areas, so this is ok */
1345:
1346: gotphys: lwz r2,0(r2) /* Get the second part of the PTE */
1347: b insert /* Go insert into the PTEG... */
1348:
1349: MustBeOK: li r10,0 /* Get lock clear value */
1350: li r3,T_IN_VAIN /* Say that we handled it */
1351: stw r10,PCAlock(r8) /* Clear the PTEG lock */
1352: sync
1353: #if PERFTIMES && DEBUG
1354: mflr r11
1355: mr r4,r3
1356: li r3,33
1357: bl EXT(dbgLog2) ; Start of hw_add_map
1358: mr r3,r4
1359: mtlr r11
1360: #endif
1361: blr /* Blow back and handle exception */
1362:
1363:
1364:
1365: /*
1366: * We couldn't find it in the mapping list. As a last try, we will
1367: * see if we can autogen it.
1368: *
1369: * An autogen area is defined as a contiguous range of virtual addresses that
1370: * map to a fixed contiguous area of physical storage. This implimentation
1371: * does not support an area that is not in the kernal address space. We may
1372: * want to consider doing that later. The number and size of autogen areas
1373: * are not defined, but it would be silly to define them for one or two pages
1374: * or hundreds of individual areas.
1375: *
1376: * These areas are accessed at this level read-only without locks. Higher
1377: * levels can add an autogen area to the front of the list by moving the anchor
1378: * to the forward pointer and then doing a compare-and-swap to set the new
1379: * anchor. Removals are tougher. They shouldn't happen frequently, if at all.
1380: * The only problem is at the moment of the breaking of the chain. It is possible
1381: * that another processor is using the element being removed. So, unless we know
1382: * for a fact that the element is unused, we can't delete it. So, removal works
1383: * like this: first, the we lock the chain at the higher level, to insure that
1384: * no more than one processor is deleteing elements. Next, we move the forward
1385: * pointer from the removee to the forward of its previous. (we find the previous
1386: * under the lock.) Note that the removee's forward still points to the next.
1387: * The lock on the chain can be released now.
1388: *
1389: * At this point, a second processor could be traversing the list. If it hasn't
1390: * reached the removee yet, it can't see it because to it, it has been removed.
1391: * If it happens to be at the removed one, it will process it and go to the next,
1392: * It is up to the remover to insure that the there is enough time for the other
1393: * processor(s) to finish. What it does is to send a processor synchronize
1394: * SIGP to all other CPU and wait until they have been received. Since all
1395: * code that traverses the list is uninterruptable, the SYNC command can't
1396: * occur until all CPUs are done with the removee.
1397: *
1398: * The autogen list is ordered ascending. By relaxing the
1399: * "must-link-at-head" restriction, and requiring a lock for addition,
1400: * we can order the updates of the links such that a
1401: * non-interlocked search can proceed during the update. We
1402: * get a zero-cost early bail-out from the autogen search, and the
1403: * additional overhead from maintanence is nearly nil.
1404: *
1405: * The one problem we have here is autogenned execute protected areas, we can
1406: * end up with a persistant ISI. So, the solution is just say NO. No to execute
1407: * protected autogen areas.
1408: */
1409:
1410: .align 4
1411:
1412: tryAuto: lis r10,HIGH_ADDR(EXT(AutoGenList)) /* Get the top part of autogen list anchor */
1413: rlwinm. r11,r3,0,5,24 /* Check if we are in the kernel */
1414: ori r10,r10,LOW_ADDR(EXT(AutoGenList)) /* Get the bottom part */
1415: beq- checkAuto /* In kernel, see if we can autogen... */
1416:
1417: /*
1418: * When we come here, we know that we can't handle this. Restore whatever
1419: * state that we trashed and go back to continue handling the interrupt.
1420: */
1421:
1422: realFault: li r10,0 /* Get lock clear value */
1423: lwz r3,saveexception(r13) /* Figure out the exception code again */
1424: stw r10,PCAlock(r8) /* Clear the PTEG lock */
1425: #if PERFTIMES && DEBUG
1426: mflr r11
1427: mr r4,r3
1428: li r3,33
1429: bl EXT(dbgLog2) ; Start of hw_add_map
1430: mr r3,r4
1431: mtlr r11
1432: #endif
1433: blr /* Blow back and handle exception */
1434:
1435: .align 4
1436:
1437: checkAuto: lwz r10,0(r10) /* Get the first autogen area */
1438:
1439: findAuto: mr. r11,r10 /* Are there more? */
1440: beq- realFault /* Nope, no autogen, it's a fault... */
1441:
1442: lwz r4,AGNstart(r11) /* Get start of range */
1443: lwz r9,AGNsize(r11) /* Get the size */
1444: sub. r5,r6,r4 /* Get distance into region */
1445: lwz r10,AGNnext(r11) /* Assure we'll need the next one */
1446: blt- realFault /* Bail out when we're past any possible hit */
1447: cmplw r5,r9 /* See if we fit in the range. This works even
1448: on an unordered list. If the start address
1449: is after the address under test, the subtract
1450: will give us a negative number, but with a
1451: logical test, it will be a bigger number */
1452: lwz r2,AGNpteX(r11) /* Get translation--should be in cache */
1453: bgt+ findAuto /* Not in this slot, try again... */
1454:
1455: lis r4,0x8080 /* Indicate that this was autogened */
1456: li r0,0x0180 /* Autogenned areas always set RC bits.
1457: This keeps the hardware from having
1458: to do two storage writes */
1459:
1460: /*
1461: * Here where we insert the PTE into the hash. The PTE image is in R3, R2.
1462: * The PTEG allocation controls are a bit map of the state of the PTEG. The
1463: * PCAlock bits are a temporary lock for the specified PTE. PCAfree indicates that
1464: * the PTE slot is empty. PCAauto means that it comes from an autogen area. These
1465: * guys do not keep track of reference and change and are actually "wired".
1466: * They're easy to maintain and are second in priority for a steal. PCAsteal
1467: * is a sliding position mask used to "randomize" PTE slot stealing. All 4 of these
1468: * fields fit in a single word and are loaded and stored under control of the
1469: * PTEG control area lock (PCAlock).
1470: *
1471: * Physically, the fields are arranged:
1472: * 0: PCAfree
1473: * 1: PCAauto
1474: * 2: PCAlock
1475: * 3: PCAsteal
1476: */
1477:
1478: insert: lwz r10,PCAallo(r8) /* Get the PTEG controls */
1479: eqv r6,r6,r6 /* Get all ones */
1480: mr r11,r10 /* Make a copy */
1481: rlwimi r6,r10,8,16,23 /* Insert sliding steal position */
1482: rlwimi r11,r11,24,24,31 /* Duplicate the locked field */
1483: addi r6,r6,-256 /* Form mask */
1484: rlwimi r11,r11,16,0,15 /* This gives us a quadrupled lock mask */
1485: rlwinm r5,r10,31,24,0 /* Slide over the mask for next time */
1486: mr r9,r10 /* Make a copy to test */
1487: not r11,r11 /* Invert the quadrupled lock */
1488: or r2,r2,r0 /* Force on R, and maybe C bit */
1489: and r9,r9,r11 /* Remove the locked guys */
1490: rlwimi r5,r5,8,24,24 /* Wrap bottom bit to top in mask */
1491: rlwimi r9,r11,0,16,31 /* Put two copies of the unlocked entries at the end */
1492: rlwimi r10,r5,0,24,31 /* Move steal map back in */
1493: and r9,r9,r6 /* Set the starting point for stealing */
1494:
1495: /* So, now we have in R9:
1496: byte 0 = ~locked & free
1497: byte 1 = ~locked & autogen
1498: byte 2 = ~locked & (PCAsteal - 1)
1499: byte 3 = ~locked
1500:
1501: Each bit position represents (modulo 8) a PTE. If it is 1, it is available for
1502: allocation at its priority level, left to right.
1503:
1504: Additionally, the PCA steal field in R10 has been rotated right one bit.
1505: */
1506:
1507:
1508: cntlzw r6,r9 /* Allocate a slot */
1509: mr r14,r12 /* Save our mapping for later */
1510: cmplwi r6,32 /* Was there anything available? */
1511: rlwinm r7,r6,29,30,31 /* Get the priority slot we got this from */
1512: rlwinm r6,r6,0,29,31 ; Isolate bit position
1513: srw r11,r4,r6 /* Position the PTEG control bits */
1514: rlwinm r6,r6,0,29,31 /* Calculate the PTE slot mask */
1515: andc r10,r10,r11 /* Turn off the free and auto bits */
1516: beq- realFault /* Arghh, no slots! Take the long way 'round... */
1517:
1518: /* Remember, we've already set up the mask pattern
1519: depending upon how we got here:
1520: if got here from simple mapping, R4=0x80000000,
1521: if we got here from autogenit is 0x80800000. */
1522:
1523: rlwinm r6,r6,3,26,28 /* Start calculating actual PTE address */
1524: rlwinm. r11,r11,0,8,15 /* Isolate just the auto bit (remember about it too) */
1525: add r6,r8,r6 /* Get position into PTEG control area */
1526: cmplwi cr1,r7,1 /* Set the condition based upon the old PTE type */
1527: sub r6,r6,r1 /* Switch it to the hash table */
1528: or r10,r10,r11 /* Turn auto on if it is (PTEG control all set up now) */
1529: subi r6,r6,1 /* Point right */
1530: stw r10,PCAallo(r8) /* Allocate our slot */
1531: dcbt br0,r6 ; Touch in the PTE
1532: bne wasauto /* This was autogenned... */
1533:
1534: stw r6,mmPTEent(r14) /* Link the mapping to the PTE slot */
1535:
1536: /*
1537: * So, now we're here and what exactly do we have? We've got:
1538: * 1) a full PTE entry, both top and bottom words in R3 and R2
1539: * 2) an allocated slot in the PTEG.
1540: * 3) R8 still points to the PTEG Control Area (PCA)
1541: * 4) R6 points to the PTE entry.
1542: * 5) R1 contains length of the hash table-1. We use this to back-translate
1543: * a PTE to a virtual address so we can invalidate TLBs.
1544: * 6) R11 has a copy of the PCA controls we set.
1545: * 7) R7 indicates what the PTE slot was before we got to it. 0 shows
1546: * that it was empty, 1 that it was an autogen, and 2 or 3, that it was
1547: * a non-autogen entry. CR1 is set to LT for empty, EQ for auto, and GT
1548: * otherwise.
1549: * 8) So far as our selected PTE, it should be valid if it was stolen
1550: * and invalid if not. We could put some kind of assert here to
1551: * check, but I think that I'd rather leave it in as a mysterious,
1552: * non-reproducable bug.
1553: * 9) The new PTE's mapping has been moved to the front of its PTEG hash list
1554: * so that it's kept in some semblance of a MRU list.
1555: * 10) R14 points to the mapping we're adding.
1556: *
1557: * So, what do we have to do yet?
1558: * 1) If we stole a slot, we need to invalidate the PTE completely.
1559: * 2) If we stole one AND it was not an autogen,
1560: * copy the entire old PTE (including R and C bits) to its mapping.
1561: * 3) Set the new PTE in the PTEG and make sure it is valid.
1562: * 4) Unlock the PTEG control area.
1563: * 5) Go back to the interrupt handler, changing the interrupt
1564: * code to "in vain" which will restore the registers and bail out.
1565: *
1566: */
1567:
1568: wasauto: oris r3,r3,0x8000 /* Turn on the valid bit */
1569: blt+ cr1,slamit /* It was empty, go slam it on in... */
1570:
1571: lwz r10,0(r6) /* Grab the top part of the PTE */
1572: rlwinm r12,r6,6,4,19 /* Match up the hash to a page boundary */
1573: rlwinm r5,r10,5,4,19 /* Extract the VSID to a page boundary */
1574: rlwinm r10,r10,0,1,31 /* Make it invalid */
1575: xor r12,r5,r12 /* Calculate vaddr */
1576: stw r10,0(r6) /* Invalidate the PTE */
1577: rlwinm r5,r10,7,27,29 ; Move nybble 0 up to subhash position
1578: rlwimi r12,r10,1,0,3 /* Move in the segment portion */
1579: lis r9,HIGH_ADDR(EXT(tlb_system_lock)) /* Get the TLBIE lock */
1580: xor r5,r5,r10 ; Splooch nybble 0 and 1
1581: rlwimi r12,r10,22,4,9 /* Move in the API */
1582: ori r9,r9,LOW_ADDR(EXT(tlb_system_lock)) /* Grab up the bottom part */
1583: rlwinm r4,r10,27,27,29 ; Get low 3 bits of the VSID for look-aside hash
1584:
1585: sync /* Make sure the invalid is stored */
1586:
1587: xor r4,r4,r5 ; Finish splooching nybble 0, 1, and the low bits of the VSID
1588:
1589: lwarx r5,0,r9 ; ?
1590:
1591: tlbhang: lwarx r5,0,r9 /* Get the TLBIE lock */
1592:
1593: rlwinm r4,r4,0,27,29 ; Clean up splooched hash value
1594:
1595: mr. r5,r5 /* Is it locked? */
1596: add r4,r4,r8 /* Point to the offset into the PCA area */
1597: li r5,1 /* Get our lock word */
1598: bne- tlbhang /* It's locked, go wait... */
1599:
1600: la r4,PCAhash(r4) /* Point to the start of the hash chain for the PTE we're replacing */
1601:
1602: stwcx. r5,0,r9 /* Try to get it */
1603: bne- tlbhang /* We was beat... */
1604:
1605: mfspr r7,pvr /* Find out what kind of machine we are */
1606: li r5,0 /* Lock clear value */
1607: rlwinm r7,r7,16,16,31 /* Isolate CPU type */
1608:
1609: tlbie r12 /* Invalidate it everywhere */
1610:
1611: cmplwi r7,3 /* Is this a 603? */
1612: stw r5,0(r9) /* Clear the lock */
1613:
1614: beq- its603 /* It's a 603, skip the tlbsync... */
1615:
1616: eieio /* Make sure that the tlbie happens first */
1617: tlbsync /* wait for everyone to catch up */
1618:
1619: its603: sync /* Make sure of it all */
1620:
1621: beq- cr1,slamit /* The old was an autogen, time to slam it in... */
1622:
1623: lwz r9,4(r6) /* Get the real portion of old PTE */
1624: lwz r7,0(r4) /* Get the first element. We can't get to here
1625: if we aren't working with a mapping... */
1626: mr r0,r7 ; Save pointer to first element
1627:
1628: findold: mr r1,r11 ; Save the previous guy
1629: mr. r11,r7 /* Copy and test the chain */
1630: beq- bebad /* Assume it's not zero... */
1631:
1632: lwz r5,mmPTEv(r11) /* See if this is the old active one */
1633: cmplw cr2,r11,r14 /* Check if this is actually the new one */
1634: cmplw r5,r10 /* Is this us? (Note: valid bit kept off in mappings) */
1635: lwz r7,mmhashnext(r11) /* Get the next one in line */
1636: beq- cr2,findold /* Don't count the new one... */
1637: cmplw cr2,r11,r0 ; Check if we are first on the list
1638: bne+ findold /* Not it (and assume the worst)... */
1639:
1640: lwz r12,mmphysent(r11) /* Get the pointer to the physical entry */
1641: beq- cr2,nomove ; We are first, no need to requeue...
1642:
1643: stw r11,0(r4) ; Chain us to the head
1644: stw r0,mmhashnext(r11) ; Chain the old head to us
1645: stw r7,mmhashnext(r1) ; Unlink us
1646:
1647: nomove: li r5,0 /* Clear this on out */
1648:
1649: mr. r12,r12 /* Is there a physical entry? */
1650: stw r5,mmPTEent(r11) ; Clear the PTE entry pointer
1651: li r5,pepte1 /* Point to the PTE last half */
1652:
1653: bne+ mrgmrc /* Yeah, merge RC into it... */
1654:
1655: stw r9,mmPTEr(r11) ; Squirrel away the whole thing (RC bits are in here)
1656: b slamit /* We've got the old saved... */
1657:
1658:
1659: bebad: lis r0,HIGH_ADDR(Choke) /* We have a kernel choke!!! */
1660: ori r0,r0,LOW_ADDR(Choke)
1661: sc /* Firmware Heimlich maneuver */
1662:
1663: .align 5
1664:
1665: mrgmrc: rlwinm r11,r9,0,23,24 /* Keep only the RC bits */
1666:
1667: lwarx r9,r7,r12 ; ?
1668:
1669: mrgmrcx: lwarx r9,r5,r12 /* Get the master copy */
1670: or r9,r9,r11 /* Merge in latest RC */
1671: stwcx. r9,r5,r12 /* Save it back */
1672: bne- mrgmrcx /* If it changed, try again... */
1673:
1674: /*
1675: * Here's where we finish up. We save the real part of the PTE, eieio it, to make sure it's
1676: * out there before the top half (with the valid bit set).
1677: */
1678:
1679: slamit: stw r2,4(r6) /* Stash the real part */
1680: li r4,0 /* Get a lock clear value */
1681: eieio /* Erect a barricade */
1682: stw r3,0(r6) /* Stash the virtual part and set valid on */
1683:
1684: stw r4,PCAlock(r8) /* Clear the PCA lock */
1685:
1686: li r3,T_IN_VAIN /* Say that we handled it */
1687: sync /* Go no further until the stores complete */
1688: #if PERFTIMES && DEBUG
1689: mflr r11
1690: mr r4,r3
1691: li r3,33
1692: bl EXT(dbgLog2) ; Start of hw_add_map
1693: mr r3,r4
1694: mtlr r11
1695: #endif
1696: blr /* Back to the fold... */
1697:
1698:
1699: /*
1700: * This walks the hash table or DBATs to locate the physical address of a virtual one.
1701: * The space is provided. If it is the kernel space, the DBATs are searched first. Failing
1702: * that, the hash table is accessed. Zero is returned for failure, so it must be special cased.
1703: * This is usually used for debugging, so we try not to rely
1704: * on anything that we don't have to.
1705: */
1706:
1707: ENTRY(LRA, TAG_NO_FRAME_USED)
1708:
1709: mfmsr r10 /* Save the current MSR */
1710: xoris r0,r3,HIGH_ADDR(PPC_SID_KERNEL) /* Clear the top half if equal */
1711: andi. r9,r10,0x7FCF /* Turn off interrupts and translation */
1712: eqv r12,r12,r12 /* Fill the bottom with foxes */
1713: mtmsr r9 /* Cheat and turn off translation without an RFI.
1714: This only works when instructions are in a V=R area. */
1715: cmplwi r0,LOW_ADDR(PPC_SID_KERNEL) /* See if this is kernel space */
1716: rlwinm r11,r3,6,6,25 /* Position the space for the VSID */
1717: isync /* Purge pipe */
1718: bne- notkernsp /* This is not for the kernel... */
1719:
1720: mfspr r5,dbat0u /* Get the virtual address and length */
1721: eqv r8,r8,r8 /* Get all foxes */
1722: rlwinm. r0,r5,0,30,30 /* Check if valid for supervisor state */
1723: rlwinm r7,r5,0,0,14 /* Clean up the base virtual address */
1724: beq- ckbat1 /* not valid, skip this one... */
1725: sub r7,r4,r7 /* Subtract out the base */
1726: rlwimi r8,r5,15,0,14 /* Get area length - 1 */
1727: mfspr r6,dbat0l /* Get the real part */
1728: cmplw r7,r8 /* Check if it is in the range */
1729: bng+ fndbat /* Yup, she's a good un... */
1730:
1731: ckbat1: mfspr r5,dbat1u /* Get the virtual address and length */
1732: eqv r8,r8,r8 /* Get all foxes */
1733: rlwinm. r0,r5,0,30,30 /* Check if valid for supervisor state */
1734: rlwinm r7,r5,0,0,14 /* Clean up the base virtual address */
1735: beq- ckbat2 /* not valid, skip this one... */
1736: sub r7,r4,r7 /* Subtract out the base */
1737: rlwimi r8,r5,15,0,14 /* Get area length - 1 */
1738: mfspr r6,dbat1l /* Get the real part */
1739: cmplw r7,r8 /* Check if it is in the range */
1740: bng+ fndbat /* Yup, she's a good un... */
1741:
1742: ckbat2: mfspr r5,dbat2u /* Get the virtual address and length */
1743: eqv r8,r8,r8 /* Get all foxes */
1744: rlwinm. r0,r5,0,30,30 /* Check if valid for supervisor state */
1745: rlwinm r7,r5,0,0,14 /* Clean up the base virtual address */
1746: beq- ckbat3 /* not valid, skip this one... */
1747: sub r7,r4,r7 /* Subtract out the base */
1748: rlwimi r8,r5,15,0,14 /* Get area length - 1 */
1749: mfspr r6,dbat2l /* Get the real part */
1750: cmplw r7,r8 /* Check if it is in the range */
1751: bng- fndbat /* Yup, she's a good un... */
1752:
1753: ckbat3: mfspr r5,dbat3u /* Get the virtual address and length */
1754: eqv r8,r8,r8 /* Get all foxes */
1755: rlwinm. r0,r5,0,30,30 /* Check if valid for supervisor state */
1756: rlwinm r7,r5,0,0,14 /* Clean up the base virtual address */
1757: beq- notkernsp /* not valid, skip this one... */
1758: sub r7,r4,r7 /* Subtract out the base */
1759: rlwimi r8,r5,15,0,14 /* Get area length - 1 */
1760: mfspr r6,dbat3l /* Get the real part */
1761: cmplw r7,r8 /* Check if it is in the range */
1762: bgt+ notkernsp /* No good... */
1763:
1764: fndbat: rlwinm r6,r6,0,0,14 /* Clean up the real address */
1765: mtmsr r10 /* Restore state */
1766: add r3,r7,r6 /* Relocate the offset to real */
1767: isync /* Purge pipe */
1768: blr /* Bye, bye... */
1769:
1770: notkernsp: mfspr r5,sdr1 /* Get hash table base and size */
1771: rlwimi r11,r4,30,2,5 /* Insert the segment no. to make a VSID */
1772: rlwimi r12,r5,16,0,15 /* Make table size -1 out of mask */
1773: rlwinm r7,r4,26,10,25 /* Isolate the page index */
1774: andc r5,r5,r12 /* Clean up the hash table */
1775: xor r7,r7,r11 /* Get primary hash */
1776: rlwinm r11,r11,1,1,24 /* Position VSID for pte ID */
1777: and r7,r7,r12 /* Wrap the hash */
1778: rlwimi r11,r4,10,26,31 /* Move API into pte ID */
1779: add r5,r7,r5 /* Point to the PTEG */
1780: oris r11,r11,0x8000 /* Slam on valid bit so's we don't match an invalid one */
1781:
1782: li r9,8 /* Get the number of PTEs to check */
1783: lwz r6,0(r5) /* Preload the virtual half */
1784:
1785: fndpte: subi r9,r9,1 /* Count the pte */
1786: lwz r3,4(r5) /* Get the real half */
1787: cmplw cr1,r6,r11 /* Is this what we want? */
1788: lwz r6,8(r5) /* Start to get the next virtual half */
1789: mr. r9,r9 /* Any more to try? */
1790: addi r5,r5,8 /* Bump to next slot */
1791: beq cr1,gotxlate /* We found what we were looking for... */
1792: bne+ fndpte /* Go try the next PTE... */
1793:
1794: mtmsr r10 /* Restore state */
1795: li r3,0 /* Show failure */
1796: isync /* Purge pipe */
1797: blr /* Leave... */
1798:
1799: gotxlate: mtmsr r10 /* Restore state */
1800: rlwimi r3,r4,0,20,31 /* Cram in the page displacement */
1801: isync /* Purge pipe */
1802: blr /* Return... */
1803:
1804:
1805:
1806: /*
1807: * hw_set_user_space(space) - Indicate whether memory space needs to be switched.
1808: * We really need to turn off interrupts here, because we need to be non-preemptable
1809: */
1810:
1811:
1812: .align 5
1813: .globl EXT(hw_set_user_space)
1814:
1815: LEXT(hw_set_user_space)
1816:
1817: mfmsr r10 /* Get the current MSR */
1818: rlwinm r9,r10,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Turn off 'rupts */
1819: mtmsr r9 /* Disable 'em */
1820: mfsprg r6,0 /* Get the per_proc_info address */
1821: stw r3,PP_USERSPACE(r6) /* Show our new address space */
1822: mtmsr r10 /* Restore interruptions */
1823: blr /* Return... */
1824:
1825:
1826: /* struct mapping *hw_cpv(struct mapping *mp) - Converts a physcial mapping CB address to virtual
1827: *
1828: */
1829:
1830: .align 5
1831: .globl EXT(hw_cpv)
1832:
1833: LEXT(hw_cpv)
1834:
1835: mfmsr r10 ; Get the current MSR
1836: rlwinm r4,r3,0,0,19 ; Round back to the mapping block allocation control block
1837: andi. r9,r10,0x7FEF ; Turn off interrupts and data translation
1838: mtmsr r9 ; Disable DR and EE
1839: isync
1840:
1841: lwz r4,mbvrswap(r4) ; Get the conversion value
1842: mtmsr r10 ; Interrupts and DR back on
1843: isync
1844: xor r3,r3,r4 ; Convert to physical
1845: rlwinm r3,r3,0,0,26 ; Clean out any flags
1846: blr
1847:
1848:
1849: /* struct mapping *hw_cvp(struct mapping *mp) - Converts a virtual mapping CB address to physcial
1850: *
1851: * Translation must be on for this
1852: *
1853: */
1854:
1855: .align 5
1856: .globl EXT(hw_cvp)
1857:
1858: LEXT(hw_cvp)
1859:
1860: rlwinm r4,r3,0,0,19 ; Round back to the mapping block allocation control block
1861: rlwinm r3,r3,0,0,26 ; Clean out any flags
1862: lwz r4,mbvrswap(r4) ; Get the conversion value
1863: xor r3,r3,r4 ; Convert to virtual
1864: blr
1865:
1866:
1867: /* int mapalc(struct mappingblok *mb) - Finds, allocates, and checks a free mapping entry in a block
1868: *
1869: * Lock must already be held on mapping block list
1870: * returns 0 if all slots filled.
1871: * returns n if a slot is found and it is not the last
1872: * returns -n if a slot os found and it is the last
1873: * when n and -n are returned, the corresponding bit is cleared
1874: *
1875: */
1876:
1877: .align 5
1878: .globl EXT(mapalc)
1879:
1880: LEXT(mapalc)
1881:
1882: lwz r4,mbfree(r3) ; Get the first mask
1883: lis r0,0x8000 ; Get the mask to clear the first free bit
1884: lwz r5,mbfree+4(r3) ; Get the second mask
1885: mr r12,r3 ; Save the return
1886: cntlzw r8,r4 ; Get first free field
1887: lwz r6,mbfree+8(r3) ; Get the third mask
1888: srw. r9,r0,r8 ; Get bit corresponding to first free one
1889: lwz r7,mbfree+12(r3) ; Get the fourth mask
1890: cntlzw r10,r5 ; Get first free field in second word
1891: andc r4,r4,r9 ; Turn it off
1892: bne malcfnd0 ; Found one...
1893:
1894: srw. r9,r0,r10 ; Get bit corresponding to first free one in second word
1895: cntlzw r11,r6 ; Get first free field in third word
1896: andc r5,r5,r9 ; Turn it off
1897: bne malcfnd1 ; Found one...
1898:
1899: srw. r9,r0,r11 ; Get bit corresponding to first free one in third word
1900: cntlzw r10,r7 ; Get first free field in fourth word
1901: andc r6,r6,r9 ; Turn it off
1902: bne malcfnd2 ; Found one...
1903:
1904: srw. r9,r0,r10 ; Get bit corresponding to first free one in second word
1905: li r3,0 ; Assume abject failure
1906: andc r7,r7,r9 ; Turn it off
1907: beqlr ; There are none any left...
1908:
1909: addi r3,r10,96 ; Set the correct bit number
1910: stw r7,mbfree+12(r12) ; Actually allocate the slot
1911:
1912: mapafin: or r4,r4,r5 ; Merge the first two allocation maps
1913: or r6,r6,r7 ; Then the last two
1914: or. r4,r4,r6 ; Merge both halves
1915: bnelr+ ; Return if some left for next time...
1916:
1917: neg r3,r3 ; Indicate we just allocated the last one
1918: blr ; Leave...
1919:
1920: malcfnd0: stw r4,mbfree(r12) ; Actually allocate the slot
1921: mr r3,r8 ; Set the correct bit number
1922: b mapafin ; Exit now...
1923:
1924: malcfnd1: stw r5,mbfree+4(r12) ; Actually allocate the slot
1925: addi r3,r10,32 ; Set the correct bit number
1926: b mapafin ; Exit now...
1927:
1928: malcfnd2: stw r6,mbfree+8(r12) ; Actually allocate the slot
1929: addi r3,r11,64 ; Set the correct bit number
1930: b mapafin ; Exit now...
1931:
1932:
1933:
1934: /*
1935: * Log out all memory usage
1936: */
1937:
1938: .align 5
1939: .globl EXT(logmem)
1940:
1941: LEXT(logmem)
1942:
1943: mfmsr r2 ; Get the MSR
1944: lis r10,hi16(EXT(DebugWork)) ; High part of area
1945: lis r12,hi16(EXT(mem_actual)) ; High part of actual
1946: andi. r0,r10,0x7FCF ; Interrupts and translation off
1947: ori r10,r10,lo16(EXT(DebugWork)) ; Get the entry
1948: mtmsr r0 ; Turn stuff off
1949: ori r12,r12,lo16(EXT(mem_actual)) ; Get the actual
1950: li r0,1 ; Get a one
1951:
1952: isync
1953:
1954: stw r0,4(r10) ; Force logging off
1955: lwz r0,0(r12) ; Get the end of memory
1956:
1957: lis r12,hi16(EXT(mem_size)) ; High part of defined memory
1958: ori r12,r12,lo16(EXT(mem_size)) ; Low part of defined memory
1959: lwz r12,0(r12) ; Make it end of defined
1960:
1961: cmplw r0,r12 ; Is there room for the data?
1962: ble- logmemexit ; No, do not even try...
1963:
1964: stw r12,0(r12) ; Set defined memory size
1965: stw r0,4(r12) ; Set the actual amount of memory
1966:
1967: lis r3,hi16(EXT(hash_table_base)) ; Hash table address
1968: lis r4,hi16(EXT(hash_table_size)) ; Hash table size
1969: lis r5,hi16(EXT(pmap_mem_regions)) ; Memory regions
1970: lis r6,hi16(EXT(mapCtl)) ; Mappings
1971: ori r3,r3,lo16(EXT(hash_table_base))
1972: ori r4,r4,lo16(EXT(hash_table_size))
1973: ori r5,r5,lo16(EXT(pmap_mem_regions))
1974: ori r6,r6,lo16(EXT(mapCtl))
1975: lwz r3,0(r3)
1976: lwz r4,0(r4)
1977: lwz r5,4(r5) ; Get the pointer to the phys_ent table
1978: lwz r6,0(r6) ; Get the pointer to the current mapping block
1979: stw r3,8(r12) ; Save the hash table address
1980: stw r4,12(r12) ; Save the hash table size
1981: stw r5,16(r12) ; Save the physent pointer
1982: stw r6,20(r12) ; Save the mappings
1983:
1984: addi r11,r12,0x1000 ; Point to area to move hash table and PCA
1985:
1986: add r4,r4,r4 ; Double size for both
1987:
1988: copyhash: lwz r7,0(r3) ; Copy both of them
1989: lwz r8,4(r3)
1990: lwz r9,8(r3)
1991: lwz r10,12(r3)
1992: subic. r4,r4,0x10
1993: addi r3,r3,0x10
1994: stw r7,0(r11)
1995: stw r8,4(r11)
1996: stw r9,8(r11)
1997: stw r10,12(r11)
1998: addi r11,r11,0x10
1999: bgt+ copyhash
2000:
2001: rlwinm r4,r12,20,12,31 ; Get number of phys_ents
2002:
2003: copyphys: lwz r7,0(r5) ; Copy physents
2004: lwz r8,4(r5)
2005: subic. r4,r4,1
2006: addi r5,r5,8
2007: stw r7,0(r11)
2008: stw r8,4(r11)
2009: addi r11,r11,8
2010: bgt+ copyphys
2011:
2012: addi r11,r11,4095 ; Round up to next page
2013: rlwinm r11,r11,0,0,19
2014:
2015: lwz r4,4(r6) ; Get the size of the mapping area
2016:
2017: copymaps: lwz r7,0(r6) ; Copy the mappings
2018: lwz r8,4(r6)
2019: lwz r9,8(r6)
2020: lwz r10,12(r6)
2021: subic. r4,r4,0x10
2022: addi r6,r6,0x10
2023: stw r7,0(r11)
2024: stw r8,4(r11)
2025: stw r9,8(r11)
2026: stw r10,12(r11)
2027: addi r11,r11,0x10
2028: bgt+ copymaps
2029:
2030: sub r11,r11,r12 ; Get the total length we saved
2031: stw r11,24(r12) ; Save the size
2032:
2033: logmemexit: mtmsr r2 ; Back to normal
2034: li r3,0
2035: isync
2036: blr
2037:
2038:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.