]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ppc/hw_vm.s
xnu-1486.2.11.tar.gz
[apple/xnu.git] / osfmk / ppc / hw_vm.s
index 2bb659aae5830896d675d9f7d95d2ec9e10eafc5..bcad7dad23da773ce954b84097d4ab2e1edb8e52 100644 (file)
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 #include <assym.s>
 #include <debug.h>
-#include <cpus.h>
 #include <db_machine_commands.h>
 #include <mach_rt.h>
        
 #include <ppc/exception.h>
 #include <ppc/Performance.h>
 #include <ppc/exception.h>
-#include <ppc/pmap_internals.h>
 #include <mach/ppc/vm_param.h>
-#define PERFTIMES 0
        
                        .text
 
-/*
- *
- *                     Random notes and musings...
- *
- *                     Access to mappings via the PTEG hash must be done with the list locked.
- *                     Access via the physical entries is controlled by the physent lock.
- *                     Access to mappings is controlled by the PTEG lock once they are queued.
- *                     If they are not on the list, they don't really exist, so
- *                     only one processor at a time can find them, so no access control is needed. 
- *
- *                     The second half of the PTE is kept in the physical entry.  It is done this
- *                     way, because there may be multiple mappings that refer to the same physical
- *                     page (i.e., address aliases or synonymns).  We must do it this way, because
- *                     maintenance of the reference and change bits becomes nightmarish if each mapping
- *                     has its own. One side effect of this, and not necessarily a bad one, is that
- *                     all mappings for a single page can have a single WIMG, protection state, and RC bits.
- *                     The only "bad" thing, is the reference bit.  With a single copy, we can not get
- *                     a completely accurate working set calculation, i.e., we can't tell which mapping was
- *                     used to reference the page, all we can tell is that the physical page was 
- *                     referenced.
- *
- *                     The master copys of the reference and change bits are kept in the phys_entry.
- *                     Other than the reference and change bits, changes to the phys_entry are not
- *                     allowed if it has any mappings.  The master reference and change bits must be
- *                     changed via atomic update.
- *
- *                     Invalidating a PTE merges the RC bits into the phys_entry.
- *
- *                     Before checking the reference and/or bits, ALL mappings to the physical page are
- *                     invalidated.
- *                     
- *                     PTEs are never explicitly validated, they are always faulted in.  They are also
- *                     not visible outside of the hw_vm modules.  Complete seperation of church and state.
- *
- *                     Removal of a mapping is invalidates its PTE.
- *
- *                     So, how do we deal with mappings to I/O space? We don't have a physent for it.
- *                     Within the mapping is a copy of the second half of the PTE.  This is used
- *                     ONLY when there is no physical entry.  It is swapped into the PTE whenever
- *                     it is built.  There is no need to swap it back out, because RC is not
- *                     maintained for these mappings.
- *
- *                     So, I'm starting to get concerned about the number of lwarx/stcwx loops in
- *                     this.  Satisfying a mapped address with no stealing requires one lock.  If we 
- *                     steal an entry, there's two locks and an atomic update.  Invalidation of an entry
- *                     takes one lock and, if there is a PTE, another lock and an atomic update.  Other 
- *                     operations are multiples (per mapping) of the above.  Maybe we should look for
- *                     an alternative.  So far, I haven't found one, but I haven't looked hard.
- */
+;
+;                                     0        0        1        2        3        4        4        5      6
+;                                     0        8        6        4        2        0        8        6      3 
+;                                    +--------+--------+--------+--------+--------+--------+--------+--------+
+;                                    |00000000|00000SSS|SSSSSSSS|SSSSSSSS|SSSSPPPP|PPPPPPPP|PPPPxxxx|xxxxxxxx|          - EA
+;                                    +--------+--------+--------+--------+--------+--------+--------+--------+
+;
+;                                                       0        0        1
+;                                                       0        8        6      
+;                                                      +--------+--------+--------+
+;                                                      |//////BB|BBBBBBBB|BBBB////|                                     - SID - base
+;                                                      +--------+--------+--------+
+;
+;                                     0        0        1
+;                                     0        8        6      
+;                                    +--------+--------+--------+
+;                                    |////////|11111111|111111//|                                                       - SID - copy 1
+;                                    +--------+--------+--------+
+;
+;                   0        0        1
+;                   0        8        6      
+;                  +--------+--------+--------+
+;                  |////////|//222222|22222222|                                                                         - SID - copy 2
+;                  +--------+--------+--------+
+;
+;          0        0        1
+;          0        8        6      
+;         +--------+--------+--------+
+;         |//////33|33333333|33//////|                                                                                  - SID - copy 3 - not needed
+;         +--------+--------+--------+                                                                                         for 65 bit VPN
+;
+;                   0        0        1        2        3        4        4  5   5  
+;                   0        8        6        4        2        0        8  1   5  
+;                  +--------+--------+--------+--------+--------+--------+--------+
+;                  |00000000|00000002|22222222|11111111|111111BB|BBBBBBBB|BBBB////|                                     - SID Hash - this is all
+;                  +--------+--------+--------+--------+--------+--------+--------+                                           SID copies ORed
+;                   0        0        1        2        3        4        4  5   5  
+;                   0        8        6        4        2        0        8  1   5  
+;                  +--------+--------+--------+--------+--------+--------+--------+
+;                  |00000000|0000000S|SSSSSSSS|SSSSSSSS|SSSSSS00|00000000|0000////|                                      - Shifted high order EA
+;                  +--------+--------+--------+--------+--------+--------+--------+                                           left shifted "segment"
+;                                                                                                                             part of EA to make
+;                                                                                                                             room for SID base
+;
+;
+;                   0        0        1        2        3        4        4  5   5  
+;                   0        8        6        4        2        0        8  1   5  
+;                  +--------+--------+--------+--------+--------+--------+--------+
+;                  |00000000|0000000V|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVV////|                                     - VSID - SID Hash XORed
+;                  +--------+--------+--------+--------+--------+--------+--------+                                            with shifted EA
+;
+;                   0        0        1        2        3        4        4        5        6        7      7
+;                   0        8        6        4        2        0        8        6        4        2      9
+;                  +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
+;                  |00000000|0000000V|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVVPPPP|PPPPPPPP|PPPPxxxx|xxxxxxxx|          - VPN
+;                  +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
+;
 
 
-/*                     hw_add_map(struct mapping *mp, space_t space, vm_offset_t va) - Adds a mapping
+/*                     addr64_t hw_add_map(struct pmap *pmap, struct mapping *mp) - Adds a mapping
  *
- *                     Adds a mapping to the PTEG hash list.
+ *                     Maps a page or block into a pmap
  *
- *                     Interrupts must be disabled before calling.
- *
- *                     Using the space and the virtual address, we hash into the hash table
- *                     and get a lock on the PTEG hash chain.  Then we chain the 
- *                     mapping to the front of the list.
+ *                     Returns 0 if add worked or the vaddr of the first overlap if not
  *
+ * Make mapping - not block or I/O - note: this is low-level, upper should remove duplicates
+ *  
+ *  1) bump mapping busy count
+ *  2) lock pmap share
+ *  3) find mapping full path - finds all possible list previous elements
+ *  4) upgrade pmap to exclusive
+ *  5) add mapping to search list
+ *  6) find physent
+ *  7) lock physent
+ *  8) add to physent
+ *  9) unlock physent
+ * 10) unlock pmap
+ * 11) drop mapping busy count
+ * 
+ * 
+ * Make mapping - block or I/O - note: this is low-level, upper should remove duplicates
+ *  
+ *  1) bump mapping busy count
+ *  2) lock pmap share
+ *  3) find mapping full path - finds all possible list previous elements
+ *  4) upgrade pmap to exclusive
+ *  5) add mapping to search list
+ *  6) unlock pmap
+ *  7) drop mapping busy count
+ * 
  */
 
                        .align  5
                        .globl  EXT(hw_add_map)
 
 LEXT(hw_add_map)
-
-#if PERFTIMES && DEBUG
-                       mr              r7,r3
-                       mflr    r11
-                       li              r3,20
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r7
-                       mtlr    r11
+                       
+                       stwu    r1,-(FM_ALIGN((31-17+1)*4)+FM_SIZE)(r1) ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r17,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r18,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r19,FM_ARG0+0x08(r1)            ; Save a register
+                       mfsprg  r19,2                                           ; Get feature flags 
+                       stw             r20,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r21,FM_ARG0+0x10(r1)            ; Save a register
+                       mtcrf   0x02,r19                                        ; move pf64Bit cr6
+                       stw             r22,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r23,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r24,FM_ARG0+0x1C(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x20(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x24(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x28(r1)            ; Save a register
+                       stw             r28,FM_ARG0+0x2C(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x30(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x34(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x38(r1)            ; Save a register
+                       stw             r0,(FM_ALIGN((31-17+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+
+#if DEBUG
+                       lwz             r11,pmapFlags(r3)                       ; Get pmaps flags
+                       rlwinm. r11,r11,0,pmapVMgsaa            ; Is guest shadow assist active?
+                       bne             hamPanic                                        ; Call not valid for guest shadow assist pmap
 #endif
+                       
+                       rlwinm  r11,r4,0,0,19                           ; Round down to get mapping block address
+                       mr              r28,r3                                          ; Save the pmap
+                       mr              r31,r4                                          ; Save the mapping
+                       bt++    pf64Bitb,hamSF1                         ; skip if 64-bit (only they take the hint)
+                       lwz             r20,pmapvr+4(r3)                        ; Get conversion mask for pmap
+                       lwz             r21,mbvrswap+4(r11)                     ; Get conversion mask for mapping
 
-                       mfmsr   r0                                                      /* Get the MSR */
-                       eqv             r6,r6,r6                                        /* Fill the bottom with foxes */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r11,r4,6,6,25                           /* Position the space for the VSID */
-                       mfspr   r10,sdr1                                        /* Get hash table base and size */
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwimi  r11,r5,30,2,5                           /* Insert the segment no. to make a VSID */
-                       mfsprg  r12,2                                           ; Get feature flags
-                       rlwimi  r6,r10,16,0,15                          /* Make table size -1 out of mask */
-                       rlwinm  r7,r5,26,10,25                          /* Isolate the page index */
-                       or              r8,r10,r6                                       /* Point to the last byte in table */
-                       rlwinm  r9,r5,4,0,3                                     ; Move nybble 1 up to 0
-                       xor             r7,r7,r11                                       /* Get primary hash */
-                       mtcrf   0x04,r12                                        ; Set the features                      
-                       andi.   r12,r0,0x7FCF                           /* Disable translation and interruptions */
-                       rlwinm  r11,r11,1,1,24                          /* Position VSID for pte ID */
-                       addi    r8,r8,1                                         /* Point to the PTEG Control Area */
-                       xor             r9,r9,r5                                        ; Splooch vaddr nybble 0 and 1 together
-                       and             r7,r7,r6                                        /* Wrap the hash */
-                       rlwimi  r11,r5,10,26,31                         /* Move API into pte ID */
-                       rlwinm  r9,r9,6,27,29                           ; Get splooched bits in place
-                       add             r8,r8,r7                                        /* Point to our PCA entry */
-                       rlwinm  r10,r4,2,27,29                          ; Get low 3 bits of the VSID for look-aside hash
-                       
-                       bt              pfNoMSRirb,hamNoMSR                     ; No MSR...
-
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hamNoMSRx
+                       b               hamSF1x                                         ; Done...
                        
-hamNoMSR:      mr              r4,r0                                           ; Save R0
-                       mr              r2,r3                                           ; Save
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r0,r4                                           ; Restore
-                       mr              r3,r2                                           ; Restore
-hamNoMSRx:
+hamSF1:                ld              r20,pmapvr(r3)                          ; Get conversion mask for pmap
+                       ld              r21,mbvrswap(r11)                       ; Get conversion mask for mapping
 
-                       la              r4,PCAhash(r8)                          /* Point to the mapping hash area */
-                       xor             r9,r9,r10                                       ; Finish splooching nybble 0, 1, and the low bits of the VSID
-                       isync                                                           /* Get rid of anything prefetched before we ref storage */
-/*
- *                     We've now got the address of our PCA, the hash chain anchor, our API subhash,
- *                     and word 0 of the PTE (the virtual part). 
- *
- *                     Now, we just lock the PCA.              
- */
+hamSF1x:       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
                        
-                       li              r12,1                                           /* Get the locked value */
-                       dcbt    0,r4                                            /* We'll need the hash area in a sec, so get it */
-                       add             r4,r4,r9                                        /* Point to the right mapping hash slot */
-                       
-ptegLckx:      lwarx   r10,0,r8                                        /* Get the PTEG lock */
-                       mr.             r10,r10                                         /* Is it locked? */
-                       bne-    ptegLckwx                                       /* Yeah... */
-                       stwcx.  r12,0,r8                                        /* Take take it */
-                       bne-    ptegLckx                                        /* Someone else was trying, try again... */
-                       b               ptegSXgx                                        /* All done... */
-
-                       .align  4
-                       
-ptegLckwx:     mr.             r10,r10                                         /* Check if it's already held */
-                       beq+    ptegLckx                                        /* It's clear... */
-                       lwz             r10,0(r8)                                       /* Get lock word again... */
-                       b               ptegLckwx                                       /* Wait... */
-                       
-                       .align  4
-                       
-ptegSXgx:      isync                                                           /* Make sure we haven't used anything yet */
-
-                       lwz             r7,0(r4)                                        /* Pick up the anchor of hash list */
-                       stw             r3,0(r4)                                        /* Save the new head */
-                       stw             r7,mmhashnext(r3)                       /* Chain in the old head */
-                       
-                       stw             r4,mmPTEhash(r3)                        /* Point to the head of the hash list */
-                       
-                       sync                                                            /* Make sure the chain is updated */
-                       stw             r10,0(r8)                                       /* Unlock the hash list */
-                       mtmsr   r0                                                      /* Restore translation and interruptions */
-                       isync                                                           /* Toss anything done with DAT off */
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,21
-                       bl              EXT(dbgLog2)                            ; end of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Leave... */
+                       mr              r17,r11                                         ; Save the MSR
+                       xor             r28,r28,r20                                     ; Convert the pmap to physical addressing
+                       xor             r31,r31,r21                                     ; Convert the mapping to physical addressing
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       lwz             r24,mpFlags(r31)                        ; Pick up the flags
+                       bne--   hamBadLock                                      ; Nope...
 
+                       li              r21,0                                           ; Remember that we have the shared lock
+                       
+;
+;                      Note that we do a full search (i.e., no shortcut level skips, etc.)
+;                      here so that we will know the previous elements so we can dequeue them
+;                      later.
+;
 
-/*                     mp=hw_lock_phys_vir(space, va) - Finds and locks a physical entry by vaddr.
- *
- *                     Returns the mapping with the associated physent locked if found, or a
- *                     zero and no lock if not.  It we timed out trying to get a the lock on
- *                     the physical entry, we retun a 1.  A physical entry can never be on an
- *                     odd boundary, so we can distinguish between a mapping and a timeout code.
- *
- *                     Interrupts must be disabled before calling.
- *
- *                     Using the space and the virtual address, we hash into the hash table
- *                     and get a lock on the PTEG hash chain.  Then we search the chain for the
- *                     mapping for our virtual address.  From there, we extract the pointer to
- *                     the physical entry.
- *
- *                     Next comes a bit of monkey business.  we need to get a lock on the physical
- *                     entry.  But, according to our rules, we can't get it after we've gotten the
- *                     PTEG hash lock, we could deadlock if we do.  So, we need to release the
- *                     hash lock.  The problem is, though, that as soon as we release it, some 
- *                     other yahoo may remove our mapping between the time that we release the
- *                     hash lock and obtain the phys entry lock.  So, we can't count on the 
- *                     mapping once we release the lock.  Instead, after we lock the phys entry,
- *                     we search the mapping list (phys_link) for our translation.  If we don't find it,
- *                     we unlock the phys entry, bail out, and return a 0 for the mapping address.  If we 
- *                     did find it, we keep the lock and return the address of the mapping block.
- *
- *                     What happens when a mapping is found, but there is no physical entry?
- *                     This is what happens when there is I/O area mapped.  It one of these mappings
- *                     is found, the mapping is returned, as is usual for this call, but we don't
- *                     try to lock anything.  There could possibly be some problems here if another
- *                     processor releases the mapping while we still alre using it.  Hope this 
- *                     ain't gonna happen.
- *
- *                     Taaa-dahhh!  Easy as pie, huh?
- *
- *                     So, we have a few hacks hacks for running translate off in here. 
- *                     First, when we call the lock routine, we have carnel knowlege of the registers is uses. 
- *                     That way, we don't need a stack frame, which we can't have 'cause the stack is in
- *                     virtual storage.  But wait, as if that's not enough...  We need one more register.  So, 
- *                     we cram the LR into the CTR and return from there.
- *
- */
+hamRescan:     lwz             r4,mpVAddr(r31)                         ; Get the new vaddr top half
+                       lwz             r5,mpVAddr+4(r31)                       ; Get the new vaddr bottom half
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       lhz             r23,mpBSize(r31)                        ; Get the block size for later
+                       mr              r29,r4                                          ; Save top half of vaddr for later
+                       mr              r30,r5                                          ; Save bottom half of vaddr for later
+                       
+                       bl              EXT(mapSearchFull)                      ; Go see if we can find it
+                       
+                       li              r22,lo16(0x800C)                        ; Get 0xFFFF800C
+                       rlwinm  r0,r24,mpBSub+1,31,31           ; Rotate to get 0 if 4K bsu or 1 if 32MB bsu
+                       addi    r23,r23,1                                       ; Get actual length
+                       rlwnm   r22,r22,r0,27,31                        ; Rotate to get 12 or 25
+                       lis             r0,0x8000                                       ; Get 0xFFFFFFFF80000000
+                       slw             r9,r23,r22                                      ; Isolate the low part
+                       rlwnm   r22,r23,r22,22,31                       ; Extract the high order
+                       addic   r23,r9,-4096                            ; Get the length to the last page
+                       add             r0,r0,r0                                        ; Get 0xFFFFFFFF00000000 for 64-bit or 0 for 32-bit
+                       addme   r22,r22                                         ; Do high order as well...
+                       mr.             r3,r3                                           ; Did we find a mapping here?
+                       or              r0,r30,r0                                       ; Fill high word of 64-bit with 1s so we will properly carry
+                       bne--   hamOverlay                                      ; We found a mapping, this is no good, can not double map...
+
+                       addc    r9,r0,r23                                       ; Add size to get last page in new range
+                       or.             r0,r4,r5                                        ; Are we beyond the end?
+                       adde    r8,r29,r22                                      ; Add the rest of the length on
+                       rlwinm  r9,r9,0,0,31                            ; Clean top half of sum
+                       beq++   hamFits                                         ; We are at the end...
+
+                       cmplw   cr1,r9,r5                                       ; Is the bottom part of our end less?
+                       cmplw   r8,r4                                           ; Is our end before the next (top part)
+                       crand   cr0_eq,cr0_eq,cr1_lt            ; Is the second half less and the first half equal?
+                       cror    cr0_eq,cr0_eq,cr0_lt            ; Or is the top half less
+                       
+                       bf--    cr0_eq,hamOverlay                       ; No, we do fit, there is an overlay...
+                       
+;
+;                      Here we try to convert to an exclusive lock.  This will fail if someone else
+;                      has it shared.
+;
+hamFits:       mr.             r21,r21                                         ; Do we already have the exclusive lock?                        
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       
+                       bne--   hamGotX                                         ; We already have the exclusive...
+                       
+                       bl              sxlkPromote                                     ; Try to promote shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       beq++   hamGotX                                         ; Yeah...
+                       
+;
+;                      Since we could not promote our lock, we need to convert to it.
+;                      That means that we drop the shared lock and wait to get it
+;                      exclusive.  Since we release the lock, we need to do the look up
+;                      again.
+;                      
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkConvert                                     ; Convert shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       bne--   hamBadLock                                      ; Nope, we must have timed out...
+                       
+                       li              r21,1                                           ; Remember that we have the exclusive lock
+                       b               hamRescan                                       ; Go look again...
+                       
                        .align  5
-                       .globl  EXT(hw_lock_phys_vir)
 
-LEXT(hw_lock_phys_vir)
+hamGotX:       mr              r3,r28                                          ; Get the pmap to insert into
+                       mr              r4,r31                                          ; Point to the mapping
+                       bl              EXT(mapInsert)                          ; Insert the mapping into the list
+
+                       rlwinm  r11,r24,mpPcfgb+2,mpPcfg>>6     ; Get the index into the page config table
+                       lhz             r8,mpSpace(r31)                         ; Get the address space
+                       lwz             r11,lgpPcfg(r11)                        ; Get the page config
+                       mfsdr1  r7                                                      ; Get the hash table base/bounds
+
+                       lwz             r4,pmapResidentCnt(r28)         ; Get the mapped page count 
+                       lwz     r12,pmapResidentMax(r28)                ; r12 = pmap->stats.resident_max
+                       addi    r4,r4,1                                         ; Bump up the mapped page count
+                       stw             r4,pmapResidentCnt(r28)         ; Set the mapped page count
+                       cmplw   r12,r4                                  ; if pmap->stats.resident_max >= pmap->stats.resident_count
+                       bge+    hamSkipMax                              ;       goto hamSkipResMax
+                       stw     r4,pmapResidentMax(r28)                 ; pmap->stats.resident_max = pmap->stats.resident_count
+                       
+hamSkipMax:            andi.   r0,r24,mpType                           ; Is this a normal mapping?
+
+                       rlwimi  r8,r8,14,4,17                           ; Double address space
+                       rlwinm  r9,r30,0,4,31                           ; Clear segment
+                       rlwinm  r10,r30,18,14,17                        ; Shift EA[32:35] down to correct spot in VSID (actually shift up 14)
+                       rlwimi  r8,r8,28,0,3                            ; Get the last nybble of the hash
+                       rlwimi  r10,r29,18,0,13                         ; Shift EA[18:31] down to VSID (31-bit math works because of max hash table size)                       
+                       rlwinm  r7,r7,0,16,31                           ; Isolate length mask (or count)
+                       srw             r9,r9,r11                                       ; Isolate just the page index
+                       xor             r10,r10,r8                                      ; Calculate the low 32 bits of the VSID
+
+                       xor             r9,r9,r10                                       ; Get the hash to the PTEG
+                       
+                       bne--   hamDoneNP                                       ; Not a normal mapping, therefore, no physent...
+                       
+                       bl              mapPhysFindLock                         ; Go find and lock the physent
+                       
+                       bt++    pf64Bitb,ham64                          ; This is 64-bit...
+                       
+                       lwz             r11,ppLink+4(r3)                        ; Get the alias chain pointer
+                       rlwinm  r7,r7,16,0,15                           ; Get the PTEG wrap size
+                       slwi    r9,r9,6                                         ; Make PTEG offset
+                       ori             r7,r7,0xFFC0                            ; Stick in the bottom part
+                       rlwinm  r12,r11,0,~ppFlags                      ; Clean it up
+                       and             r9,r9,r7                                        ; Wrap offset into table
+                       mr              r4,r31                                          ; Set the link to install
+                       stw             r9,mpPte(r31)                           ; Point the mapping at the PTEG (exact offset is invalid)
+                       stw             r12,mpAlias+4(r31)                      ; Move to the mapping
+                       bl              mapPhyCSet32                            ; Install the link
+                       b               hamDone                                         ; Go finish up...
+                       
+                       .align  5
+                       
+ham64:         li              r0,ppLFAmask                            ; Get mask to clean up alias pointer
+                       subfic  r7,r7,46                                        ; Get number of leading zeros
+                       eqv             r4,r4,r4                                        ; Get all ones
+                       ld              r11,ppLink(r3)                          ; Get the alias chain pointer
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       srd             r4,r4,r7                                        ; Get the wrap mask
+                       sldi    r9,r9,7                                         ; Change hash to PTEG offset
+                       andc    r11,r11,r0                                      ; Clean out the lock and flags
+                       and             r9,r9,r4                                        ; Wrap to PTEG
+                       mr              r4,r31
+                       stw             r9,mpPte(r31)                           ; Point the mapping at the PTEG (exact offset is invalid)
+                       std             r11,mpAlias(r31)                        ; Set the alias pointer in the mapping
+
+                       bl              mapPhyCSet64                            ; Install the link
+                                               
+hamDone:       bl              mapPhysUnlock                           ; Unlock the physent chain
 
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r5,r3
-                       li              r3,22
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r5
-                       mtlr    r11
-#endif
-                       mfmsr   r12                                                     /* Get the MSR */
-                       eqv             r6,r6,r6                                        /* Fill the bottom with foxes */
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       rlwinm  r11,r3,6,6,25                           /* Position the space for the VSID */
-                       rlwinm  r12,r12,0,MSR_FP_BIT+1,MSR_FP_BIT-1     ; Force floating point off
-                       mfspr   r5,sdr1                                         /* Get hash table base and size */
-                       rlwimi  r11,r4,30,2,5                           /* Insert the segment no. to make a VSID */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       rlwinm  r12,r12,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1   ; Force vectors off
-                       rlwimi  r6,r5,16,0,15                           /* Make table size -1 out of mask */
-                       andi.   r0,r12,0x7FCF                           /* Disable translation and interruptions */
-                       rlwinm  r9,r4,4,0,3                                     ; Move nybble 1 up to 0
-                       rlwinm  r7,r4,26,10,25                          /* Isolate the page index */
-                       or              r8,r5,r6                                        /* Point to the last byte in table */
-                       xor             r7,r7,r11                                       /* Get primary hash */
-                       rlwinm  r11,r11,1,1,24                          /* Position VSID for pte ID */
-                       addi    r8,r8,1                                         /* Point to the PTEG Control Area */
-                       xor             r9,r9,r4                                        ; Splooch vaddr nybble 0 and 1 together
-                       and             r7,r7,r6                                        /* Wrap the hash */
-                       rlwimi  r11,r4,10,26,31                         /* Move API into pte ID */
-                       rlwinm  r9,r9,6,27,29                           ; Get splooched bits in place
-                       add             r8,r8,r7                                        /* Point to our PCA entry */
-                       rlwinm  r10,r3,2,27,29                          ; Get low 3 bits of the VSID for look-aside hash
-
-                       bt              pfNoMSRirb,hlpNoMSR                     ; No MSR...
+hamDoneNP:     la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
 
-                       mtmsr   r0                                                      ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hlpNoMSRx
+                       mr              r3,r31                                          ; Get the mapping pointer
+                       bl              mapDropBusy                                     ; Drop the busy count
                        
-hlpNoMSR:      mr              r3,r0                                           ; Get the new MSR
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       sc                                                                      ; Set it
-hlpNoMSRx:
+                       li              r3,0                                            ; Set successful return
+                       li              r4,0                                            ; Set successful return
 
-                       la              r3,PCAhash(r8)                          /* Point to the mapping hash area */
-                       xor             r9,r9,r10                                       ; Finish splooching nybble 0, 1, and the low bits of the VSID
-                       isync                                                           /* Make sure translation is off before we ref storage */
+hamReturn:     bt++    pf64Bitb,hamR64                         ; Yes...
 
-/*
- *                     We've now got the address of our PCA, the hash chain anchor, our API subhash,
- *                     and word 0 of the PTE (the virtual part). 
- *
- *                     Now, we just lock the PCA and find our mapping, if it exists.                           
- */
-                       
-                       dcbt    0,r3                                            /* We'll need the hash area in a sec, so get it */
-                       add             r3,r3,r9                                        /* Point to the right mapping hash slot */
+                       mtmsr   r17                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               hamReturnC                                      ; Join common...
+
+hamR64:                mtmsrd  r17                                                     ; Restore enables/translation/etc.
+                       isync                                                           
                        
-ptegLcka:      lwarx   r10,0,r8                                        /* Get the PTEG lock */
-                       li              r5,1                                            /* Get the locked value */
-                       mr.             r10,r10                                         /* Is it locked? */
-                       bne-    ptegLckwa                                       /* Yeah... */
-                       stwcx.  r5,0,r8                                         /* Take take it */
-                       bne-    ptegLcka                                        /* Someone else was trying, try again... */
-                       b               ptegSXga                                        /* All done... */
+hamReturnC:    lwz             r0,(FM_ALIGN((31-17+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Get the return
+                       lwz             r17,FM_ARG0+0x00(r1)            ; Save a register
+                       lwz             r18,FM_ARG0+0x04(r1)            ; Save a register
+                       lwz             r19,FM_ARG0+0x08(r1)            ; Save a register
+                       lwz             r20,FM_ARG0+0x0C(r1)            ; Save a register
+                       mtlr    r0                                                      ; Restore the return
+                       lwz             r21,FM_ARG0+0x10(r1)            ; Save a register
+                       lwz             r22,FM_ARG0+0x14(r1)            ; Save a register
+                       lwz             r23,FM_ARG0+0x18(r1)            ; Save a register
+                       lwz             r24,FM_ARG0+0x1C(r1)            ; Save a register
+                       lwz             r25,FM_ARG0+0x20(r1)            ; Save a register
+                       lwz             r26,FM_ARG0+0x24(r1)            ; Save a register
+                       lwz             r27,FM_ARG0+0x28(r1)            ; Save a register
+                       lwz             r28,FM_ARG0+0x2C(r1)            ; Save a register
+                       lwz             r29,FM_ARG0+0x30(r1)            ; Save a register
+                       lwz             r30,FM_ARG0+0x34(r1)            ; Save a register
+                       lwz             r31,FM_ARG0+0x38(r1)            ; Save a register
+                       lwz             r1,0(r1)                                        ; Pop the stack
                        
-                       .align  4
+                       blr                                                                     ; Leave...
 
-ptegLckwa:     mr.             r10,r10                                         /* Check if it's already held */
-                       beq+    ptegLcka                                        /* It's clear... */
-                       lwz             r10,0(r8)                                       /* Get lock word again... */
-                       b               ptegLckwa                                       /* Wait... */
                        
-                       .align  4
+                       .align  5
 
-ptegSXga:      isync                                                           /* Make sure we haven't used anything yet */
+hamOverlay:    lwz             r22,mpFlags(r3)                         ; Get the overlay flags
+                       li              r0,mpC|mpR                                      ; Get a mask to turn off RC bits
+                       lwz             r23,mpFlags(r31)                        ; Get the requested flags
+                       lwz             r20,mpVAddr(r3)                         ; Get the overlay address
+                       lwz             r8,mpVAddr(r31)                         ; Get the requested address
+                       lwz             r21,mpVAddr+4(r3)                       ; Get the overlay address
+                       lwz             r9,mpVAddr+4(r31)                       ; Get the requested address
+                       lhz             r10,mpBSize(r3)                         ; Get the overlay length
+                       lhz             r11,mpBSize(r31)                        ; Get the requested length
+                       lwz             r24,mpPAddr(r3)                         ; Get the overlay physical address
+                       lwz             r25,mpPAddr(r31)                        ; Get the requested physical address
+                       andc    r21,r21,r0                                      ; Clear RC bits
+                       andc    r9,r9,r0                                        ; Clear RC bits
 
-                       mflr    r0                                                      /* Get the LR */
-                       lwz             r9,0(r3)                                        /* Pick up the first mapping block */
-                       mtctr   r0                                                      /* Stuff it into the CTR */
-                       
-findmapa:      
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
 
-                       mr.             r3,r9                                           /* Did we hit the end? */
-                       bne+    chkmapa                                         /* Nope... */
-                       
-                       stw             r3,0(r8)                                        /* Unlock the PTEG lock
-                                                                                                  Note: we never saved anything while we 
-                                                                                                  had the lock, so we don't need a sync 
-                                                                                                  before we unlock it */
+                       rlwinm. r0,r22,0,mpRIPb,mpRIPb          ; Are we in the process of removing this one?
+                       mr              r3,r20                                          ; Save the top of the colliding address
+                       rlwinm  r4,r21,0,0,19                           ; Save the bottom of the colliding address
 
-vbail:         mtmsr   r12                                                     /* Restore translation and interruptions */
-                       isync                                                           /* Make sure translation is cool */
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,23
-                       bl              EXT(dbgLog2)                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       bctr                                                            /* Return in abject failure... */
-                       
-                       .align  4
-
-chkmapa:       lwz             r10,mmPTEv(r3)                          /* Pick up our virtual ID */
-                       lwz             r9,mmhashnext(r3)                       /* Pick up next mapping block */
-                       cmplw   r10,r11                                         /* Have we found ourself? */
-                       bne-    findmapa                                        /* Nope, still wandering... */
-                       
-                       lwz             r9,mmphysent(r3)                        /* Get our physical entry pointer */
-                       li              r5,0                                            /* Clear this out */
-                       mr.             r9,r9                                           /* Is there, like, a physical entry? */
-                       stw             r5,0(r8)                                        /* Unlock the PTEG lock
-                                                                                                  Note: we never saved anything while we 
-                                                                                                  had the lock, so we don't need a sync 
-                                                                                                  before we unlock it */
-                                                                                                  
-                       beq-    vbail                                           /* If there is no physical entry, it's time
-                                                                                                  to leave... */
-                                                                                                  
-/*                     Here we want to call hw_lock_bit.  We don't want to use the stack, 'cause it's
- *                     in virtual storage, and we're in real.  So, we've carefully looked at the code
- *                     in hw_lock_bit (and unlock) and cleverly don't use any of the registers that it uses.
- *                     Be very, very aware of how you change this code.  By the way, it uses:
- *                     R0, R6, R7, R8, and R9.  R3, R4, and R5 contain parameters
- *                     Unfortunatly, we need to stash R9 still. So... Since we know we will not be interrupted
- *                     ('cause we turned off interruptions and translation is off) we will use SPRG3...
- */
-                       lwz             r10,mmPTEhash(r3)                       /* Save the head of the hash-alike chain.  We need it to find ourselves later */
-                       lis             r5,HIGH_ADDR(EXT(LockTimeOut))  /* Get address of timeout value */
-                       la              r3,pephyslink(r9)                       /* Point to the lock word */
-                       ori             r5,r5,LOW_ADDR(EXT(LockTimeOut))        /* Get second half of address */
-                       li              r4,PHYS_LOCK                            /* Get the lock bit value */
-                       lwz             r5,0(r5)                                        /* Pick up the timeout value */
-                       mtsprg  3,r9                                            /* Save R9 in SPRG3 */
+                       bne++   hamRemv                                         ; Removing, go say so so we help...
                        
-                       bl              EXT(hw_lock_bit)                        /* Go do the lock */
+                       cmplw   r20,r8                                          ; High part of vaddr the same?
+                       cmplw   cr1,r21,r9                                      ; Low part?
+                       crand   cr5_eq,cr0_eq,cr1_eq            ; Remember if same
                        
-                       mfsprg  r9,3                                            /* Restore pointer to the phys_entry */         
-                       mr.             r3,r3                                           /* Did we timeout? */
-                       lwz             r4,pephyslink(r9)                       /* Pick up first mapping block */               
-                       beq-    penterr                                         /* Bad deal, we timed out... */
-
-                       rlwinm  r4,r4,0,0,26                            ; Clear out the flags from first link
+                       cmplw   r10,r11                                         ; Size the same?
+                       cmplw   cr1,r24,r25                                     ; Physical address?
+                       crand   cr5_eq,cr5_eq,cr0_eq            ; Remember
+                       crand   cr5_eq,cr5_eq,cr1_eq            ; Remember if same
                        
-findmapb:      mr.             r3,r4                                           /* Did we hit the end? */
-                       bne+    chkmapb                                         /* Nope... */
+                       xor             r23,r23,r22                                     ; Compare mapping flag words
+                       andi.   r23,r23,mpType|mpPerm           ; Are mapping types and attributes the same?
+                       crand   cr5_eq,cr5_eq,cr0_eq            ; Merge in final check
+                       bf--    cr5_eq,hamSmash                         ; This is not the same, so we return a smash...
                        
-                       la              r3,pephyslink(r9)                       /* Point to where the lock is */                                                
-                       li              r4,PHYS_LOCK                            /* Get the lock bit value */
-                       bl              EXT(hw_unlock_bit)                      /* Go unlock the physentry */
-
-                       li              r3,0                                            /* Say we failed */                     
-                       b               vbail                                           /* Return in abject failure... */
+                       ori             r4,r4,mapRtMapDup                       ; Set duplicate
+                       b               hamReturn                                       ; And leave...
                        
-penterr:       li              r3,1                                            /* Set timeout */
-                       b               vbail                                           /* Return in abject failure... */
-                                       
+hamRemv:       ori             r4,r4,mapRtRemove                       ; We are in the process of removing the collision
+                       b               hamReturn                                       ; Come back yall...
+                       
+hamSmash:      ori             r4,r4,mapRtSmash                        ; Tell caller that it has some clean up to do
+                       b               hamReturn                                       ; Join common epilog code
+
                        .align  5
+                       
+hamBadLock:    li              r3,0                                            ; Set lock time out error code
+                       li              r4,mapRtBadLk                           ; Set lock time out error code
+                       b               hamReturn                                       ; Leave....
+
+hamPanic:      lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
 
-chkmapb:       lwz             r6,mmPTEv(r3)                           /* Pick up our virtual ID */
-                       lwz             r4,mmnext(r3)                           /* Pick up next mapping block */
-                       cmplw   r6,r11                                          /* Have we found ourself? */
-                       lwz             r5,mmPTEhash(r3)                        /* Get the start of our hash chain */
-                       bne-    findmapb                                        /* Nope, still wandering... */
-                       cmplw   r5,r10                                          /* On the same hash chain? */
-                       bne-    findmapb                                        /* Nope, keep looking... */
 
-                       b               vbail                                           /* Return in glorious triumph... */
 
 
 /*
- *                     hw_rem_map(mapping) - remove a mapping from the system.
- *
- *                     Upon entry, R3 contains a pointer to a mapping block and the associated
- *                     physical entry is locked if there is one.
+ *                     mapping *hw_rem_map(pmap, vaddr, addr64_t *next) - remove a mapping from the system.
  *
- *                     If the mapping entry indicates that there is a PTE entry, we invalidate
- *                     if and merge the reference and change information into the phys_entry.
+ *                     Upon entry, R3 contains a pointer to a pmap.  Since vaddr is
+ *                     a 64-bit quantity, it is a long long so it is in R4 and R5.
+ *                     
+ *                     We return the virtual address of the removed mapping as a 
+ *                     R3.
  *
- *                     Next, we remove the mapping from the phys_ent and the PTEG hash list.
+ *                     Note that this is designed to be called from 32-bit mode with a stack.
  *
- *                     Unlock any locks that are left, and exit.
+ *                     We disable translation and all interruptions here.  This keeps is
+ *                     from having to worry about a deadlock due to having anything locked
+ *                     and needing it to process a fault.
  *
  *                     Note that this must be done with both interruptions off and VM off
  *     
- *                     Note that this code depends upon the VSID being of the format 00SXXXXX
- *                     where S is the segment number.
- *
- *                       
+ *  Remove mapping via pmap, regular page, no pte
+ * 
+ *  1) lock pmap share
+ *  2) find mapping full path - finds all possible list previous elements
+ *  4) upgrade pmap to exclusive
+ *  3) bump mapping busy count
+ *  5) remove mapping from search list
+ *  6) unlock pmap
+ *  7) lock physent
+ *  8) remove from physent
+ *  9) unlock physent
+ * 10) drop mapping busy count
+ * 11) drain mapping busy count
+ * 
+ * 
+ * Remove mapping via pmap, regular page, with pte
+ * 
+ *  1) lock pmap share
+ *  2) find mapping full path - finds all possible list previous elements
+ *  3) upgrade lock to exclusive
+ *  4) bump mapping busy count
+ *  5) lock PTEG
+ *  6) invalidate pte and tlbie
+ *  7) atomic merge rc into physent
+ *  8) unlock PTEG
+ *  9) remove mapping from search list
+ * 10) unlock pmap
+ * 11) lock physent
+ * 12) remove from physent
+ * 13) unlock physent
+ * 14) drop mapping busy count
+ * 15) drain mapping busy count
+ * 
+ * 
+ * Remove mapping via pmap, I/O or block
+ * 
+ *  1) lock pmap share
+ *  2) find mapping full path - finds all possible list previous elements
+ *  3) upgrade lock to exclusive
+ *  4) bump mapping busy count
+ *     5) mark remove-in-progress
+ *     6) check and bump remove chunk cursor if needed
+ *     7) unlock pmap
+ *     8) if something to invalidate, go to step 11
+
+ *     9) drop busy
+ * 10) return with mapRtRemove to force higher level to call again
+ * 11) Lock PTEG
+ * 12) invalidate ptes, no tlbie
+ * 13) unlock PTEG
+ * 14) repeat 11 - 13 for all pages in chunk
+ * 15) if not final chunk, go to step 9
+ * 16) invalidate tlb entries for the whole block map but no more than the full tlb
+ * 17) lock pmap share
+ * 18) find mapping full path - finds all possible list previous elements
+ * 19) upgrade lock to exclusive
+ * 20) remove mapping from search list
+ * 21) drop mapping busy count
+ * 22) drain mapping busy count
+ *     
  */
 
                        .align  5
                        .globl  EXT(hw_rem_map)
 
 LEXT(hw_rem_map)
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,24
-                       bl              EXT(dbgLog2)                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
 
-                       bt              pfNoMSRirb,lmvNoMSR                     ; No MSR...
+;
+;                      NOTE NOTE NOTE - IF WE CHANGE THIS STACK FRAME STUFF WE NEED TO CHANGE
+;                      THE HW_PURGE_* ROUTINES ALSO
+;
 
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               lmvNoMSRx
+#define hrmStackSize ((31-15+1)*4)+4
+                       stwu    r1,-(FM_ALIGN(hrmStackSize)+FM_SIZE)(r1)        ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r15,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r16,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r17,FM_ARG0+0x08(r1)            ; Save a register
+                       stw             r18,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r19,FM_ARG0+0x10(r1)            ; Save a register
+                       mfsprg  r19,2                                           ; Get feature flags 
+                       stw             r20,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r21,FM_ARG0+0x18(r1)            ; Save a register
+                       mtcrf   0x02,r19                                        ; move pf64Bit cr6
+                       stw             r22,FM_ARG0+0x1C(r1)            ; Save a register
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save a register
+                       stw             r24,FM_ARG0+0x24(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x28(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x2C(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x30(r1)            ; Save a register
+                       stw             r28,FM_ARG0+0x34(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x38(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x3C(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x40(r1)            ; Save a register
+                       stw             r6,FM_ARG0+0x44(r1)                     ; Save address to save next mapped vaddr
+                       stw             r0,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)      ; Save the return
+
+#if DEBUG
+                       lwz             r11,pmapFlags(r3)                       ; Get pmaps flags
+                       rlwinm. r11,r11,0,pmapVMgsaa            ; Is guest shadow assist active? 
+                       bne             hrmPanic                                        ; Call not valid for guest shadow assist pmap
+#endif
                        
-lmvNoMSR:      
-                       mr              r6,r0
-                       mr              r4,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r4
-                       mr              r0,r6
+                       bt++    pf64Bitb,hrmSF1                         ; skip if 64-bit (only they take the hint)
+                       lwz             r9,pmapvr+4(r3)                         ; Get conversion mask
+                       b               hrmSF1x                                         ; Done...
+                       
+hrmSF1:                ld              r9,pmapvr(r3)                           ; Get conversion mask
 
-lmvNoMSRx:
+hrmSF1x:       
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
+                       
+                       xor             r28,r3,r9                                       ; Convert the pmap to physical addressing
 
-               
-                       lwz             r6,mmPTEhash(r3)                        /* Get pointer to hash list anchor */
-                       lwz             r5,mmPTEv(r3)                           /* Get the VSID */
-                       dcbt    0,r6                                            /* We'll need that chain in a bit */
+;
+;                      Here is where we join in from the hw_purge_* routines
+;
 
-                       rlwinm  r7,r6,0,0,25                            /* Round hash list down to PCA boundary */
-                       li              r12,1                                           /* Get the locked value */
-                       subi    r6,r6,mmhashnext                        /* Make the anchor look like an entry */
+hrmJoin:       lwz             r3,pmapFlags(r28)                       ; Get pmap's flags
+                       mfsprg  r19,2                                           ; Get feature flags again (for alternate entries)
 
-ptegLck1:      lwarx   r10,0,r7                                        /* Get the PTEG lock */
-                       mr.             r10,r10                                         /* Is it locked? */
-                       bne-    ptegLckw1                                       /* Yeah... */
-                       stwcx.  r12,0,r7                                        /* Try to take it */
-                       bne-    ptegLck1                                        /* Someone else was trying, try again... */
-                       b               ptegSXg1                                        /* All done... */
+                       mr              r17,r11                                         ; Save the MSR
+                       mr              r29,r4                                          ; Top half of vaddr
+                       mr              r30,r5                                          ; Bottom half of vaddr
                        
-                       .align  4
-
-ptegLckw1:     mr.             r10,r10                                         /* Check if it's already held */
-                       beq+    ptegLck1                                        /* It's clear... */
-                       lwz             r10,0(r7)                                       /* Get lock word again... */
-                       b               ptegLckw1                                       /* Wait... */
+                       rlwinm. r3,r3,0,pmapVMgsaa                      ; Is guest shadow assist active? 
+                       bne--   hrmGuest                                        ; Yes, handle specially
                        
-                       .align  4
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne--   hrmBadLock                                      ; Nope...
+                       
+;
+;                      Note that we do a full search (i.e., no shortcut level skips, etc.)
+;                      here so that we will know the previous elements so we can dequeue them
+;                      later. Note: we get back mpFlags in R7.
+;
 
-ptegSXg1:      isync                                                           /* Make sure we haven't used anything yet */
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       mr              r4,r29                                          ; High order of address
+                       mr              r5,r30                                          ; Low order of address
+                       bl              EXT(mapSearchFull)                      ; Go see if we can find it
+
+                       andi.   r0,r7,mpPerm                            ; Mapping marked permanent?
+                       crmove  cr5_eq,cr0_eq                           ; Remember permanent marking
+                       mr              r20,r7                                          ; Remember mpFlags
+                       mr.             r31,r3                                          ; Did we? (And remember mapping address for later)
+                       mr              r15,r4                                          ; Save top of next vaddr
+                       mr              r16,r5                                          ; Save bottom of next vaddr
+                       beq--   hrmNotFound                                     ; Nope, not found...
+                       
+                       bf--    cr5_eq,hrmPerm                          ; This one can't be removed...
+;
+;                      Here we try to promote to an exclusive lock.  This will fail if someone else
+;                      has it shared.
+;
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkPromote                                     ; Try to promote shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       beq++   hrmGotX                                         ; Yeah...
+                       
+;
+;                      Since we could not promote our lock, we need to convert to it.
+;                      That means that we drop the shared lock and wait to get it
+;                      exclusive.  Since we release the lock, we need to do the look up
+;                      again.
+;                      
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkConvert                                     ; Convert shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       bne--   hrmBadLock                                      ; Nope, we must have timed out...
+                       
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       mr              r4,r29                                          ; High order of address
+                       mr              r5,r30                                          ; Low order of address
+                       bl              EXT(mapSearchFull)                      ; Rescan the list
+                       
+                       andi.   r0,r7,mpPerm                            ; Mapping marked permanent?
+                       crmove  cr5_eq,cr0_eq                           ; Remember permanent marking
+                       mr.             r31,r3                                          ; Did we lose it when we converted?
+                       mr              r20,r7                                          ; Remember mpFlags
+                       mr              r15,r4                                          ; Save top of next vaddr
+                       mr              r16,r5                                          ; Save bottom of next vaddr
+                       beq--   hrmNotFound                                     ; Yeah, we did, someone tossed it for us...
+               
+                       bf--    cr5_eq,hrmPerm                          ; This one can't be removed...
 
-                       lwz             r12,mmhashnext(r3)                      /* Prime with our forward pointer */
-                       lwz             r4,mmPTEent(r3)                         /* Get the pointer to the PTE now that the lock's set */
+;
+;                      We have an exclusive lock on the mapping chain. And we
+;                      also have the busy count bumped in the mapping so it can
+;                      not vanish on us.
+;
 
-srchmaps:      mr.             r10,r6                                          /* Save the previous entry */
-                       bne+    mapok                                           /* No error... */
+hrmGotX:       mr              r3,r31                                          ; Get the mapping
+                       bl              mapBumpBusy                                     ; Bump up the busy count
                        
-                       lis             r0,HIGH_ADDR(Choke)                     /* We have a kernel choke!!! */
-                       ori             r0,r0,LOW_ADDR(Choke)           
-                       sc                                                                      /* Firmware Heimlich manuever */
-
-                       .align  4                       
+;
+;                      Invalidate any PTEs associated with this
+;                      mapping (more than one if a block) and accumulate the reference
+;                      and change bits.
+;
+;                      Here is also where we need to split 32- and 64-bit processing
+;
 
-mapok:         lwz             r6,mmhashnext(r6)                       /* Look at the next one */
-                       cmplwi  cr5,r4,0                                        /* Is there a PTE? */
-                       cmplw   r6,r3                                           /* Have we found ourselves? */
-                       bne+    srchmaps                                        /* Nope, get your head together... */
+                       lwz             r21,mpPte(r31)                          ; Grab the offset to the PTE
+                       rlwinm  r23,r29,0,1,0                           ; Copy high order vaddr to high if 64-bit machine
+                       mfsdr1  r29                                                     ; Get the hash table base and size
+
+                       rlwinm  r0,r20,0,mpType                         ; Isolate mapping type
+                       cmplwi  cr5,r0,mpBlock                          ; Remember whether this is a block mapping
+                       cmplwi  r0,mpMinSpecial                         ; cr0_lt <- not a special mapping type
+                       
+                       rlwinm  r0,r21,0,mpHValidb,mpHValidb    ; See if we actually have a PTE
+                       ori             r2,r2,0xFFFF                            ; Get mask to clean out hash table base (works for both 32- and 64-bit)
+                       cmpwi   cr1,r0,0                                        ; Have we made a PTE for this yet? 
+                       rlwinm  r21,r21,0,~mpHValid                     ; Clear out valid bit
+                       crorc   cr0_eq,cr1_eq,cr0_lt            ; No need to look at PTE if none or a special mapping
+                       rlwimi  r23,r30,0,0,31                          ; Insert low under high part of address
+                       andc    r29,r29,r2                                      ; Clean up hash table base
+                       li              r22,0                                           ; Clear this on out (also sets RC to 0 if we bail)
+                       mr              r30,r23                                         ; Move the now merged vaddr to the correct register
+                       add             r26,r29,r21                                     ; Point to the PTEG slot
+                       
+                       bt++    pf64Bitb,hrmSplit64                     ; Go do 64-bit version...
+                       
+                       rlwinm  r9,r21,28,4,29                          ; Convert PTEG to PCA entry
+                       beq-    cr5,hrmBlock32                          ; Go treat block specially...
+                       subfic  r9,r9,-4                                        ; Get the PCA entry offset
+                       bt-             cr0_eq,hrmPysDQ32                       ; Skip next if no possible PTE...
+                       add             r7,r9,r29                                       ; Point to the PCA slot
+       
+                       bl              mapLockPteg                                     ; Go lock up the PTEG (Note: we need to save R6 to set PCA)
+       
+                       lwz             r21,mpPte(r31)                          ; Get the quick pointer again
+                       lwz             r5,0(r26)                                       ; Get the top of PTE
                        
-                       stw             r12,mmhashnext(r10)                     /* Remove us from the queue */
-                       rlwinm  r9,r5,1,0,3                                     /* Move in the segment */
-                       rlwinm  r8,r4,6,4,19                            /* Line PTEG disp up to a page */
-                       rlwinm  r11,r5,5,4,19                           /* Line up the VSID */
-                       lwz             r10,mmphysent(r3)                       /* Point to the physical entry */
-               
-                       beq+    cr5,nopte                                       /* There's no PTE to invalidate... */
+                       rlwinm. r0,r21,0,mpHValidb,mpHValidb    ; See if we actually have a PTE
+                       rlwinm  r21,r21,0,~mpHValid                     ; Clear out valid bit
+                       rlwinm  r5,r5,0,1,31                            ; Turn off valid bit in PTE
+                       stw             r21,mpPte(r31)                          ; Make sure we invalidate mpPte, still pointing to PTEG (keep walk_page from making a mistake)
+                       beq-    hrmUlckPCA32                            ; Pte is gone, no need to invalidate...
                        
-                       xor             r8,r8,r11                                       /* Back hash to virt index */
-                       lis             r12,HIGH_ADDR(EXT(tlb_system_lock))     /* Get the TLBIE lock */
-                       rlwimi  r9,r5,22,4,9                            /* Move in the API */
-                       ori             r12,r12,LOW_ADDR(EXT(tlb_system_lock))  /* Grab up the bottom part */
-                       mfspr   r11,pvr                                         /* Find out what kind of machine we are */
-                       rlwimi  r9,r8,0,10,19                           /* Create the virtual address */
-                       rlwinm  r11,r11,16,16,31                        /* Isolate CPU type */
+                       stw             r5,0(r26)                                       ; Invalidate the PTE
 
-                       stw             r5,0(r4)                                        /* Make the PTE invalid */              
+                       li              r9,tlbieLock                            ; Get the TLBIE lock
 
-                       cmplwi  cr1,r11,3                                       /* Is this a 603? */
-                       sync                                                            /* Make sure the invalid is stored */
-                                               
-tlbhang1:      lwarx   r5,0,r12                                        /* Get the TLBIE lock */
-                       rlwinm  r11,r4,29,29,31                         /* Get the bit position of entry */
-                       mr.             r5,r5                                           /* Is it locked? */
-                       lis             r6,0x8000                                       /* Start up a bit mask */
-                       li              r5,1                                            /* Get our lock word */
-                       bne-    tlbhang1                                        /* It's locked, go wait... */
-                       stwcx.  r5,0,r12                                        /* Try to get it */
-                       bne-    tlbhang1                                        /* We was beat... */
+                       sync                                                            ; Make sure the invalid PTE is actually in memory
+       
+hrmPtlb32:     lwarx   r5,0,r9                                         ; Get the TLBIE lock 
+                       mr.             r5,r5                                           ; Is it locked?
+                       li              r5,1                                            ; Get locked indicator
+                       bne-    hrmPtlb32                                       ; It is locked, go spin...
+                       stwcx.  r5,0,r9                                         ; Try to get it
+                       bne-    hrmPtlb32                                       ; We was beat... 
+                       
+                       rlwinm. r0,r19,0,pfSMPcapb,pfSMPcapb    ; Can this processor do SMP?    
+                                       
+                       tlbie   r30                                                     ; Invalidate it all corresponding TLB entries
                        
-                       srw             r6,r6,r11                                       /* Make a "free slot" mask */
-                       lwz             r5,PCAallo(r7)                          /* Get the allocation control bits */
-                       rlwinm  r11,r6,24,8,15                          /* Make the autogen bit to turn off */
-                       or              r5,r5,r6                                        /* turn on the free bit */
-                       rlwimi  r11,r11,24,16,23                        /* Get lock bit mask to turn it off */
+                       beq-    hrmNTlbs                                        ; Jump if we can not do a TLBSYNC....
                        
-                       andc    r5,r5,r11                                       /* Turn off the lock and autogen bits in allocation flags */
-                       li              r11,0                                           /* Lock clear value */
+                       eieio                                                           ; Make sure that the tlbie happens first
+                       tlbsync                                                         ; Wait for everyone to catch up
+                       sync                                                            ; Make sure of it all
+                       
+hrmNTlbs:      li              r0,0                                            ; Clear this 
+                       rlwinm  r2,r21,29,29,31                         ; Get slot number (8 byte entries)
+                       stw             r0,tlbieLock(0)                         ; Clear the tlbie lock
+                       lis             r0,0x8000                                       ; Get bit for slot 0
+                       eieio                                                           ; Make sure those RC bit have been stashed in PTE
+                       
+                       srw             r0,r0,r2                                        ; Get the allocation hash mask
+                       lwz             r22,4(r26)                                      ; Get the latest reference and change bits
+                       or              r6,r6,r0                                        ; Show that this slot is free
+
+hrmUlckPCA32:                  
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock the PTEG
+               
+;
+;                      Now, it is time to remove the mapping and unlock the chain.
+;                      But first, we need to make sure no one else is using this 
+;                      mapping so we drain the busy now
+;                      
 
-                       tlbie   r9                                                      /* Invalidate it everywhere */
+hrmPysDQ32:    mr              r3,r31                                          ; Point to the mapping
+                       bl              mapDrainBusy                            ; Go wait until mapping is unused
 
-                       
-                       beq-    cr1,its603a                                     /* It's a 603, skip the tlbsync... */
-                       
-                       eieio                                                           /* Make sure that the tlbie happens first */
-                       tlbsync                                                         /* wait for everyone to catch up */
-                       isync                                                           
-                       
-its603a:       sync                                                            /* Make sure of it all */
-                       stw             r11,0(r12)                                      /* Clear the tlbie lock */
-                       eieio                                                           /* Make sure those RC bit are loaded */
-                       stw             r5,PCAallo(r7)                          /* Show that the slot is free */
-                       stw             r11,mmPTEent(r3)                        /* Clear the pointer to the PTE */
+                       mr              r3,r28                                          ; Get the pmap to remove from
+                       mr              r4,r31                                          ; Point to the mapping
+                       bl              EXT(mapRemove)                          ; Remove the mapping from the list                      
 
-nopte:         mr.             r10,r10                                         /* See if there is a physical entry */
-                       la              r9,pephyslink(r10)                      /* Point to the physical mapping chain */
-                       beq-    nophys                                          /* No physical entry, we're done... */
-                       beq-    cr5,nadamrg                                     /* No PTE to merge... */
+                       lwz             r4,pmapResidentCnt(r28)         ; Get the mapped page count 
+                       rlwinm  r0,r20,0,mpType                         ; Isolate mapping type
+                       cmplwi  cr1,r0,mpMinSpecial                     ; cr1_lt <- not a special mapping type
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       subi    r4,r4,1                                         ; Drop down the mapped page count
+                       stw             r4,pmapResidentCnt(r28)         ; Set the mapped page count 
+                       bl              sxlkUnlock                                      ; Unlock the search list
 
-                       lwz             r6,4(r4)                                        /* Get the latest reference and change bits */
-                       la              r12,pepte1(r10)                         /* Point right at the master copy */
-                       rlwinm  r6,r6,0,23,24                           /* Extract just the RC bits */
+                       bf--    cr1_lt,hrmRetn32                        ; This one has no real memory associated with it so we are done...
 
-mrgrc:         lwarx   r8,0,r12                                        /* Get the master copy */
-                       or              r8,r8,r6                                        /* Merge in latest RC */
-                       stwcx.  r8,0,r12                                        /* Save it back */
-                       bne-    mrgrc                                           /* If it changed, try again... */
-                       
-nadamrg:       li              r11,0                                           /* Clear this out */
-                       lwz             r12,mmnext(r3)                          /* Prime with our next */
+                       bl              mapPhysFindLock                         ; Go find and lock the physent
 
-                       sync                                                            ; Make sure all is saved
+                       lwz             r9,ppLink+4(r3)                         ; Get first mapping
 
-                       stw             r11,0(r7)                                       /* Unlock the hash chain now so we don't
-                                                                                                  lock out another processor during 
-                                                                                                  our next little search */            
+                       mr              r4,r22                                          ; Get the RC bits we just got
+                       bl              mapPhysMerge                            ; Go merge the RC bits
+                       
+                       rlwinm  r9,r9,0,~ppFlags                        ; Clear the flags from the mapping pointer
                        
-srchpmap:      mr.             r10,r9                                          /* Save the previous entry */
-                       bne+    mapok1                                          /* No error... */
+                       cmplw   r9,r31                                          ; Are we the first on the list?
+                       bne-    hrmNot1st                                       ; Nope...
                        
-                       lis             r0,HIGH_ADDR(Choke)                     /* We have a kernel choke!!! */
-                       ori             r0,r0,LOW_ADDR(Choke)                   
-                       sc                                                                      /* Firmware Heimlich maneuver */
+                       li              r9,0                                            ; Get a 0
+                       lwz             r4,mpAlias+4(r31)                       ; Get our new forward pointer
+                       stw             r9,mpAlias+4(r31)                       ; Make sure we are off the chain
+                       bl              mapPhyCSet32                            ; Go set the physent link and preserve flags                                                            
                        
-                       .align  4
+                       b               hrmPhyDQd                                       ; Join up and unlock it all...
 
-mapok1:                lwz             r9,mmnext(r9)                           /* Look at the next one */
-                       rlwinm  r8,r9,0,27,31                           ; Save the flags (including the lock)
-                       rlwinm  r9,r9,0,0,26                            ; Clear out the flags from first link
-                       cmplw   r9,r3                                           /* Have we found ourselves? */
-                       bne+    srchpmap                                        /* Nope, get your head together... */
+                       .align  5
                        
-                       rlwimi  r12,r8,0,27,31                          ; Insert the lock and flags */
-                       stw             r12,mmnext(r10)                         /* Remove us from the queue */
+hrmPerm:       li              r8,-4096                                        ; Get the value we need to round down to a page
+                       and             r8,r8,r31                                       ; Get back to a page
+                       lwz             r8,mbvrswap+4(r8)                       ; Get last half of virtual to real swap
                        
-                       mtmsr   r0                                                      /* Interrupts and translation back on */
-                       isync
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       li              r3,25
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Return... */
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       
+                       xor             r3,r31,r8                                       ; Flip mapping address to virtual
+                       ori             r3,r3,mapRtPerm                         ; Set permanent mapping error
+                       b               hrmErRtn
+                       
+hrmBadLock:    li              r3,mapRtBadLk                           ; Set bad lock
+                       b               hrmErRtn
+                       
+hrmEndInSight:
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       
+hrmDoneChunk:
+                       mr              r3,r31                                          ; Point to the mapping
+                       bl              mapDropBusy                                     ; Drop the busy here since we need to come back
+                       li              r3,mapRtRemove                          ; Say we are still removing this
+                       b               hrmErRtn
 
-                       .align  4
+                       .align  5
+                       
+hrmNotFound:
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       li              r3,mapRtNotFnd                          ; No mapping found
 
-nophys:                li              r4,0                                            /* Make sure this is 0 */
-                       sync                                                            /* Make sure that chain is updated */
-                       stw             r4,0(r7)                                        /* Unlock the hash chain */
-                       mtmsr   r0                                                      /* Interrupts and translation back on */
-                       isync
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       li              r3,25
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Return... */
+hrmErRtn:      bt++    pf64Bitb,hrmSF1z                        ; skip if 64-bit (only they take the hint)
 
+                       mtmsr   r17                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               hrmRetnCmn                                      ; Join the common return code...
 
-/*
- *                     hw_prot(physent, prot) - Change the protection of a physical page
- *
- *                     Upon entry, R3 contains a pointer to a physical entry which is locked.
- *                     R4 contains the PPC protection bits.
- *
- *                     The first thing we do is to slam the new protection into the phys entry.
- *                     Then we scan the mappings and process each one.
- *
- *                     Acquire the lock on the PTEG hash list for the mapping being processed.
- *
- *                     If the current mapping has a PTE entry, we invalidate
- *                     it and merge the reference and change information into the phys_entry.
- *
- *                     Next, slam the protection bits into the entry and unlock the hash list.
- *
- *                     Note that this must be done with both interruptions off and VM off
- *     
- *                       
- */
+hrmSF1z:       mtmsrd  r17                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               hrmRetnCmn                                      ; Join the common return code...
 
                        .align  5
-                       .globl  EXT(hw_prot)
 
-LEXT(hw_prot)
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r7,r3
-//                     lwz             r5,4(r3)
-                       li              r5,0x1111
-                       li              r3,26
-                       bl              EXT(dbgLog2)                            ; Start of hw_add_map
-                       mr              r3,r7
-                       mtlr    r11
-#endif
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       li              r5,pepte1                                       /* Get displacement to the second word of master pte */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
-
-                       bt              pfNoMSRirb,hpNoMSR                      ; No MSR...
-
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hpNoMSRx
+hrmNot1st:     mr.             r8,r9                                           ; Remember and test current node
+                       beq-    hrmPhyDQd                                       ; Could not find our node, someone must have unmapped us...
+                       lwz             r9,mpAlias+4(r9)                        ; Chain to the next
+                       cmplw   r9,r31                                          ; Is this us?
+                       bne-    hrmNot1st                                       ; Not us...
+               
+                       lwz             r9,mpAlias+4(r9)                        ; Get our forward pointer
+                       stw             r9,mpAlias+4(r8)                        ; Unchain us
                        
-hpNoMSR:       
-                       mr              r10,r0
-                       mr              r7,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r0,r10
-                       mr              r3,r7
-hpNoMSRx:
+                       nop                                                                     ; For alignment
+                       
+hrmPhyDQd:     bl              mapPhysUnlock                           ; Unlock the physent chain
 
+hrmRetn32:     rlwinm  r8,r31,0,0,19                           ; Find start of page
+                       mr              r3,r31                                          ; Copy the pointer to the mapping
+                       lwz             r8,mbvrswap+4(r8)                       ; Get last half of virtual to real swap
+                       bl              mapDrainBusy                            ; Go wait until mapping is unused
 
+                       xor             r3,r31,r8                                       ; Flip mapping address to virtual
                        
-                       lwz             r10,pephyslink(r3)                      /* Get the first mapping block */
-                       rlwinm  r10,r10,0,0,26                          ; Clear out the flags from first link
-
-/*
- *                     Note that we need to to do the interlocked update here because another processor
- *                     can be updating the reference and change bits even though the physical entry
- *                     is locked.  All modifications to the PTE portion of the physical entry must be
- *                     done via interlocked update.
- */
+                       mtmsr   r17                                                     ; Restore enables/translation/etc.
+                       isync
 
-protcng:       lwarx   r8,r5,r3                                        /* Get the master copy */
-                       rlwimi  r8,r4,0,30,31                           /* Move in the protection bits */
-                       stwcx.  r8,r5,r3                                        /* Save it back */
-                       bne-    protcng                                         /* If it changed, try again... */
+hrmRetnCmn:    lwz             r6,FM_ARG0+0x44(r1)                     ; Get address to save next mapped vaddr
+                       lwz             r0,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)      ; Restore the return
+                       lwz             r17,FM_ARG0+0x08(r1)            ; Restore a register
+                       lwz             r18,FM_ARG0+0x0C(r1)            ; Restore a register
+                       mr.             r6,r6                                           ; Should we pass back the "next" vaddr?
+                       lwz             r19,FM_ARG0+0x10(r1)            ; Restore a register
+                       lwz             r20,FM_ARG0+0x14(r1)            ; Restore a register
+                       mtlr    r0                                                      ; Restore the return
+                       
+                       rlwinm  r16,r16,0,0,19                          ; Clean to a page boundary
+                       beq             hrmNoNextAdr                            ; Do not pass back the next vaddr...
+                       stw             r15,0(r6)                                       ; Pass back the top of the next vaddr
+                       stw             r16,4(r6)                                       ; Pass back the bottom of the next vaddr
+
+hrmNoNextAdr:
+                       lwz             r15,FM_ARG0+0x00(r1)            ; Restore a register
+                       lwz             r16,FM_ARG0+0x04(r1)            ; Restore a register
+                       lwz             r21,FM_ARG0+0x18(r1)            ; Restore a register
+                       rlwinm  r3,r3,0,0,31                            ; Clear top of register if 64-bit
+                       lwz             r22,FM_ARG0+0x1C(r1)            ; Restore a register
+                       lwz             r23,FM_ARG0+0x20(r1)            ; Restore a register
+                       lwz             r24,FM_ARG0+0x24(r1)            ; Restore a register
+                       lwz             r25,FM_ARG0+0x28(r1)            ; Restore a register
+                       lwz             r26,FM_ARG0+0x2C(r1)            ; Restore a register
+                       lwz             r27,FM_ARG0+0x30(r1)            ; Restore a register
+                       lwz             r28,FM_ARG0+0x34(r1)            ; Restore a register
+                       lwz             r29,FM_ARG0+0x38(r1)            ; Restore a register
+                       lwz             r30,FM_ARG0+0x3C(r1)            ; Restore a register
+                       lwz             r31,FM_ARG0+0x40(r1)            ; Restore a register
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
 
+;
+;                      Here is where we come when all is lost.  Somehow, we failed a mapping function
+;                      that must work... All hope is gone.  Alas, we die.......
+;
 
+hrmPanic:      lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
 
-protnext:      mr.             r10,r10                                         /* Are there any more mappings? */
-                       beq-    protdone                                        /* Naw... */
-                       
-                       lwz             r7,mmPTEhash(r10)                       /* Get pointer to hash list anchor */
-                       lwz             r5,mmPTEv(r10)                          /* Get the virtual address */
-                       rlwinm  r7,r7,0,0,25                            /* Round hash list down to PCA boundary */
 
-                       li              r12,1                                           /* Get the locked value */
+;
+;                      Invalidate block mappings by invalidating a chunk of autogen PTEs in PTEGs hashed
+;                      in the range. Then, if we did not finish, return a code indicating that we need to 
+;                      be called again.  Eventually, we will finish and then, we will do a TLBIE for each 
+;                      PTEG up to the point where we have cleared it all (64 for 32-bit architecture)
+;
+;                      A potential speed up is that we stop the invalidate loop once we have walked through
+;                      the hash table once. This really is not worth the trouble because we need to have
+;                      mapped 1/2 of physical RAM in an individual block.  Way unlikely.
+;
+;                      We should rethink this and see if we think it will be faster to check PTE and
+;                      only invalidate the specific PTE rather than all block map PTEs in the PTEG.
+;
 
-protLck1:      lwarx   r11,0,r7                                        /* Get the PTEG lock */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       bne-    protLckw1                                       /* Yeah... */
-                       stwcx.  r12,0,r7                                        /* Try to take it */
-                       bne-    protLck1                                        /* Someone else was trying, try again... */
-                       b               protSXg1                                        /* All done... */
+                       .align  5
                        
-                       .align  4
+hrmBlock32:    lis             r29,0xD000                                      ; Get shift to 32MB bsu
+                       rlwinm  r24,r20,mpBSub+1+2,29,29        ; Rotate to get 0 if 4K bsu or 13 if 32MB bsu
+                       lhz             r25,mpBSize(r31)                        ; Get the number of pages in block
+                       lhz             r23,mpSpace(r31)                        ; Get the address space hash
+                       lwz             r9,mpBlkRemCur(r31)                     ; Get our current remove position
+                       rlwnm   r29,r29,r24,28,31                       ; Rotate to get 0 or 13
+                       addi    r25,r25,1                                       ; Account for zero-based counting
+                       ori             r0,r20,mpRIP                            ; Turn on the remove in progress flag
+                       slw             r25,r25,r29                                     ; Adjust for 32MB if needed
+                       mfsdr1  r29                                                     ; Get the hash table base and size
+                       rlwinm  r24,r23,maxAdrSpb,32-maxAdrSpb-maxAdrSpb,31-maxAdrSpb   ; Get high order of hash
+                       subi    r25,r25,1                                       ; Convert back to zero-based counting
+                       lwz             r27,mpVAddr+4(r31)                      ; Get the base vaddr
+                       sub             r4,r25,r9                                       ; Get number of pages left
+                       cmplw   cr1,r9,r25                                      ; Have we already hit the end?
+                       addi    r10,r9,mapRemChunk                      ; Point to the start of the next chunk
+                       addi    r2,r4,-mapRemChunk                      ; See if mapRemChunk or more
+                       rlwinm  r26,r29,16,7,15                         ; Get the hash table size
+                       srawi   r2,r2,31                                        ; We have -1 if less than mapRemChunk or 0 if equal or more
+                       stb             r0,mpFlags+3(r31)                       ; Save the flags with the mpRIP bit on
+                       subi    r4,r4,mapRemChunk-1                     ; Back off for a running start (will be negative for more than mapRemChunk)
+                       cmpwi   cr7,r2,0                                        ; Remember if we have finished
+                       slwi    r0,r9,12                                        ; Make cursor into page offset
+                       or              r24,r24,r23                                     ; Get full hash
+                       and             r4,r4,r2                                        ; If more than a chunk, bring this back to 0
+                       rlwinm  r29,r29,0,0,15                          ; Isolate the hash table base
+                       add             r27,r27,r0                                      ; Adjust vaddr to start of current chunk
+                       addi    r4,r4,mapRemChunk-1                     ; Add mapRemChunk-1 to get max(num left,  chunksize)
+                       
+                       bgt-    cr1,hrmEndInSight                       ; Someone is already doing the last hunk...
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       stw             r10,mpBlkRemCur(r31)            ; Set next chunk to do (note: this may indicate after end)
+                       bl              sxlkUnlock                                      ; Unlock the search list while we are invalidating
+                       
+                       rlwinm  r8,r27,4+maxAdrSpb,31-maxAdrSpb-3,31-maxAdrSpb  ; Isolate the segment
+                       rlwinm  r30,r27,26,6,25                         ; Shift vaddr to PTEG offset (and remember VADDR in R27)
+                       xor             r24,r24,r8                                      ; Get the proper VSID
+                       rlwinm  r21,r27,26,10,25                        ; Shift page index to PTEG offset (and remember VADDR in R27)
+                       ori             r26,r26,lo16(0xFFC0)            ; Stick in the rest of the length
+                       rlwinm  r22,r4,6,10,25                          ; Shift size to PTEG offset
+                       rlwinm  r24,r24,6,0,25                          ; Shift hash to PTEG units
+                       add             r22,r22,r30                                     ; Get end address (in PTEG units)
+                       
+hrmBInv32:     rlwinm  r23,r30,0,10,25                         ; Isolate just the page index 
+                       xor             r23,r23,r24                                     ; Hash it
+                       and             r23,r23,r26                                     ; Wrap it into the table
+                       rlwinm  r3,r23,28,4,29                          ; Change to PCA offset
+                       subfic  r3,r3,-4                                        ; Get the PCA entry offset
+                       add             r7,r3,r29                                       ; Point to the PCA slot
+                       cmplw   cr5,r30,r22                                     ; Check if we reached the end of the range
+                       addi    r30,r30,64                                      ; bump to the next vaddr
+                                                               
+                       bl              mapLockPteg                                     ; Lock the PTEG
+                                       
+                       rlwinm. r4,r6,16,0,7                            ; Position, save, and test block mappings in PCA
+                       add             r5,r23,r29                                      ; Point to the PTEG
+                       li              r0,0                                            ; Set an invalid PTE value
+                       beq+    hrmBNone32                                      ; No block map PTEs in this PTEG...
+                       mtcrf   0x80,r4                                         ; Set CRs to select PTE slots
+                       mtcrf   0x40,r4                                         ; Set CRs to select PTE slots
 
-protLckw1:     mr.             r11,r11                                         /* Check if it's already held */
-                       beq+    protLck1                                        /* It's clear... */
-                       lwz             r11,0(r7)                                       /* Get lock word again... */
-                       b               protLckw1                                       /* Wait... */
-                       
-                       .align  4
+                       bf              0,hrmSlot0                                      ; No autogen here
+                       stw             r0,0x00(r5)                                     ; Invalidate PTE
 
-protSXg1:      isync                                                           /* Make sure we haven't used anything yet */
+hrmSlot0:      bf              1,hrmSlot1                                      ; No autogen here
+                       stw             r0,0x08(r5)                                     ; Invalidate PTE
 
-                       lwz             r6,mmPTEent(r10)                        /* Get the pointer to the PTE now that the lock's set */
+hrmSlot1:      bf              2,hrmSlot2                                      ; No autogen here
+                       stw             r0,0x10(r5)                                     ; Invalidate PTE
 
-                       rlwinm  r9,r5,1,0,3                                     /* Move in the segment */
-                       lwz             r2,mmPTEr(r10)                          ; Get the mapping copy of the PTE
-                       mr.             r6,r6                                           /* See if there is a PTE here */
-                       rlwinm  r8,r5,31,2,25                           /* Line it up */
-                       rlwimi  r2,r4,0,30,31                           ; Move protection bits into the mapping copy
-               
-                       beq+    protul                                          /* There's no PTE to invalidate... */
-                       
-                       xor             r8,r8,r6                                        /* Back hash to virt index */
-                       rlwimi  r9,r5,22,4,9                            /* Move in the API */
-                       lis             r12,HIGH_ADDR(EXT(tlb_system_lock))     /* Get the TLBIE lock */
-                       rlwinm  r5,r5,0,1,31                            /* Clear the valid bit */
-                       ori             r12,r12,LOW_ADDR(EXT(tlb_system_lock))  /* Grab up the bottom part */
-                       mfspr   r11,pvr                                         /* Find out what kind of machine we are */
-                       rlwimi  r9,r8,6,10,19                           /* Create the virtual address */
-                       rlwinm  r11,r11,16,16,31                        /* Isolate CPU type */
-
-                       stw             r5,0(r6)                                        /* Make the PTE invalid */              
-                       cmplwi  cr1,r11,3                                       /* Is this a 603? */
-                       sync                                                            /* Make sure the invalid is stored */
-                                               
-tlbhangp:      lwarx   r11,0,r12                                       /* Get the TLBIE lock */
-                       rlwinm  r8,r6,29,29,31                          /* Get the bit position of entry */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       lis             r5,0x8000                                       /* Start up a bit mask */
-                       li              r11,1                                           /* Get our lock word */
-                       bne-    tlbhangp                                        /* It's locked, go wait... */
-                       stwcx.  r11,0,r12                                       /* Try to get it */
-                       bne-    tlbhangp                                        /* We was beat... */
-                       
-                       li              r11,0                                           /* Lock clear value */
+hrmSlot2:      bf              3,hrmSlot3                                      ; No autogen here
+                       stw             r0,0x18(r5)                                     ; Invalidate PTE
 
-                       tlbie   r9                                                      /* Invalidate it everywhere */
+hrmSlot3:      bf              4,hrmSlot4                                      ; No autogen here
+                       stw             r0,0x20(r5)                                     ; Invalidate PTE
 
-                       beq-    cr1,its603p                                     /* It's a 603, skip the tlbsync... */
-                       
-                       eieio                                                           /* Make sure that the tlbie happens first */
-                       tlbsync                                                         /* wait for everyone to catch up */
-                       isync                                                           
-                       
-its603p:       stw             r11,0(r12)                                      /* Clear the lock */
-                       srw             r5,r5,r8                                        /* Make a "free slot" mask */
-                       sync                                                            /* Make sure of it all */
+hrmSlot4:      bf              5,hrmSlot5                                      ; No autogen here
+                       stw             r0,0x28(r5)                                     ; Invalidate PTE
 
-                       lwz             r6,4(r6)                                        /* Get the latest reference and change bits */
-                       stw             r11,mmPTEent(r10)                       /* Clear the pointer to the PTE */
-                       rlwinm  r6,r6,0,23,24                           /* Extract the RC bits */
-                       lwz             r9,PCAallo(r7)                          /* Get the allocation control bits */
-                       rlwinm  r8,r5,24,8,15                           /* Make the autogen bit to turn off */
-                       rlwimi  r2,r6,0,23,24                           ; Put the latest RC bit in mapping copy
-                       or              r9,r9,r5                                        /* Set the slot free */
-                       rlwimi  r8,r8,24,16,23                          /* Get lock bit mask to turn it off */
-                       andc    r9,r9,r8                                        /* Clear the auto and lock bits */
-                       li              r5,pepte1                                       /* Get displacement to the second word of master pte */
-                       stw             r9,PCAallo(r7)                          /* Store the allocation controls */
-                       
-protmod:       lwarx   r11,r5,r3                                       /* Get the master copy */
-                       or              r11,r11,r6                                      /* Merge in latest RC */
-                       stwcx.  r11,r5,r3                                       /* Save it back */
-                       bne-    protmod                                         /* If it changed, try again... */
-                       
-protul:                li              r4,0                                            /* Get a 0 */
-                       stw             r2,mmPTEr(r10)                          ; Save the updated mapping PTE
-                       lwz             r10,mmnext(r10)                         /* Get the next */
+hrmSlot5:      bf              6,hrmSlot6                                      ; No autogen here
+                       stw             r0,0x30(r5)                                     ; Invalidate PTE
 
-                       sync                                                            ; Make sure stores are complete
+hrmSlot6:      bf              7,hrmSlot7                                      ; No autogen here
+                       stw             r0,0x38(r5)                                     ; Invalidate PTE
 
-                       stw             r4,0(r7)                                        /* Unlock the hash chain */
-                       b               protnext                                        /* Go get the next one */
-                       
-                       .align  4
+hrmSlot7:      rlwinm  r0,r4,16,16,23                          ; Move in use to autogen
+                       or              r6,r6,r4                                        ; Flip on the free bits that corrospond to the autogens we cleared
+                       andc    r6,r6,r0                                        ; Turn off all the old autogen bits
 
-protdone:      mtmsr   r0                                                      /* Interrupts and translation back on */
-                       isync
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       li              r3,27
-                       bl              EXT(dbgLog2)                            ; Start of hw_add_map
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Return... */
+hrmBNone32:    eieio                                                           ; Make sure all updates come first
 
+                       stw             r6,0(r7)                                        ; Unlock and set the PCA
+                       
+                       bne+    cr5,hrmBInv32                           ; Go invalidate the next...
 
-/*
- *                     hw_prot_virt(mapping, prot) - Change the protection of single page
- *
- *                     Upon entry, R3 contains a pointer (real) to a mapping.
- *                     R4 contains the PPC protection bits.
- *
- *                     Acquire the lock on the PTEG hash list for the mapping being processed.
- *
- *                     If the current mapping has a PTE entry, we invalidate
- *                     it and merge the reference and change information into the phys_entry.
- *
- *                     Next, slam the protection bits into the entry, merge the RC bits, 
- *                     and unlock the hash list.
- *
- *                     Note that this must be done with both interruptions off and VM off
- *     
- *                       
- */
+                       bge+    cr7,hrmDoneChunk                        ; We have not as yet done the last chunk, go tell our caller to call again...
 
-                       .align  5
-                       .globl  EXT(hw_prot_virt)
+                       mr              r3,r31                                          ; Copy the pointer to the mapping
+                       bl              mapDrainBusy                            ; Go wait until we are sure all other removers are done with this one
 
-LEXT(hw_prot_virt)
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r7,r3
-//                     lwz             r5,4(r3)
-                       li              r5,0x1111
-                       li              r3,40
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r7
-                       mtlr    r11
-#endif
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
+                       sync                                                            ; Make sure memory is consistent
                        
-                       bt              pfNoMSRirb,hpvNoMSR                     ; No MSR...
-
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hpvNoMSRx
+                       subi    r5,r25,63                                       ; Subtract TLB size from page count (note we are 0 based here)
+                       li              r6,63                                           ; Assume full invalidate for now
+                       srawi   r5,r5,31                                        ; Make 0 if we need a full purge, -1 otherwise
+                       andc    r6,r6,r5                                        ; Clear max if we have less to do
+                       and             r5,r25,r5                                       ; Clear count if we have more than max
+                       lwz             r27,mpVAddr+4(r31)                      ; Get the base vaddr again
+                       li              r7,tlbieLock                            ; Get the TLBIE lock
+                       or              r5,r5,r6                                        ; Get number of TLBIEs needed           
+                                       
+hrmBTLBlck:    lwarx   r2,0,r7                                         ; Get the TLBIE lock
+                       mr.             r2,r2                                           ; Is it locked?
+                       li              r2,1                                            ; Get our lock value
+                       bne-    hrmBTLBlck                                      ; It is locked, go wait...
+                       stwcx.  r2,0,r7                                         ; Try to get it
+                       bne-    hrmBTLBlck                                      ; We was beat...
+       
+hrmBTLBi:      addic.  r5,r5,-1                                        ; See if we did them all
+                       tlbie   r27                                                     ; Invalidate it everywhere
+                       addi    r27,r27,0x1000                          ; Up to the next page
+                       bge+    hrmBTLBi                                        ; Make sure we have done it all...
                        
-hpvNoMSR:      
-                       mr              r5,r0
-                       mr              r7,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r7
-                       mr              r0,r5
-hpvNoMSRx:
-
+                       rlwinm. r0,r19,0,pfSMPcapb,pfSMPcapb    ; Can this processor do SMP?    
+                       li              r2,0                                            ; Lock clear value
+                       
+                       sync                                                            ; Make sure all is quiet
+                       beq-    hrmBNTlbs                                       ; Jump if we can not do a TLBSYNC....
+                       
+                       eieio                                                           ; Make sure that the tlbie happens first
+                       tlbsync                                                         ; Wait for everyone to catch up
+                       sync                                                            ; Wait for quiet again
+
+hrmBNTlbs:     stw             r2,tlbieLock(0)                         ; Clear the tlbie lock
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne-    hrmPanic                                        ; Nope...
+                       
+                       lwz             r4,mpVAddr(r31)                         ; High order of address
+                       lwz             r5,mpVAddr+4(r31)                       ; Low order of address
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       mr              r29,r4                                          ; Save this in case we need it (only promote fails)
+                       mr              r30,r5                                          ; Save this in case we need it (only promote fails)
+                       bl              EXT(mapSearchFull)                      ; Go see if we can find it
+                       
+                       mr.             r3,r3                                           ; Did we? (And remember mapping address for later)
+                       mr              r15,r4                                          ; Save top of next vaddr
+                       mr              r16,r5                                          ; Save bottom of next vaddr
+                       beq-    hrmPanic                                        ; Nope, not found...
+                       
+                       cmplw   r3,r31                                          ; Same mapping?
+                       bne-    hrmPanic                                        ; Not good...
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkPromote                                     ; Try to promote shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       mr              r3,r31                                          ; Restore the mapping pointer
+                       beq+    hrmBDone1                                       ; Yeah...
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkConvert                                     ; Convert shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       bne--   hrmPanic                                        ; Nope, we must have timed out...
+                       
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       mr              r4,r29                                          ; High order of address
+                       mr              r5,r30                                          ; Low order of address
+                       bl              EXT(mapSearchFull)                      ; Rescan the list
+                       
+                       mr.             r3,r3                                           ; Did we lose it when we converted?
+                       mr              r15,r4                                          ; Save top of next vaddr
+                       mr              r16,r5                                          ; Save bottom of next vaddr
+                       beq--   hrmPanic                                        ; Yeah, we did, someone tossed it for us...
+
+hrmBDone1:     bl              mapDrainBusy                            ; Go wait until mapping is unused
+
+                       mr              r3,r28                                          ; Get the pmap to remove from
+                       mr              r4,r31                                          ; Point to the mapping
+                       bl              EXT(mapRemove)                          ; Remove the mapping from the list      
+                                       
+                       lwz             r4,pmapResidentCnt(r28)         ; Get the mapped page count 
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       subi    r4,r4,1                                         ; Drop down the mapped page count
+                       stw             r4,pmapResidentCnt(r28)         ; Set the mapped page count 
+                       bl              sxlkUnlock                                      ; Unlock the search list
+               
+                       b               hrmRetn32                                       ; We are all done, get out...
 
+;
+;                      Here we handle the 64-bit version of hw_rem_map
+;
+               
+                       .align  5
+               
+hrmSplit64:    rlwinm  r9,r21,27,5,29                          ; Convert PTEG to PCA entry
+                       beq--   cr5,hrmBlock64                          ; Go treat block specially...
+                       subfic  r9,r9,-4                                        ; Get the PCA entry offset
+                       bt--    cr0_eq,hrmPysDQ64                       ; Skip next if no possible PTE...
+                       add             r7,r9,r29                                       ; Point to the PCA slot
                        
-/*
- *                     Note that we need to to do the interlocked update here because another processor
- *                     can be updating the reference and change bits even though the physical entry
- *                     is locked.  All modifications to the PTE portion of the physical entry must be
- *                     done via interlocked update.
- */
+                       bl              mapLockPteg                                     ; Go lock up the PTEG
+       
+                       lwz             r21,mpPte(r31)                          ; Get the quick pointer again
+                       ld              r5,0(r26)                                       ; Get the top of PTE
+                       
+                       rlwinm. r0,r21,0,mpHValidb,mpHValidb    ; See if we actually have a PTE
+                       rlwinm  r21,r21,0,~mpHValid                     ; Clear out valid bit
+                       sldi    r23,r5,16                                       ; Shift AVPN up to EA format
+//                     ****    Need to adjust above shift based on the page size - large pages need to shift a bit more
+                       rldicr  r5,r5,0,62                                      ; Clear the valid bit
+                       rldimi  r23,r30,0,36                            ; Insert the page portion of the VPN
+                       stw             r21,mpPte(r31)                          ; Make sure we invalidate mpPte but keep pointing to PTEG (keep walk_page from making a mistake)
+                       beq--   hrmUlckPCA64                            ; Pte is gone, no need to invalidate...
+                       
+                       std             r5,0(r26)                                       ; Invalidate the PTE
+
+                       li              r9,tlbieLock                            ; Get the TLBIE lock
+
+                       sync                                                            ; Make sure the invalid PTE is actually in memory
+
+hrmPtlb64:     lwarx   r5,0,r9                                         ; Get the TLBIE lock 
+                       rldicl  r23,r23,0,16                            ; Clear bits 0:15 cause they say to
+                       mr.             r5,r5                                           ; Is it locked?
+                       li              r5,1                                            ; Get locked indicator
+                       bne--   hrmPtlb64w                                      ; It is locked, go spin...
+                       stwcx.  r5,0,r9                                         ; Try to get it
+                       bne--   hrmPtlb64                                       ; We was beat... 
+                                       
+                       tlbie   r23                                                     ; Invalidate all corresponding TLB entries
+                       
+                       eieio                                                           ; Make sure that the tlbie happens first
+                       tlbsync                                                         ; Wait for everyone to catch up
                        
-                       lwz             r7,mmPTEhash(r3)                        /* Get pointer to hash list anchor */
-                       lwz             r5,mmPTEv(r3)                           /* Get the virtual address */
-                       rlwinm  r7,r7,0,0,25                            /* Round hash list down to PCA boundary */
+                       ptesync                                                         ; Make sure of it all
+                       li              r0,0                                            ; Clear this 
+                       rlwinm  r2,r21,28,29,31                         ; Get slot number (16 byte entries)
+                       stw             r0,tlbieLock(0)                         ; Clear the tlbie lock
+                       oris    r0,r0,0x8000                            ; Assume slot 0
 
-                       li              r12,1                                           /* Get the locked value */
+                       srw             r0,r0,r2                                        ; Get slot mask to deallocate
 
-protvLck1:     lwarx   r11,0,r7                                        /* Get the PTEG lock */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       bne-    protvLckw1                                      /* Yeah... */
-                       stwcx.  r12,0,r7                                        /* Try to take it */
-                       bne-    protvLck1                                       /* Someone else was trying, try again... */
-                       b               protvSXg1                                       /* All done... */
+                       lwz             r22,12(r26)                                     ; Get the latest reference and change bits
+                       or              r6,r6,r0                                        ; Make the guy we killed free
                        
-                       .align  4
+hrmUlckPCA64:
+                       eieio                                                           ; Make sure all updates come first
 
-protvLckw1:    mr.             r11,r11                                         /* Check if it's already held */
-                       beq+    protvLck1                                       /* It's clear... */
-                       lwz             r11,0(r7)                                       /* Get lock word again... */
-                       b               protvLckw1                                      /* Wait... */
-                       
-                       .align  4
+                       stw             r6,0(r7)                                        ; Unlock and change the PCA
+               
+hrmPysDQ64:    mr              r3,r31                                          ; Point to the mapping
+                       bl              mapDrainBusy                            ; Go wait until mapping is unused
+
+                       mr              r3,r28                                          ; Get the pmap to remove from
+                       mr              r4,r31                                          ; Point to the mapping
+                       bl              EXT(mapRemove)                          ; Remove the mapping from the list                      
+
+                       rlwinm  r0,r20,0,mpType                         ; Isolate mapping type
+                       cmplwi  cr1,r0,mpMinSpecial                     ; cr1_lt <- not a special mapping type
+                       lwz             r4,pmapResidentCnt(r28)         ; Get the mapped page count 
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       subi    r4,r4,1                                         ; Drop down the mapped page count
+                       stw             r4,pmapResidentCnt(r28)         ; Set the mapped page count 
+                       bl              sxlkUnlock                                      ; Unlock the search list
+               
+                       bf--    cr1_lt,hrmRetn64                        ; This one has no real memory associated with it so we are done...
 
-protvSXg1:     isync                                                           /* Make sure we haven't used anything yet */
+                       bl              mapPhysFindLock                         ; Go find and lock the physent
 
-                       lwz             r6,mmPTEent(r3)                         /* Get the pointer to the PTE now that the lock's set */
-                       lwz             r2,mmPTEr(r3)                           ; Get the mapping copy if the real part
+                       li              r0,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       ld              r9,ppLink(r3)                           ; Get first mapping
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       mr              r4,r22                                          ; Get the RC bits we just got
+                       
+                       bl              mapPhysMerge                            ; Go merge the RC bits
+                       
+                       andc    r9,r9,r0                                        ; Clean up the mapping pointer
+                       
+                       cmpld   r9,r31                                          ; Are we the first on the list?
+                       bne--   hrmNot1st64                                     ; Nope...
+                       
+                       li              r9,0                                            ; Get a 0
+                       ld              r4,mpAlias(r31)                         ; Get our forward pointer
+                       
+                       std             r9,mpAlias(r31)                         ; Make sure we are off the chain
+                       bl              mapPhyCSet64                            ; Go set the physent link and preserve flags                                                            
 
-                       rlwinm  r9,r5,1,0,3                                     /* Move in the segment */
-                       cmplwi  cr7,r6,0                                        ; Any PTE to invalidate?
-                       rlwimi  r2,r4,0,30,31                           ; Move in the new protection bits
-                       rlwinm  r8,r5,31,2,25                           /* Line it up */
-               
-                       beq+    cr7,pvnophys                            /* There's no PTE to invalidate... */
-                       
-                       xor             r8,r8,r6                                        /* Back hash to virt index */
-                       rlwimi  r9,r5,22,4,9                            /* Move in the API */
-                       lis             r12,HIGH_ADDR(EXT(tlb_system_lock))     /* Get the TLBIE lock */
-                       rlwinm  r5,r5,0,1,31                            /* Clear the valid bit */
-                       ori             r12,r12,LOW_ADDR(EXT(tlb_system_lock))  /* Grab up the bottom part */
-                       mfspr   r11,pvr                                         /* Find out what kind of machine we are */
-                       rlwimi  r9,r8,6,10,19                           /* Create the virtual address */
-                       rlwinm  r11,r11,16,16,31                        /* Isolate CPU type */
-
-                       stw             r5,0(r6)                                        /* Make the PTE invalid */              
-                       cmplwi  cr1,r11,3                                       /* Is this a 603? */
-                       sync                                                            /* Make sure the invalid is stored */
+                       b               hrmPhyDQd64                                     ; Join up and unlock it all...
+                       
+hrmPtlb64w:    li              r5,lgKillResv                           ; Point to some spare memory
+                       stwcx.  r5,0,r5                                         ; Clear the pending reservation                 
                                                
-tlbhangpv:     lwarx   r11,0,r12                                       /* Get the TLBIE lock */
-                       rlwinm  r8,r6,29,29,31                          /* Get the bit position of entry */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       lis             r5,0x8000                                       /* Start up a bit mask */
-                       li              r11,1                                           /* Get our lock word */
-                       bne-    tlbhangpv                                       /* It's locked, go wait... */
-                       stwcx.  r11,0,r12                                       /* Try to get it */
-                       bne-    tlbhangpv                                       /* We was beat... */
                        
-                       li              r11,0                                           /* Lock clear value */
+hrmPtlb64x:    lwz             r5,0(r9)                                        ; Do a regular load to avoid taking reservation
+                       mr.             r5,r5                                           ; is it locked?
+                       beq++   hrmPtlb64                                       ; Nope...
+                       b               hrmPtlb64x                                      ; Sniff some more...
+               
+                       .align  5                                                       
+                       
+hrmNot1st64:
+                       mr.             r8,r9                                           ; Remember and test current node
+                       beq--   hrmPhyDQd64                                     ; Could not find our node...
+                       ld              r9,mpAlias(r9)                          ; Chain to the next
+                       cmpld   r9,r31                                          ; Is this us?
+                       bne--   hrmNot1st64                                     ; Not us...
+               
+                       ld              r9,mpAlias(r9)                          ; Get our forward pointer
+                       std             r9,mpAlias(r8)                          ; Unchain us
+                       
+                       nop                                                                     ; For alignment
+                       
+hrmPhyDQd64:   
+                       bl              mapPhysUnlock                           ; Unlock the physent chain
 
-                       tlbie   r9                                                      /* Invalidate it everywhere */
+hrmRetn64:     rldicr  r8,r31,0,51                                     ; Find start of page
+                       mr              r3,r31                                          ; Copy the pointer to the mapping
+                       lwz             r8,mbvrswap+4(r8)                       ; Get last half of virtual to real swap
+                       bl              mapDrainBusy                            ; Go wait until mapping is unused
 
-                       beq-    cr1,its603pv                            /* It's a 603, skip the tlbsync... */
+                       xor             r3,r31,r8                                       ; Flip mapping address to virtual
                        
-                       eieio                                                           /* Make sure that the tlbie happens first */
-                       tlbsync                                                         /* wait for everyone to catch up */
-                       isync                                                           
-                       
-its603pv:      stw             r11,0(r12)                                      /* Clear the lock */
-                       srw             r5,r5,r8                                        /* Make a "free slot" mask */
-                       sync                                                            /* Make sure of it all */
-
-                       lwz             r6,4(r6)                                        /* Get the latest reference and change bits */
-                       stw             r11,mmPTEent(r3)                        /* Clear the pointer to the PTE */
-                       rlwinm  r6,r6,0,23,24                           /* Extract the RC bits */
-                       lwz             r9,PCAallo(r7)                          /* Get the allocation control bits */
-                       rlwinm  r8,r5,24,8,15                           /* Make the autogen bit to turn off */
-                       lwz             r10,mmphysent(r3)                       ; Get any physical entry
-                       or              r9,r9,r5                                        /* Set the slot free */
-                       rlwimi  r8,r8,24,16,23                          /* Get lock bit mask to turn it off */
-                       andc    r9,r9,r8                                        /* Clear the auto and lock bits */
-                       mr.             r10,r10                                         ; Is there a physical entry?
-                       li              r5,pepte1                                       /* Get displacement to the second word of master pte */
-                       stw             r9,PCAallo(r7)                          /* Store the allocation controls */
-                       rlwimi  r2,r6,0,23,24                           ; Stick in RC bits
-                       beq-    pvnophys                                        ; No physical entry...
-                       
-protvmod:      lwarx   r11,r5,r10                                      /* Get the master copy */
-                       or              r11,r11,r6                                      /* Merge in latest RC */
-                       stwcx.  r11,r5,r10                                      /* Save it back */
-                       bne-    protvmod                                        /* If it changed, try again... */
-                       
-pvnophys:      li              r4,0                                            /* Get a 0 */
-                       stw             r2,mmPTEr(r3)                           ; Set the real part of the PTE
-
-                       sync                                                            ; Make sure everything is stored
-
-                       stw             r4,0(r7)                                        /* Unlock the hash chain */
-                       mtmsr   r0                                                      ; Restore interrupts and translation
+                       mtmsrd  r17                                                     ; Restore enables/translation/etc.
                        isync
-
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       li              r3,41
-                       bl              EXT(dbgLog2)                            
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Return... */
-
-
-/*
- *                     hw_attr_virt(mapping, attr) - Change the attributes of single page
- *
- *                     Upon entry, R3 contains a pointer (real) to a mapping.
- *                     R4 contains the WIMG bits.
- *
- *                     Acquire the lock on the PTEG hash list for the mapping being processed.
- *
- *                     If the current mapping has a PTE entry, we invalidate
- *                     it and merge the reference and change information into the phys_entry.
- *
- *                     Next, slam the WIMG bits into the entry, merge the RC bits, 
- *                     and unlock the hash list.
- *
- *                     Note that this must be done with both interruptions off and VM off
- *     
- *                       
- */
-
-                       .align  5
-                       .globl  EXT(hw_attr_virt)
-
-LEXT(hw_attr_virt)
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r7,r3
-//                     lwz             r5,4(r3)
-                       li              r5,0x1111
-                       li              r3,40
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r7
-                       mtlr    r11
-#endif
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
-
-                       bt              pfNoMSRirb,havNoMSR                     ; No MSR...
-
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               havNoMSRx
-                       
-havNoMSR:      
-                       mr              r5,r0
-                       mr              r7,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r7
-                       mr              r0,r5
-havNoMSRx:
-
-/*
- *                     Note that we need to to do the interlocked update here because another processor
- *                     can be updating the reference and change bits even though the physical entry
- *                     is locked.  All modifications to the PTE portion of the physical entry must be
- *                     done via interlocked update.
- */
                        
-                       lwz             r7,mmPTEhash(r3)                        /* Get pointer to hash list anchor */
-                       lwz             r5,mmPTEv(r3)                           /* Get the virtual address */
-                       rlwinm  r7,r7,0,0,25                            /* Round hash list down to PCA boundary */
+                       b               hrmRetnCmn                                      ; Join the common return path...
 
-                       li              r12,1                                           /* Get the locked value */
 
-attrvLck1:     lwarx   r11,0,r7                                        /* Get the PTEG lock */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       bne-    attrvLckw1                                      /* Yeah... */
-                       stwcx.  r12,0,r7                                        /* Try to take it */
-                       bne-    attrvLck1                                       /* Someone else was trying, try again... */
-                       b               attrvSXg1                                       /* All done... */
-                       
-                       .align  4
+;
+;                      Check hrmBlock32 for comments.
+;
 
-attrvLckw1:    mr.             r11,r11                                         /* Check if it's already held */
-                       beq+    attrvLck1                                       /* It's clear... */
-                       lwz             r11,0(r7)                                       /* Get lock word again... */
-                       b               attrvLckw1                                      /* Wait... */
+                       .align  5
                        
-                       .align  4
-
-attrvSXg1:     isync                                                           /* Make sure we haven't used anything yet */
-
-                       lwz             r6,mmPTEent(r3)                         /* Get the pointer to the PTE now that the lock's set */
-                       lwz             r2,mmPTEr(r3)                           ; Get the mapping copy if the real part
-
-                       rlwinm  r9,r5,1,0,3                                     /* Move in the segment */
-                       mr.             r6,r6                                           /* See if there is a PTE here */
-                       rlwimi  r2,r4,0,25,28                           ; Move in the new attribute bits
-                       rlwinm  r8,r5,31,2,25                           /* Line it up and check if empty */
-               
-                       beq+    avnophys                                        /* There's no PTE to invalidate... */
-                       
-                       xor             r8,r8,r6                                        /* Back hash to virt index */
-                       rlwimi  r9,r5,22,4,9                            /* Move in the API */
-                       lis             r12,HIGH_ADDR(EXT(tlb_system_lock))     /* Get the TLBIE lock */
-                       rlwinm  r5,r5,0,1,31                            /* Clear the valid bit */
-                       ori             r12,r12,LOW_ADDR(EXT(tlb_system_lock))  /* Grab up the bottom part */
-                       mfspr   r11,pvr                                         /* Find out what kind of machine we are */
-                       rlwimi  r9,r8,6,10,19                           /* Create the virtual address */
-                       rlwinm  r11,r11,16,16,31                        /* Isolate CPU type */
-                       stw             r5,0(r6)                                        /* Make the PTE invalid */              
-                       cmplwi  cr1,r11,3                                       /* Is this a 603? */
-                       sync                                                            /* Make sure the invalid is stored */
+hrmBlock64:    lis             r29,0xD000                                      ; Get shift to 32MB bsu                 
+                       rlwinm  r10,r20,mpBSub+1+2,29,29        ; Rotate to get 0 if 4K bsu or 13 if 32MB bsu
+                       lhz             r24,mpSpace(r31)                        ; Get the address space hash
+                       lhz             r25,mpBSize(r31)                        ; Get the number of pages in block
+                       lwz             r9,mpBlkRemCur(r31)                     ; Get our current remove position
+                       rlwnm   r29,r29,r10,28,31                       ; Rotate to get 0 or 13
+                       addi    r25,r25,1                                       ; Account for zero-based counting
+                       ori             r0,r20,mpRIP                            ; Turn on the remove in progress flag
+                       slw             r25,r25,r29                                     ; Adjust for 32MB if needed
+                       mfsdr1  r29                                                     ; Get the hash table base and size
+                       ld              r27,mpVAddr(r31)                        ; Get the base vaddr
+                       subi    r25,r25,1                                       ; Convert back to zero-based counting
+                       rlwinm  r5,r29,0,27,31                          ; Isolate the size
+                       sub             r4,r25,r9                                       ; Get number of pages left
+                       cmplw   cr1,r9,r25                                      ; Have we already hit the end?
+                       addi    r10,r9,mapRemChunk                      ; Point to the start of the next chunk
+                       addi    r2,r4,-mapRemChunk                      ; See if mapRemChunk or more
+                       stb             r0,mpFlags+3(r31)                       ; Save the flags with the mpRIP bit on
+                       srawi   r2,r2,31                                        ; We have -1 if less than mapRemChunk or 0 if equal or more
+                       subi    r4,r4,mapRemChunk-1                     ; Back off for a running start (will be negative for more than mapRemChunk)
+                       cmpwi   cr7,r2,0                                        ; Remember if we are doing the last chunk
+                       and             r4,r4,r2                                        ; If more than a chunk, bring this back to 0
+                       srdi    r27,r27,12                                      ; Change address into page index
+                       addi    r4,r4,mapRemChunk-1                     ; Add mapRemChunk-1 to get max(num left,  chunksize)
+                       add             r27,r27,r9                                      ; Adjust vaddr to start of current chunk
+                       
+                       bgt--   cr1,hrmEndInSight                       ; Someone is already doing the last hunk...
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       stw             r10,mpBlkRemCur(r31)            ; Set next chunk to do (note: this may indicate after end)
+                       bl              sxlkUnlock                                      ; Unlock the search list while we are invalidating
+                       
+                       rlwimi  r24,r24,14,4,17                         ; Insert a copy of space hash
+                       eqv             r26,r26,r26                                     ; Get all foxes here
+                       rldimi  r24,r24,28,8                            ; Make a couple copies up higher
+                       rldicr  r29,r29,0,47                            ; Isolate just the hash table base
+                       subfic  r5,r5,46                                        ; Get number of leading zeros
+                       srd             r26,r26,r5                                      ; Shift the size bits over              
+                       mr              r30,r27                                         ; Get start of chunk to invalidate
+                       rldicr  r26,r26,0,56                            ; Make length in PTEG units
+                       add             r22,r4,r30                                      ; Get end page number
+                                                                       
+hrmBInv64:     srdi    r0,r30,2                                        ; Shift page index over to form ESID
+                       rldicr  r0,r0,0,49                                      ; Clean all but segment portion
+                       rlwinm  r2,r30,0,16,31                          ; Get the current page index
+                       xor             r0,r0,r24                                       ; Form VSID
+                       xor             r8,r2,r0                                        ; Hash the vaddr
+                       sldi    r8,r8,7                                         ; Make into PTEG offset
+                       and             r23,r8,r26                                      ; Wrap into the hash table
+                       rlwinm  r3,r23,27,5,29                          ; Change to PCA offset (table is always 2GB or less so 32-bit instructions work here)
+                       subfic  r3,r3,-4                                        ; Get the PCA entry offset
+                       add             r7,r3,r29                                       ; Point to the PCA slot
+                       
+                       cmplw   cr5,r30,r22                                     ; Have we reached the end of the range?
+                                                               
+                       bl              mapLockPteg                                     ; Lock the PTEG
                                                
-tlbhangav:     lwarx   r11,0,r12                                       /* Get the TLBIE lock */
-                       rlwinm  r8,r6,29,29,31                          /* Get the bit position of entry */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       lis             r5,0x8000                                       /* Start up a bit mask */
-                       li              r11,1                                           /* Get our lock word */
-                       bne-    tlbhangav                                       /* It's locked, go wait... */
-                       stwcx.  r11,0,r12                                       /* Try to get it */
-                       bne-    tlbhangav                                       /* We was beat... */
-                       
-                       li              r11,0                                           /* Lock clear value */
+                       rlwinm. r4,r6,16,0,7                            ; Extract the block mappings in this here PTEG and see if there are any
+                       add             r5,r23,r29                                      ; Point to the PTEG
+                       li              r0,0                                            ; Set an invalid PTE value
+                       beq++   hrmBNone64                                      ; No block map PTEs in this PTEG...
+                       mtcrf   0x80,r4                                         ; Set CRs to select PTE slots
+                       mtcrf   0x40,r4                                         ; Set CRs to select PTE slots
 
-                       tlbie   r9                                                      /* Invalidate it everywhere */
-
-                       beq-    cr1,its603av                            /* It's a 603, skip the tlbsync... */
-                       
-                       eieio                                                           /* Make sure that the tlbie happens first */
-                       tlbsync                                                         /* wait for everyone to catch up */
-                       isync                                                           
-                       
-its603av:      stw             r11,0(r12)                                      /* Clear the lock */
-                       srw             r5,r5,r8                                        /* Make a "free slot" mask */
-                       sync                                                            /* Make sure of it all */
-
-                       lwz             r6,4(r6)                                        /* Get the latest reference and change bits */
-                       stw             r11,mmPTEent(r3)                        /* Clear the pointer to the PTE */
-                       rlwinm  r6,r6,0,23,24                           /* Extract the RC bits */
-                       lwz             r9,PCAallo(r7)                          /* Get the allocation control bits */
-                       rlwinm  r8,r5,24,8,15                           /* Make the autogen bit to turn off */
-                       lwz             r10,mmphysent(r3)                       ; Get any physical entry
-                       or              r9,r9,r5                                        /* Set the slot free */
-                       rlwimi  r8,r8,24,16,23                          /* Get lock bit mask to turn it off */
-                       andc    r9,r9,r8                                        /* Clear the auto and lock bits */
-                       mr.             r10,r10                                         ; Is there a physical entry?
-                       li              r5,pepte1                                       /* Get displacement to the second word of master pte */
-                       stw             r9,PCAallo(r7)                          /* Store the allocation controls */
-                       rlwimi  r2,r6,0,23,24                           ; Stick in RC bits
-                       beq-    avnophys                                        ; No physical entry...                  
-                       
-attrvmod:      lwarx   r11,r5,r10                                      /* Get the master copy */
-                       or              r11,r11,r6                                      /* Merge in latest RC */
-                       stwcx.  r11,r5,r10                                      /* Save it back */
-                       bne-    attrvmod                                        /* If it changed, try again... */
-                       
-avnophys:      li              r4,0                                            /* Get a 0 */
-                       stw             r2,mmPTEr(r3)                           ; Set the real part of the PTE
-
-                       sync                                                            ; Make sure that everything is updated
-
-                       stw             r4,0(r7)                                        /* Unlock the hash chain */
-                       
-                       rlwinm  r2,r2,0,0,19                            ; Clear back to page boundary
-                       
-attrflsh:      cmplwi  r4,(4096-32)                            ; Are we about to do the last line on page?
-                       dcbst   r2,r4                                           ; Flush cache because we changed attributes
-                       addi    r4,r4,32                                        ; Bump up cache
-                       blt+    attrflsh                                        ; Do the whole page...
-                       sync
 
-                       li              r4,0
-attrimvl:      cmplwi  r4,(4096-32)                            ; Are we about to do the last line on page?
-                       dcbi    r2,r4                                           ; Invalidate dcache because we changed attributes
-                       icbi    r2,r4                                           ; Invalidate icache because we changed attributes
-                       addi    r4,r4,32                                        ; Bump up cache
-                       blt+    attrimvl                                        ; Do the whole page...
-                       sync
+                       bf              0,hrmSlot0s                                     ; No autogen here
+                       std             r0,0x00(r5)                                     ; Invalidate PTE
 
-                       mtmsr   r0                                                      ; Restore interrupts and translation
-                       isync
+hrmSlot0s:     bf              1,hrmSlot1s                                     ; No autogen here
+                       std             r0,0x10(r5)                                     ; Invalidate PTE
 
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       li              r3,41
-                       bl              EXT(dbgLog2)                            
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Return... */
+hrmSlot1s:     bf              2,hrmSlot2s                                     ; No autogen here
+                       std             r0,0x20(r5)                                     ; Invalidate PTE
 
+hrmSlot2s:     bf              3,hrmSlot3s                                     ; No autogen here
+                       std             r0,0x30(r5)                                     ; Invalidate PTE
 
-/*
- *                     hw_pte_comm(physent) - Do something to the PTE pointing to a physical page
- *
- *                     Upon entry, R3 contains a pointer to a physical entry which is locked.
- *                     Note that this must be done with both interruptions off and VM off
- *
- *                     First, we set up CRs 5 and 7 to indicate which of the 7 calls this is.
- *
- *                     Now we scan the mappings to invalidate any with an active PTE.
- *
- *                             Acquire the lock on the PTEG hash list for the mapping being processed.
- *
- *                             If the current mapping has a PTE entry, we invalidate
- *                             it and merge the reference and change information into the phys_entry.
- *
- *                             Next, unlock the hash list and go on to the next mapping.
- *
- *     
- *                       
- */
+hrmSlot3s:     bf              4,hrmSlot4s                                     ; No autogen here
+                       std             r0,0x40(r5)                                     ; Invalidate PTE
 
-                       .align  5
-                       .globl  EXT(hw_inv_all)
+hrmSlot4s:     bf              5,hrmSlot5s                                     ; No autogen here
+                       std             r0,0x50(r5)                                     ; Invalidate PTE
 
-LEXT(hw_inv_all)
-       
-                       li              r9,0x800                                        /* Indicate invalidate all */
-                       li              r2,0                                            ; No inadvertant modifications please
-                       b               hw_pte_comm                                     /* Join in the fun... */
+hrmSlot5s:     bf              6,hrmSlot6s                                     ; No autogen here
+                       std             r0,0x60(r5)                                     ; Invalidate PTE
 
+hrmSlot6s:     bf              7,hrmSlot7s                                     ; No autogen here
+                       std             r0,0x70(r5)                                     ; Invalidate PTE
 
-                       .align  5
-                       .globl  EXT(hw_tst_mod)
+hrmSlot7s:     rlwinm  r0,r4,16,16,23                          ; Move in use to autogen
+                       or              r6,r6,r4                                        ; Flip on the free bits that corrospond to the autogens we cleared
+                       andc    r6,r6,r0                                        ; Turn off all the old autogen bits
 
-LEXT(hw_tst_mod)
+hrmBNone64:    eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock and set the PCA
 
-                       lwz             r8,pepte1(r3)                           ; Get the saved PTE image
-                       li              r9,0x400                                        /* Indicate test modify */
-                       li              r2,0                                            ; No inadvertant modifications please
-                       rlwinm. r8,r8,25,31,31                          ; Make change bit into return code
-                       beq+    hw_pte_comm                                     ; Assume we do not know if it is set...
-                       mr              r3,r8                                           ; Set the return code
-                       blr                                                                     ; Return quickly...
+                       addi    r30,r30,1                                       ; bump to the next PTEG
+                       bne++   cr5,hrmBInv64                           ; Go invalidate the next...
 
-                       .align  5
-                       .globl  EXT(hw_tst_ref)
+                       bge+    cr7,hrmDoneChunk                        ; We have not as yet done the last chunk, go tell our caller to call again...
 
-LEXT(hw_tst_ref)
-                       lwz             r8,pepte1(r3)                           ; Get the saved PTE image
-                       li              r9,0x200                                        /* Indicate test reference bit */
-                       li              r2,0                                            ; No inadvertant modifications please
-                       rlwinm. r8,r8,24,31,31                          ; Make reference bit into return code
-                       beq+    hw_pte_comm                                     ; Assume we do not know if it is set...
-                       mr              r3,r8                                           ; Set the return code
-                       blr                                                                     ; Return quickly...
+                       mr              r3,r31                                          ; Copy the pointer to the mapping
+                       bl              mapDrainBusy                            ; Go wait until we are sure all other removers are done with this one
 
-/*
- *                     Note that the following are all in one CR for ease of use later
- */
-                       .align  4
-                       .globl  EXT(hw_set_mod)
+                       sync                                                            ; Make sure memory is consistent
 
-LEXT(hw_set_mod)
+                       subi    r5,r25,255                                      ; Subtract TLB size from page count (note we are 0 based here)
+                       li              r6,255                                          ; Assume full invalidate for now
+                       srawi   r5,r5,31                                        ; Make 0 if we need a full purge, -1 otherwise
+                       andc    r6,r6,r5                                        ; Clear max if we have less to do
+                       and             r5,r25,r5                                       ; Clear count if we have more than max
+                       sldi    r24,r24,28                                      ; Get the full XOR value over to segment position
+                       ld              r27,mpVAddr(r31)                        ; Get the base vaddr
+                       li              r7,tlbieLock                            ; Get the TLBIE lock
+                       or              r5,r5,r6                                        ; Get number of TLBIEs needed           
                        
-                       li              r9,0x008                                        /* Indicate set modify bit */
-                       li              r2,0x4                                          ; Set set C, clear none
-                       b               hw_pte_comm                                     /* Join in the fun... */
-
-
-                       .align  4
-                       .globl  EXT(hw_clr_mod)
+hrmBTLBlcl:    lwarx   r2,0,r7                                         ; Get the TLBIE lock
+                       mr.             r2,r2                                           ; Is it locked?
+                       li              r2,1                                            ; Get our lock value
+                       bne--   hrmBTLBlcm                                      ; It is locked, go wait...
+                       stwcx.  r2,0,r7                                         ; Try to get it
+                       bne--   hrmBTLBlcl                                      ; We was beat...
+       
+hrmBTLBj:      sldi    r2,r27,maxAdrSpb                        ; Move to make room for address space ID
+                       rldicr  r2,r2,0,35-maxAdrSpb            ; Clear out the extra
+                       addic.  r5,r5,-1                                        ; See if we did them all
+                       xor             r2,r2,r24                                       ; Make the VSID
+                       rldimi  r2,r27,0,36                                     ; Insert the page portion of the VPN
+                       rldicl  r2,r2,0,16                                      ; Clear bits 0:15 cause they say we gotta
 
-LEXT(hw_clr_mod)
+                       tlbie   r2                                                      ; Invalidate it everywhere
+                       addi    r27,r27,0x1000                          ; Up to the next page
+                       bge++   hrmBTLBj                                        ; Make sure we have done it all...
                        
-                       li              r9,0x004                                        /* Indicate clear modify bit */
-                       li              r2,0x1                                          ; Set set none, clear C
-                       b               hw_pte_comm                                     /* Join in the fun... */
+                       eieio                                                           ; Make sure that the tlbie happens first
+                       tlbsync                                                         ; wait for everyone to catch up
 
+                       li              r2,0                                            ; Lock clear value
 
-                       .align  4
-                       .globl  EXT(hw_set_ref)
+                       ptesync                                                         ; Wait for quiet again
 
-LEXT(hw_set_ref)
+                       stw             r2,tlbieLock(0)                         ; Clear the tlbie lock
                        
-                       li              r9,0x002                                        /* Indicate set reference */
-                       li              r2,0x8                                          ; Set set R, clear none
-                       b               hw_pte_comm                                     /* Join in the fun... */
-
-                       .align  5
-                       .globl  EXT(hw_clr_ref)
-
-LEXT(hw_clr_ref)
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne-    hrmPanic                                        ; Nope...
                        
-                       li              r9,0x001                                        /* Indicate clear reference bit */
-                       li              r2,0x2                                          ; Set set none, clear R
-                       b               hw_pte_comm                                     /* Join in the fun... */
-
-
-/*
- *                     This is the common stuff.
- */
-
-                       .align  5
-
-hw_pte_comm:                                                                   /* Common routine for pte tests and manips */
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r7,r3
-                       lwz             r4,4(r3)
-                       mr              r5,r9                   
-                       li              r3,28
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r7
-                       mtlr    r11
-#endif
-                       mfsprg  r8,2                                            ; Get feature flags 
-                       lwz             r10,pephyslink(r3)                      /* Get the first mapping block */
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm. r10,r10,0,0,26                          ; Clear out the flags from first link and see if we are mapped
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r8                                         ; Set the features                      
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
-                       beq-    comnmap                                         ; No mapping
-                       dcbt    br0,r10                                         ; Touch the first mapping in before the isync
-                       
-comnmap:
-
-                       bt              pfNoMSRirb,hpcNoMSR                     ; No MSR...
-
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hpcNoMSRx
+                       lwz             r4,mpVAddr(r31)                         ; High order of address
+                       lwz             r5,mpVAddr+4(r31)                       ; Low order of address
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       mr              r29,r4                                          ; Save this in case we need it (only promote fails)
+                       mr              r30,r5                                          ; Save this in case we need it (only promote fails)
+                       bl              EXT(mapSearchFull)                      ; Go see if we can find it
                        
-hpcNoMSR:      
-                       mr              r5,r0
-                       mr              r7,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r7
-                       mr              r0,r5
-hpcNoMSRx:
+                       mr.             r3,r3                                           ; Did we? (And remember mapping address for later)
+                       mr              r15,r4                                          ; Save top of next vaddr
+                       mr              r16,r5                                          ; Save bottom of next vaddr
+                       beq-    hrmPanic                                        ; Nope, not found...
+                       
+                       cmpld   r3,r31                                          ; Same mapping?
+                       bne-    hrmPanic                                        ; Not good...
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkPromote                                     ; Try to promote shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       mr              r3,r31                                          ; Restore the mapping pointer
+                       beq+    hrmBDone2                                       ; Yeah...
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkConvert                                     ; Convert shared to exclusive
+                       mr.             r3,r3                                           ; Could we?
+                       bne--   hrmPanic                                        ; Nope, we must have timed out...
+                       
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       mr              r4,r29                                          ; High order of address
+                       mr              r5,r30                                          ; Low order of address
+                       bl              EXT(mapSearchFull)                      ; Rescan the list
+                       
+                       mr.             r3,r3                                           ; Did we lose it when we converted?
+                       mr              r15,r4                                          ; Save top of next vaddr
+                       mr              r16,r5                                          ; Save bottom of next vaddr
+                       beq--   hrmPanic                                        ; Yeah, we did, someone tossed it for us...
 
-                       mtcrf   0x05,r9                                         /* Set the call type flags into cr5 and 7 */
+hrmBDone2:     bl              mapDrainBusy                            ; Go wait until mapping is unused
 
-                       beq-    commdone                                        ; Nothing us mapped to this page...
-                       b               commnext                                        ; Jump to first pass (jump here so we can align loop)
+                       mr              r3,r28                                          ; Get the pmap to remove from
+                       mr              r4,r31                                          ; Point to the mapping
+                       bl              EXT(mapRemove)                          ; Remove the mapping from the list      
+                                       
+                       lwz             r4,pmapResidentCnt(r28)         ; Get the mapped page count 
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       subi    r4,r4,1                                         ; Drop down the mapped page count
+                       stw             r4,pmapResidentCnt(r28)         ; Set the mapped page count 
+                       bl              sxlkUnlock                                      ; Unlock the search list
                
-                       .align  5       
-
-commnext:      lwz             r11,mmnext(r10)                         ; Get the pointer to the next mapping (if any)
-                       lwz             r7,mmPTEhash(r10)                       /* Get pointer to hash list anchor */
-                       lwz             r5,mmPTEv(r10)                          /* Get the virtual address */
-                       mr.             r11,r11                                         ; More mappings to go?
-                       rlwinm  r7,r7,0,0,25                            /* Round hash list down to PCA boundary */
-                       beq-    commnxtch                                       ; No more mappings...
-                       dcbt    br0,r11                                         ; Touch the next mapping
-
-commnxtch:     li              r12,1                                           /* Get the locked value */
-
-commLck1:      lwarx   r11,0,r7                                        /* Get the PTEG lock */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       bne-    commLckw1                                       /* Yeah... */
-                       stwcx.  r12,0,r7                                        /* Try to take it */
-                       bne-    commLck1                                        /* Someone else was trying, try again... */
-                       b               commSXg1                                        /* All done... */
+                       b               hrmRetn64                                       ; We are all done, get out...
                        
-                       .align  4
+hrmBTLBlcm:    li              r2,lgKillResv                           ; Get space unreserve line
+                       stwcx.  r2,0,r2                                         ; Unreserve it
+                                               
+hrmBTLBlcn:    lwz             r2,0(r7)                                        ; Get the TLBIE lock
+                       mr.             r2,r2                                           ; Is it held?
+                       beq++   hrmBTLBlcl                                      ; Nope...
+                       b               hrmBTLBlcn                                      ; Yeah...
 
-commLckw1:     mr.             r11,r11                                         /* Check if it's already held */
-                       beq+    commLck1                                        /* It's clear... */
-                       lwz             r11,0(r7)                                       /* Get lock word again... */
-                       b               commLckw1                                       /* Wait... */
+;
+;                      Guest shadow assist -- mapping remove
+;
+;                      Method of operation:
+;                              o Locate the VMM extension block and the host pmap
+;                              o Obtain the host pmap's search lock exclusively
+;                              o Locate the requested mapping in the shadow hash table,
+;                                exit if not found
+;                              o If connected, disconnect the PTE and gather R&C to physent
+;                              o Locate and lock the physent
+;                              o Remove mapping from physent's chain
+;                              o Unlock physent
+;                              o Unlock pmap's search lock
+;
+;                      Non-volatile registers on entry:
+;                              r17: caller's msr image
+;                              r19: sprg2 (feature flags)
+;                              r28: guest pmap's physical address
+;                              r29: high-order 32 bits of guest virtual address
+;                              r30: low-order 32 bits of guest virtual address
+;
+;                      Non-volatile register usage:
+;                              r26: VMM extension block's physical address
+;                              r27: host pmap's physical address
+;                              r28: guest pmap's physical address
+;                              r29: physent's physical address
+;                              r30: guest virtual address
+;                              r31: guest mapping's physical address
+;
+                       .align  5                       
+hrmGuest:
+                       rlwinm  r30,r30,0,0xFFFFF000            ; Clean up low-order bits of 32-bit guest vaddr
+                       bt++    pf64Bitb,hrmG64                         ; Test for 64-bit machine
+                       lwz             r26,pmapVmmExtPhys+4(r28)       ; r26 <- VMM pmap extension block paddr
+                       lwz             r27,vmxHostPmapPhys+4(r26)      ; r27 <- host pmap's paddr
+                       b               hrmGStart                                       ; Join common code
+
+hrmG64:                ld              r26,pmapVmmExtPhys(r28)         ; r26 <- VMM pmap extension block paddr
+                       ld              r27,vmxHostPmapPhys(r26)        ; r27 <- host pmap's paddr
+                       rldimi  r30,r29,32,0                            ; Insert high-order 32 bits of 64-bit guest vaddr                       
+
+hrmGStart:     la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exclusive
+                       
+                       lwz             r3,vxsGrm(r26)                          ; Get mapping remove request count
+
+                       lwz             r9,pmapSpace(r28)                       ; r9 <- guest space ID number
+                       la              r31,VMX_HPIDX_OFFSET(r26)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r9,r11                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r12,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r12                                     ; r31 <- hash page index entry
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,hrmG64Search           ; Separate handling for 64-bit search
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+                                                                                               
+                       addi    r3,r3,1                                         ; Increment remove request count
+                       stw             r3,vxsGrm(r26)                          ; Update remove request count
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       b               hrmG32SrchLp                            ; Let the search begin!
+                       
+                       .align  5
+hrmG32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free mapping flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(free && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             hrmGSrchHit                                     ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    hrmG32SrchLp                            ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free mapping flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(free && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             hrmGSrchHit                                     ; Join common path on hit (r31 points to guest mapping)
+                       b               hrmGSrchMiss                            ; No joy in our hash group
+                       
+hrmG64Search:                  
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       b               hrmG64SrchLp                            ; Let the search begin!
                        
-                       .align  4
+                       .align  5
+hrmG64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free mapping flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(free && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             hrmGSrchHit                                     ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    hrmG64SrchLp                            ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free mapping flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(free && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             hrmGSrchHit                                     ; Join common path on hit (r31 points to guest mapping)
+hrmGSrchMiss:
+                       lwz             r3,vxsGrmMiss(r26)                      ; Get remove miss count
+                       li              r25,mapRtNotFnd                         ; Return not found
+                       addi    r3,r3,1                                         ; Increment miss count
+                       stw             r3,vxsGrmMiss(r26)                      ; Update miss count
+                       b               hrmGReturn                                      ; Join guest return
+
+                       .align  5                       
+hrmGSrchHit:
+                       rlwinm. r0,r6,0,mpgDormant                      ; Is this entry dormant?
+                       bne             hrmGDormant                                     ; Yes, nothing to disconnect
+                       
+                       lwz             r3,vxsGrmActive(r26)            ; Get active hit count
+                       addi    r3,r3,1                                         ; Increment active hit count
+                       stw             r3,vxsGrmActive(r26)            ; Update hit count
+                       
+                       bt++    pf64Bitb,hrmGDscon64            ; Handle 64-bit disconnect separately
+                       bl              mapInvPte32                                     ; Disconnect PTE, invalidate, gather ref and change
+                                                                                               ; r31 <- mapping's physical address
+                                                                                               ; r3  -> PTE slot physical address
+                                                                                               ; r4  -> High-order 32 bits of PTE
+                                                                                               ; r5  -> Low-order  32 bits of PTE
+                                                                                               ; r6  -> PCA
+                                                                                               ; r7  -> PCA physical address
+                       rlwinm  r2,r3,29,29,31                          ; Get PTE's slot number in the PTEG (8-byte PTEs)
+                       b               hrmGFreePTE                                     ; Join 64-bit path to release the PTE                   
+hrmGDscon64:
+                       bl              mapInvPte64                                     ; Disconnect PTE, invalidate, gather ref and change
+                       rlwinm  r2,r3,28,29,31                          ; Get PTE's slot number in the PTEG (16-byte PTEs)
+hrmGFreePTE:
+                       mr.             r3,r3                                           ; Was there a valid PTE?
+                       beq             hrmGDormant                                     ; No valid PTE, we're almost done
+                       lis             r0,0x8000                                       ; Prepare free bit for this slot
+                       srw             r0,r0,r2                                        ; Position free bit
+                       or              r6,r6,r0                                        ; Set it in our PCA image
+                       lwz             r8,mpPte(r31)                           ; Get PTE offset
+                       rlwinm  r8,r8,0,~mpHValid                       ; Make the offset invalid
+                       stw             r8,mpPte(r31)                           ; Save invalidated PTE offset
+                       eieio                                                           ; Synchronize all previous updates (mapInvPtexx didn't)
+                       stw             r6,0(r7)                                        ; Update PCA and unlock the PTEG
+
+hrmGDormant:
+                       lwz             r3,mpPAddr(r31)                         ; r3 <- physical 4K-page number
+                       bl              mapFindLockPN                           ; Find 'n' lock this page's physent
+                       mr.             r29,r3                                          ; Got lock on our physent?
+                       beq--   hrmGBadPLock                            ; No, time to bail out
+
+                       crset   cr1_eq                                          ; cr1_eq <- previous link is the anchor
+                       bt++    pf64Bitb,hrmGRemove64           ; Use 64-bit version on 64-bit machine
+                       la              r11,ppLink+4(r29)                       ; Point to chain anchor
+                       lwz             r9,ppLink+4(r29)                        ; Get chain anchor
+                       rlwinm. r9,r9,0,~ppFlags                        ; Remove flags, yielding 32-bit physical chain pointer
+hrmGRemLoop:
+                       beq-    hrmGPEMissMiss                          ; End of chain, this is not good
+                       cmplw   r9,r31                                          ; Is this the mapping to remove?
+                       lwz             r8,mpAlias+4(r9)                        ; Get forward chain pointer
+                       bne             hrmGRemNext                                     ; No, chain onward
+                       bt              cr1_eq,hrmGRemRetry                     ; Mapping to remove is chained from anchor
+                       stw             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               hrmGDelete                                      ; Finish deleting mapping
+hrmGRemRetry:
+                       lwarx   r0,0,r11                                        ; Get previous link
+                       rlwimi  r0,r8,0,~ppFlags                        ; Insert new forward pointer whilst preserving flags
+                       stwcx.  r0,0,r11                                        ; Update previous link
+                       bne-    hrmGRemRetry                            ; Lost reservation, retry
+                       b               hrmGDelete                                      ; Finish deleting mapping
+                       
+hrmGRemNext:
+                       la              r11,mpAlias+4(r9)                       ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               hrmGRemLoop                                     ; Carry on
+
+hrmGRemove64:
+                       li              r7,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r7,r7,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       la              r11,ppLink(r29)                         ; Point to chain anchor
+                       ld              r9,ppLink(r29)                          ; Get chain anchor
+                       andc.   r9,r9,r7                                        ; Remove flags, yielding 64-bit physical chain pointer
+hrmGRem64Lp:
+                       beq--   hrmGPEMissMiss                          ; End of chain, this is not good
+                       cmpld   r9,r31                                          ; Is this the mapping to remove?
+                       ld              r8,mpAlias(r9)                          ; Get forward chain pinter
+                       bne             hrmGRem64Nxt                            ; No mapping to remove, chain on, dude
+                       bt              cr1_eq,hrmGRem64Rt                      ; Mapping to remove is chained from anchor
+                       std             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               hrmGDelete                                      ; Finish deleting mapping
+hrmGRem64Rt:
+                       ldarx   r0,0,r11                                        ; Get previous link
+                       and             r0,r0,r7                                        ; Get flags
+                       or              r0,r0,r8                                        ; Insert new forward pointer
+                       stdcx.  r0,0,r11                                        ; Slam it back in
+                       bne--   hrmGRem64Rt                                     ; Lost reservation, retry
+                       b               hrmGDelete                                      ; Finish deleting mapping
+
+                       .align  5               
+hrmGRem64Nxt:
+                       la              r11,mpAlias(r9)                         ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               hrmGRem64Lp                                     ; Carry on
+                       
+hrmGDelete:
+                       mr              r3,r29                                          ; r3 <- physent addr
+                       bl              mapPhysUnlock                           ; Unlock physent chain
+                       lwz             r3,mpFlags(r31)                         ; Get mapping's flags
+                       rlwinm  r3,r3,0,~mpgFlags                       ; Clear all guest flags
+                       ori             r3,r3,mpgFree                           ; Mark mapping free
+                       stw             r3,mpFlags(r31)                         ; Update flags
+                       li              r25,mapRtGuest                          ; Set return code to 'found guest mapping'
+
+hrmGReturn:
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap search lock phys addr
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+                       
+                       mr              r3,r25                                          ; r3 <- return code
+                       bt++    pf64Bitb,hrmGRtn64                      ; Handle 64-bit separately
+                       mtmsr   r17                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       b               hrmRetnCmn                                      ; Nothing to do now but pop a frame and return
+hrmGRtn64:     mtmsrd  r17                                                     ; Restore 'rupts, translation, 32-bit mode
+                       b               hrmRetnCmn                                      ; Join common return
+
+hrmGBadPLock:
+hrmGPEMissMiss:
+                       lis             r0,hi16(Choke)                          ; Seen the arrow on the doorpost
+                       ori             r0,r0,lo16(Choke)                       ; Sayin' "THIS LAND IS CONDEMNED"
+                       li              r3,failMapping                          ; All the way from New Orleans
+                       sc                                                                      ; To Jeruselem
 
-commSXg1:      isync                                                           /* Make sure we haven't used anything yet */
 
-                       lwz             r6,mmPTEent(r10)                        /* Get the pointer to the PTE now that the lock's set */
+/*
+ *                     mapping *hw_purge_phys(physent) - remove a mapping from the system
+ *
+ *                     Upon entry, R3 contains a pointer to a physent.  
+ *
+ *                     This function removes the first mapping from a physical entry
+ *                     alias list.  It locks the list, extracts the vaddr and pmap from
+ *                     the first entry.  It then jumps into the hw_rem_map function.
+ *                     NOTE: since we jump into rem_map, we need to set up the stack
+ *                     identically.  Also, we set the next parm to 0 so we do not
+ *                     try to save a next vaddr.
+ *                     
+ *                     We return the virtual address of the removed mapping as a 
+ *                     R3.
+ *
+ *                     Note that this is designed to be called from 32-bit mode with a stack.
+ *
+ *                     We disable translation and all interruptions here.  This keeps is
+ *                     from having to worry about a deadlock due to having anything locked
+ *                     and needing it to process a fault.
+ *
+ *                     Note that this must be done with both interruptions off and VM off
+ *     
+ * 
+ * Remove mapping via physical page (mapping_purge)
+ * 
+ *  1) lock physent
+ *  2) extract vaddr and pmap
+ *  3) unlock physent
+ *  4) do "remove mapping via pmap"
+ *  
+ *     
+ */
 
-                       rlwinm  r9,r5,1,0,3                                     /* Move in the segment */
-                       mr.             r6,r6                                           /* See if there is a PTE entry here */
-                       rlwinm  r8,r5,31,2,25                           /* Line it up and check if empty */
+                       .align  5
+                       .globl  EXT(hw_purge_phys)
+
+LEXT(hw_purge_phys)
+                       stwu    r1,-(FM_ALIGN(hrmStackSize)+FM_SIZE)(r1)        ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r15,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r16,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r17,FM_ARG0+0x08(r1)            ; Save a register
+                       stw             r18,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r19,FM_ARG0+0x10(r1)            ; Save a register
+                       stw             r20,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r21,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r22,FM_ARG0+0x1C(r1)            ; Save a register
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save a register
+                       stw             r24,FM_ARG0+0x24(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x28(r1)            ; Save a register
+                       li              r6,0                                            ; Set no next address return
+                       stw             r26,FM_ARG0+0x2C(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x30(r1)            ; Save a register
+                       stw             r28,FM_ARG0+0x34(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x38(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x3C(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x40(r1)            ; Save a register
+                       stw             r6,FM_ARG0+0x44(r1)                     ; Save address to save next mapped vaddr
+                       stw             r0,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)      ; Save the return
+
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
+
+                       bl              mapPhysLock                                     ; Lock the physent
+                       
+                       bt++    pf64Bitb,hppSF                          ; skip if 64-bit (only they take the hint)
                
-                       beq+    commul                                          /* There's no PTE to invalidate... */
-                       
-                       xor             r8,r8,r6                                        /* Back hash to virt index */
-                       rlwimi  r9,r5,22,4,9                            /* Move in the API */
-                       lis             r12,HIGH_ADDR(EXT(tlb_system_lock))             /* Get the TLBIE lock */
-                       rlwinm  r5,r5,0,1,31                            /* Clear the valid bit */
-                       ori             r12,r12,LOW_ADDR(EXT(tlb_system_lock))  /* Grab up the bottom part */
-                       rlwimi  r9,r8,6,10,19                           /* Create the virtual address */
-
-                       stw             r5,0(r6)                                        /* Make the PTE invalid */              
-                       mfspr   r4,pvr                                          /* Find out what kind of machine we are */
-                       sync                                                            /* Make sure the invalid is stored */
-                                               
-tlbhangco:     lwarx   r11,0,r12                                       /* Get the TLBIE lock */
-                       rlwinm  r8,r6,29,29,31                          /* Get the bit position of entry */
-                       mr.             r11,r11                                         /* Is it locked? */
-                       lis             r5,0x8000                                       /* Start up a bit mask */
-                       li              r11,1                                           /* Get our lock word */
-                       bne-    tlbhangco                                       /* It's locked, go wait... */
-                       stwcx.  r11,0,r12                                       /* Try to get it */
-                       bne-    tlbhangco                                       /* We was beat... */
+                       lwz             r12,ppLink+4(r3)                        ; Grab the pointer to the first mapping
+                       li              r0,ppFlags                                      ; Set the bottom stuff to clear
+                       b               hppJoin                                         ; Join the common...
+                       
+hppSF:         li              r0,ppLFAmask
+                       ld              r12,ppLink(r3)                          ; Get the pointer to the first mapping
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+
+hppJoin:       andc.   r12,r12,r0                                      ; Clean and test link
+                       beq--   hppNone                                         ; There are no more mappings on physical page
+                       
+                       lis             r28,hi16(EXT(pmapTrans))        ; Get the top of the start of the pmap hash to pmap translate table
+                       lhz             r7,mpSpace(r12)                 ; Get the address space hash
+                       ori             r28,r28,lo16(EXT(pmapTrans))    ; Get the top of the start of the pmap hash to pmap translate table
+                       slwi    r0,r7,2                                         ; Multiply space by 4
+                       lwz             r4,mpVAddr(r12)                         ; Get the top of the vaddr
+                       slwi    r7,r7,3                                         ; Multiply space by 8
+                       lwz             r5,mpVAddr+4(r12)                       ; and the bottom
+                       add             r7,r7,r0                                        ; Get correct displacement into translate table
+                       lwz             r28,0(r28)                                      ; Get the actual translation map
+       
+                       add             r28,r28,r7                                      ; Point to the pmap translation
+                                       
+                       bl              mapPhysUnlock                           ; Time to unlock the physical entry
                        
-                       rlwinm  r4,r4,16,16,31                          /* Isolate CPU type */
-                       li              r11,0                                           /* Lock clear value */
-                       cmplwi  r4,3                                            /* Is this a 603? */
-
-                       tlbie   r9                                                      /* Invalidate it everywhere */
-
-                       beq-    its603co                                        /* It's a 603, skip the tlbsync... */
+                       bt++    pf64Bitb,hppSF2                         ; skip if 64-bit (only they take the hint)
                        
-                       eieio                                                           /* Make sure that the tlbie happens first */
-                       tlbsync                                                         /* wait for everyone to catch up */
-                       isync                                                           
+                       lwz             r28,pmapPAddr+4(r28)            ; Get the physical address of the pmap
+                       b               hrmJoin                                         ; Go remove the mapping...
                        
-its603co:      stw             r11,0(r12)                                      /* Clear the lock */
-                       srw             r5,r5,r8                                        /* Make a "free slot" mask */
-                       sync                                                            /* Make sure of it all */
+hppSF2:                ld              r28,pmapPAddr(r28)                      ; Get the physical address of the pmap
+                       b               hrmJoin                                         ; Go remove the mapping...
 
-                       lwz             r6,4(r6)                                        /* Get the latest reference and change bits */
-                       lwz             r9,PCAallo(r7)                          /* Get the allocation control bits */
-                       stw             r11,mmPTEent(r10)                       /* Clear the pointer to the PTE */
-                       rlwinm  r8,r5,24,8,15                           /* Make the autogen bit to turn off */
-                       or              r9,r9,r5                                        /* Set the slot free */
-                       rlwimi  r8,r8,24,16,23                          /* Get lock bit mask to turn it off */
-                       rlwinm  r4,r6,0,23,24                           /* Extract the RC bits */
-                       andc    r9,r9,r8                                        /* Clear the auto and lock bits */
-                       li              r5,pepte1                                       /* Get displacement to the second word of master pte */
-                       stw             r9,PCAallo(r7)                          /* Store the allocation controls */
+                       .align  5
                        
-commmod:       lwarx   r11,r5,r3                                       /* Get the master copy */
-                       or              r11,r11,r4                                      /* Merge in latest RC */
-                       stwcx.  r11,r5,r3                                       /* Save it back */
-                       bne-    commmod                                         /* If it changed, try again... */
-                       b               commulnl                                        ; Skip loading the old real part...
+hppNone:       bl              mapPhysUnlock                           ; Time to unlock the physical entry
 
-commul:                lwz             r6,mmPTEr(r10)                          ; Get the real part
-
-commulnl:      rlwinm  r12,r2,5,23,24                          ; Get the "set" bits
-                       rlwinm  r11,r2,7,23,24                          ; Get the "clear" bits
-                       
-                       or              r6,r6,r12                                       ; Set the bits to come on
-                       andc    r6,r6,r11                                       ; Clear those to come off
+                       bt++    pf64Bitb,hppSF3                         ; skip if 64-bit (only they take the hint)...
 
-                       stw             r6,mmPTEr(r10)                          ; Set the new RC
+                       mtmsr   r11                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               hppRetnCmn                                      ; Join the common return code...
 
-                       lwz             r10,mmnext(r10)                         /* Get the next */
-                       li              r4,0                                            /* Make sure this is 0 */
-                       mr.             r10,r10                                         ; Is there another mapping?
+hppSF3:                mtmsrd  r11                                                     ; Restore enables/translation/etc.
+                       isync
 
-                       sync                                                            ; Make sure that all is saved
+;
+;                      NOTE: we have not used any registers other than the volatiles to this point
+;
 
-                       stw             r4,0(r7)                                        /* Unlock the hash chain */
-                       bne+    commnext                                        ; Go get the next if there is one...
-                       
-/*
- *                     Now that all PTEs have been invalidated and the master RC bits are updated,
- *                     we go ahead and figure out what the original call was and do that.  Note that
- *                     another processor could be messing around and may have entered one of the 
- *                     PTEs we just removed into the hash table.  Too bad...  You takes yer chances.
- *                     If there's a problem with that, it's because some higher level was trying to
- *                     do something with a mapping that it shouldn't.  So, the problem's really
- *                     there, nyaaa, nyaaa, nyaaa... nyaaa, nyaaa... nyaaa! So there!
- */
+hppRetnCmn:    lwz             r12,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)     ; Restore the return
 
-commdone:      li              r5,pepte1                                       /* Get displacement to the second word of master pte */
-                       blt             cr5,commfini                            /* We're finished, it was invalidate all... */
-                       bgt             cr5,commtst                                     /* It was a test modified... */
-                       beq             cr5,commtst                                     /* It was a test reference... */
+                       li              r3,mapRtEmpty                           ; Physent chain is empty
+                       mtlr    r12                                                     ; Restore the return
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
 
 /*
- *                     Note that we need to to do the interlocked update here because another processor
- *                     can be updating the reference and change bits even though the physical entry
- *                     is locked.  All modifications to the PTE portion of the physical entry must be
- *                     done via interlocked update.
+ *                     mapping *hw_purge_map(pmap, vaddr, addr64_t *next) - remove a mapping from the system.
+ *
+ *                     Upon entry, R3 contains a pointer to a pmap.  Since vaddr is
+ *                     a 64-bit quantity, it is a long long so it is in R4 and R5.
+ *                     
+ *                     We return the virtual address of the removed mapping as a 
+ *                     R3.
+ *
+ *                     Note that this is designed to be called from 32-bit mode with a stack.
+ *
+ *                     We disable translation and all interruptions here.  This keeps is
+ *                     from having to worry about a deadlock due to having anything locked
+ *                     and needing it to process a fault.
+ *
+ *                     Note that this must be done with both interruptions off and VM off
+ *     
+ *  Remove a mapping which can be reestablished by VM
+ *
  */
 
-                       rlwinm  r12,r2,5,23,24                          ; Get the "set" bits
-                       rlwinm  r11,r2,7,23,24                          ; Get the "clear" bits
-
-commcng:       lwarx   r8,r5,r3                                        /* Get the master copy */
-                       or              r8,r8,r12                                       ; Set the bits to come on
-                       andc    r8,r8,r11                                       ; Clear those to come off
-                       stwcx.  r8,r5,r3                                        /* Save it back */
-                       bne-    commcng                                         /* If it changed, try again... */
-
-                       mtmsr   r0                                                      /* Interrupts and translation back on */
-                       isync
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,29
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Return... */
-
-                       .align  4
-
-commtst:       lwz             r8,pepte1(r3)                           /* Get the PTE */
-                       bne-    cr5,commtcb                                     ; This is for the change bit...
-                       mtmsr   r0                                                      ; Interrupts and translation back on
-                       rlwinm  r3,r8,24,31,31                          ; Copy reference bit to bit 31
-                       isync                                                           ; Toss prefetching
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,29
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
+                       .align  5
+                       .globl  EXT(hw_purge_map)
+
+LEXT(hw_purge_map)
+                       stwu    r1,-(FM_ALIGN(hrmStackSize)+FM_SIZE)(r1)        ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r15,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r16,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r17,FM_ARG0+0x08(r1)            ; Save a register
+                       stw             r18,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r19,FM_ARG0+0x10(r1)            ; Save a register
+                       mfsprg  r19,2                                           ; Get feature flags 
+                       stw             r20,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r21,FM_ARG0+0x18(r1)            ; Save a register
+                       mtcrf   0x02,r19                                        ; move pf64Bit cr6
+                       stw             r22,FM_ARG0+0x1C(r1)            ; Save a register
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save a register
+                       stw             r24,FM_ARG0+0x24(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x28(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x2C(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x30(r1)            ; Save a register
+                       stw             r28,FM_ARG0+0x34(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x38(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x3C(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x40(r1)            ; Save a register
+                       stw             r6,FM_ARG0+0x44(r1)                     ; Save address to save next mapped vaddr
+                       stw             r0,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)      ; Save the return
+
+#if DEBUG
+                       lwz             r11,pmapFlags(r3)                       ; Get pmaps flags
+                       rlwinm. r11,r11,0,pmapVMgsaa            ; Is guest shadow assist active? 
+                       bne             hpmPanic                                        ; Call not valid for guest shadow assist pmap
 #endif
-                       blr                                                                     ; Return...
+                       
+                       bt++    pf64Bitb,hpmSF1                         ; skip if 64-bit (only they take the hint)
+                       lwz             r9,pmapvr+4(r3)                         ; Get conversion mask
+                       b               hpmSF1x                                         ; Done...
+                       
+hpmSF1:                ld              r9,pmapvr(r3)                           ; Get conversion mask
 
-                       .align  4
+hpmSF1x:       
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
 
-commtcb:       rlwinm  r3,r8,25,31,31                          ; Copy change bit to bit 31
+                       xor             r28,r3,r9                                       ; Convert the pmap to physical addressing
 
-commfini:      mtmsr   r0                                                      ; Interrupts and translation back on
-                       isync                                                           ; Toss prefetching
+                       mr              r17,r11                                         ; Save the MSR
 
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,29
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       blr                                                                     ; Return...
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkExclusive                           ; Go get an exclusive lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne--   hrmBadLock                                      ; Nope...
+;
+;                      Note that we do a full search (i.e., no shortcut level skips, etc.)
+;                      here so that we will know the previous elements so we can dequeue them
+;                      later.
+;
+hpmSearch:
+                       mr              r3,r28                                          ; Pass in pmap to search
+                       mr              r29,r4                                          ; Top half of vaddr
+                       mr              r30,r5                                          ; Bottom half of vaddr
+                       bl              EXT(mapSearchFull)                      ; Rescan the list
+                       mr.             r31,r3                                          ; Did we? (And remember mapping address for later)
+                       or              r0,r4,r5                                        ; Are we beyond the end?
+                       mr              r15,r4                                          ; Save top of next vaddr
+                       cmplwi  cr1,r0,0                                        ; See if there is another
+                       mr              r16,r5                                          ; Save bottom of next vaddr
+                       bne--   hpmGotOne                                       ; We found one, go check it out...
+
+hpmCNext:      bne++   cr1,hpmSearch                           ; There is another to check...
+                       b               hrmNotFound                                     ; No more in pmap to check...
+
+hpmGotOne:     lwz             r20,mpFlags(r3)                         ; Get the flags
+                       andi.   r0,r20,lo16(mpType|mpPerm)      ; cr0_eq <- normal mapping && !permanent
+                       rlwinm  r21,r20,8,24,31                         ; Extract the busy count
+                       cmplwi  cr2,r21,0                                       ; Is it busy?
+                       crand   cr0_eq,cr2_eq,cr0_eq            ; not busy and can be removed?
+                       beq++   hrmGotX                                         ; Found, branch to remove the mapping...
+                       b               hpmCNext                                        ; Nope...
+
+hpmPanic:      lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
 
 /*
- *                     unsigned int hw_test_rc(mapping *mp, boolean_t reset);
+ *                     mapping *hw_purge_space(physent, pmap) - remove a mapping from the system based upon address space
+ *
+ *                     Upon entry, R3 contains a pointer to a pmap.  
+ *                     pa is a pointer to the physent
  *
- *                     Test the RC bits for a specific mapping.  If reset is non-zero, clear them.
- *                     We return the RC value in the mapping if there is no PTE or if C is set.
- *                     (Note: R is always set with C.) Otherwise we invalidate the PTE and
- *                     collect the RC bits from there, also merging them into the global copy.
+ *                     This function removes the first mapping for a specific pmap from a physical entry
+ *                     alias list.  It locks the list, extracts the vaddr and pmap from
+ *                     the first apporpriate entry.  It then jumps into the hw_rem_map function.
+ *                     NOTE: since we jump into rem_map, we need to set up the stack
+ *                     identically.  Also, we set the next parm to 0 so we do not
+ *                     try to save a next vaddr.
  *                     
- *                     For now, we release the PTE slot and leave it invalid.  In the future, we
- *                     may consider re-validating and not releasing the slot.  It would be faster,
- *                     but our current implementation says that we will have not PTEs valid
- *                     without the reference bit set.
+ *                     We return the virtual address of the removed mapping as a 
+ *                     R3.
  *
- *                     We will special case C==1 && not reset to just return the RC.
+ *                     Note that this is designed to be called from 32-bit mode with a stack.
  *
- *                     Probable state is worst performance state: C bit is off and there is a PTE.
+ *                     We disable translation and all interruptions here.  This keeps is
+ *                     from having to worry about a deadlock due to having anything locked
+ *                     and needing it to process a fault.
+ *
+ *                     Note that this must be done with both interruptions off and VM off
+ *     
+ * 
+ * Remove mapping via physical page (mapping_purge)
+ * 
+ *  1) lock physent
+ *  2) extract vaddr and pmap
+ *  3) unlock physent
+ *  4) do "remove mapping via pmap"
+ *  
+ *     
  */
 
-#define                htrReset 31
-
                        .align  5
-                       .globl  EXT(hw_test_rc)
+                       .globl  EXT(hw_purge_space)
+
+LEXT(hw_purge_space)
+                       stwu    r1,-(FM_ALIGN(hrmStackSize)+FM_SIZE)(r1)        ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r15,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r16,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r17,FM_ARG0+0x08(r1)            ; Save a register
+                       mfsprg  r2,2                                            ; Get feature flags 
+                       stw             r18,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r19,FM_ARG0+0x10(r1)            ; Save a register
+                       stw             r20,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r21,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r22,FM_ARG0+0x1C(r1)            ; Save a register
+                       mtcrf   0x02,r2                                         ; move pf64Bit cr6
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save a register
+                       stw             r24,FM_ARG0+0x24(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x28(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x2C(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x30(r1)            ; Save a register
+                       li              r6,0                                            ; Set no next address return
+                       stw             r28,FM_ARG0+0x34(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x38(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x3C(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x40(r1)            ; Save a register
+                       stw             r6,FM_ARG0+0x44(r1)                     ; Save address to save next mapped vaddr
+                       stw             r0,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)      ; Save the return
+
+#if DEBUG
+                       lwz             r11,pmapFlags(r4)                       ; Get pmaps flags
+                       rlwinm. r11,r11,0,pmapVMgsaa            ; Is guest shadow assist active? 
+                       bne             hpsPanic                                        ; Call not valid for guest shadow assist pmap
+#endif
+                       
+                       bt++    pf64Bitb,hpsSF1                         ; skip if 64-bit (only they take the hint)
 
-LEXT(hw_test_rc)
+                       lwz             r9,pmapvr+4(r4)                         ; Get conversion mask for pmap
 
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       mfmsr   r0                                                      ; Save the MSR 
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       mr.             r4,r4                                           ; See if we have a reset to do later
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      ; Clear interruption mask
-                       crnot   htrReset,cr0_eq                         ; Remember reset
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       rlwinm  r12,r12,0,28,25                         ; Clear IR and DR
+                       b               hpsSF1x                                         ; Done...
                        
-                       bt              pfNoMSRirb,htrNoMSR                     ; No MSR...
+hpsSF1:                ld              r9,pmapvr(r4)                           ; Get conversion mask for pmap
 
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               htrNoMSRx
-                       
-htrNoMSR:      
-                       mr              r2,r0
-                       mr              r7,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r7
-                       mr              r0,r2
-htrNoMSRx:
+hpsSF1x:       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
                        
-                       lwz             r2,mmPTEr(r3)                           ; Get the real part
-                       lwz             r7,mmPTEhash(r3)                        ; Get pointer to hash list anchor
-                       rlwinm. r12,r2,0,24,24                          ; Is the change bit on?
-                       lwz             r5,mmPTEv(r3)                           ; Get the virtual address
-                       crnor   cr0_eq,cr0_eq,htrReset          ; Set if C=1 && not reset
-                       rlwinm  r7,r7,0,0,25                            ; Round hash list down to PCA boundary 
-                       bt              cr0_eq,htrcset                          ; Special case changed but no reset case...
-
-                       li              r12,1                                           ; Get the locked value
+                       xor             r4,r4,r9                                        ; Convert the pmap to physical addressing
 
-htrLck1:       lwarx   r11,0,r7                                        ; Get the PTEG lock
-                       mr.             r11,r11                                         ; Is it locked?
-                       bne-    htrLckw1                                        ; Yeah...
-                       stwcx.  r12,0,r7                                        ; Try to take it
-                       bne-    htrLck1                                         ; Someone else was trying, try again...
-                       b               htrSXg1                                         ; All done...
+                       bl              mapPhysLock                                     ; Lock the physent
+                        
+                       lwz             r8,pmapSpace(r4)                        ; Get the space hash
+                       bt++    pf64Bitb,hpsSF                          ; skip if 64-bit (only they take the hint)
+               
+                       lwz             r12,ppLink+4(r3)                        ; Grab the pointer to the first mapping
                        
-                       .align  4
-
-htrLckw1:      mr.             r11,r11                                         ; Check if it is already held 
-                       beq+    htrLck1                                         ; It is clear... 
-                       lwz             r11,0(r7)                                       ; Get lock word again... 
-                       b               htrLckw1                                        ; Wait... 
+hpsSrc32:      rlwinm. r12,r12,0,~ppFlags                      ; Clean and test mapping address
+                       beq             hpsNone                                         ; Did not find one...
                        
-                       .align  4
-
-htrSXg1:       isync                                                           ; Make sure we have not used anything yet
-
-                       lwz             r6,mmPTEent(r3)                         ; Get the pointer to the PTE now that the lock is set
-                       lwz             r2,mmPTEr(r3)                           ; Get the mapping copy of the real part
+                       lhz             r10,mpSpace(r12)                        ; Get the space
+                       
+                       cmplw   r10,r8                                          ; Is this one of ours?
+                       beq             hpsFnd                                          ; Yes...
+                       
+                       lwz             r12,mpAlias+4(r12)                      ; Chain on to the next
+                       b               hpsSrc32                                        ; Check it out...
 
-                       rlwinm  r9,r5,1,0,3                                     ; Move in the segment
-                       mr.             r6,r6                                           ; Any PTE to invalidate?
-                       rlwinm  r8,r5,31,2,25                           ; Line it up 
+                       .align  5
                
-                       beq+    htrnopte                                        ; There is no PTE to invalidate...
-                       
-                       xor             r8,r8,r6                                        ; Back hash to virt index
-                       rlwimi  r9,r5,22,4,9                            ; Move in the API
-                       lis             r12,HIGH_ADDR(EXT(tlb_system_lock))     ; Get the TLBIE lock
-                       rlwinm  r5,r5,0,1,31                            ; Clear the valid bit
-                       ori             r12,r12,LOW_ADDR(EXT(tlb_system_lock))  ; Grab up the bottom part
-                       mfspr   r11,pvr                                         ; Find out what kind of machine we are
-                       rlwimi  r9,r8,6,10,19                           ; Create the virtual address
-                       rlwinm  r11,r11,16,16,31                        ; Isolate CPU type 
-
-                       stw             r5,0(r6)                                        ; Make the PTE invalid  
-                       cmplwi  cr1,r11,3                                       ; Is this a 603?
-                       sync                                                            ; Make sure the invalid is stored
-                                               
-htrtlbhang:    lwarx   r11,0,r12                                       ; Get the TLBIE lock
-                       rlwinm  r8,r6,29,29,31                          ; Get the bit position of entry 
-                       mr.             r11,r11                                         ; Is it locked?
-                       lis             r5,0x8000                                       ; Start up a bit mask
-                       li              r11,1                                           ; Get our lock word 
-                       bne-    htrtlbhang                                      ; It is locked, go wait...
-                       stwcx.  r11,0,r12                                       ; Try to get it
-                       bne-    htrtlbhang                                      ; We was beat...
+hpsSF:         li              r0,ppLFAmask
+                       ld              r12,ppLink(r3)                          ; Get the pointer to the first mapping
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
                        
-                       li              r11,0                                           ; Lock clear value 
-
-                       tlbie   r9                                                      ;Invalidate it everywhere
-
-                       beq-    cr1,htr603                                      ; It is a 603, skip the tlbsync... 
+hpsSrc64:      andc.   r12,r12,r0                                      ; Clean and test mapping address
+                       beq             hpsNone                                         ; Did not find one...
                        
-                       eieio                                                           ; Make sure that the tlbie happens first
-                       tlbsync                                                         ; wait for everyone to catch up
-                       isync                                                           
+                       lhz             r10,mpSpace(r12)                        ; Get the space
                        
-htr603:                stw             r11,0(r12)                                      ; Clear the lock
-                       srw             r5,r5,r8                                        ; Make a "free slot" mask 
-                       sync                                                            ; Make sure of it all 
-
-                       lwz             r6,4(r6)                                        ; Get the latest reference and change bits
-                       stw             r11,mmPTEent(r3)                        ; Clear the pointer to the PTE 
-                       rlwinm  r6,r6,0,23,24                           ; Extract the RC bits 
-                       lwz             r9,PCAallo(r7)                          ; Get the allocation control bits 
-                       rlwinm  r8,r5,24,8,15                           ; Make the autogen bit to turn off
-                       lwz             r10,mmphysent(r3)                       ; Get any physical entry
-                       or              r9,r9,r5                                        ; Set the slot free 
-                       rlwimi  r8,r8,24,16,23                          ; Get lock bit mask to turn it off
-                       andc    r9,r9,r8                                        ; Clear the auto and lock bits 
-                       mr.             r10,r10                                         ; Is there a physical entry?
-                       li              r5,pepte1                                       ; Get displacement to the second word of master pte
-                       stw             r9,PCAallo(r7)                          ; Store the allocation controls
-                       rlwimi  r2,r6,0,23,24                           ; Stick in RC bits
-                       beq-    htrnopte                                        ; No physical entry...
-                       
-htrmrc:                lwarx   r11,r5,r10                                      ; Get the master copy
-                       or              r11,r11,r6                                      ; Merge in latest RC
-                       stwcx.  r11,r5,r10                                      ; Save it back
-                       bne-    htrmrc                                          ; If it changed, try again... 
-
-htrnopte:      rlwinm  r5,r2,25,30,31                          ; Position RC and mask off
-                       bf              htrReset,htrnorst                       ; No reset to do...
-                       rlwinm  r2,r2,0,25,22                           ; Clear the RC if requested
-                       
-htrnorst:      li              r4,0                                            ; Get a 0 
-                       stw             r2,mmPTEr(r3)                           ; Set the real part of the PTE
-                       
-                       sync                                                            ; Make sure that stuff is all stored
-
-                       stw             r4,0(r7)                                        ; Unlock the hash chain
-       
-                       mr              r3,r5                                           ; Get the old RC to pass back
-                       mtmsr   r0                                                      ; Restore interrupts and translation
-                       isync
-                       blr                                                                     ; Return...
+                       cmplw   r10,r8                                          ; Is this one of ours?
+                       beq             hpsFnd                                          ; Yes...
+                       
+                       ld              r12,mpAlias(r12)                        ; Chain on to the next
+                       b               hpsSrc64                                        ; Check it out...
+                       
+                       .align  5
+                       
+hpsFnd:                mr              r28,r4                                          ; Set the pmap physical address
+                       lwz             r4,mpVAddr(r12)                         ; Get the top of the vaddr
+                       lwz             r5,mpVAddr+4(r12)                       ; and the bottom
+                       
+                       bl              mapPhysUnlock                           ; Time to unlock the physical entry
+                       b               hrmJoin                                         ; Go remove the mapping...
+                       
+                       .align  5
+                       
+hpsNone:       bl              mapPhysUnlock                           ; Time to unlock the physical entry
 
-                       .align  4
+                       bt++    pf64Bitb,hpsSF3                         ; skip if 64-bit (only they take the hint)...
 
-htrcset:       rlwinm  r3,r2,25,30,31                          ; Position RC and mask off
-                       mtmsr   r0                                                      ; Restore interrupts and translation
+                       mtmsr   r11                                                     ; Restore enables/translation/etc.
                        isync
-                       blr                                                                     ; Return...
+                       b               hpsRetnCmn                                      ; Join the common return code...
 
+hpsSF3:                mtmsrd  r11                                                     ; Restore enables/translation/etc.
+                       isync
 
-/*
- *                     hw_phys_attr(struct phys_entry *pp, vm_prot_t prot, unsigned int wimg) - Sets the default physical page attributes
- *
- *                     Note that this must be done with both interruptions off and VM off
- *                     Move the passed in attributes into the pte image in the phys entry
- *     
- *                       
- */
+;
+;                      NOTE: we have not used any registers other than the volatiles to this point
+;
 
-                       .align  5
-                       .globl  EXT(hw_phys_attr)
+hpsRetnCmn:    lwz             r12,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)     ; Restore the return
 
-LEXT(hw_phys_attr)
+                       li              r3,mapRtEmpty                           ; No mappings for specified pmap on physent chain
+                       mtlr    r12                                                     ; Restore the return
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
 
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r8,r3
-                       mr              r7,r5
-                       mr              r5,r4
-//                     lwz             r4,4(r3)
-                       li              r4,0x1111
-                       li              r3,30
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r8
-                       mr              r4,r5
-                       mr              r5,r7
-                       mtlr    r11
-#endif
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       andi.   r5,r5,0x0078                            /* Clean up the WIMG */
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       rlwimi  r5,r4,0,30,31                           /* Move the protection into the wimg register */
-                       la              r6,pepte1(r3)                           /* Point to the default pte */
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
-
-                       bt              pfNoMSRirb,hpaNoMSR                     ; No MSR...
-
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hpaNoMSRx
+hpsPanic:      lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
                        
-hpaNoMSR:      
-                       mr              r10,r0
-                       mr              r4,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r4
-                       mr              r0,r10
-hpaNoMSRx:
-
-atmattr:       lwarx   r10,0,r6                                        /* Get the pte */
-                       rlwimi  r10,r5,0,25,31                          /* Move in the new attributes */
-                       stwcx.  r10,0,r6                                        /* Try it on for size */
-                       bne-    atmattr                                         /* Someone else was trying, try again... */
-               
-                       mtmsr   r0                                                      /* Interrupts and translation back on */
-                       isync
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r10
-                       li              r3,31
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mtlr    r11
-#endif
-                       blr                                                                     /* All done... */
-
-
-
 /*
- *                     handlePF - handle a page fault interruption
+ *                     mapping *hw_scrub_guest(physent, pmap) - remove first guest mapping associated with host
+ *                                                    on this physent chain
+ *
+ *                     Locates the first guest mapping on the physent chain that is associated with the
+ *                     specified host pmap. If this succeeds, the mapping is removed by joining the general
+ *                     remove path; otherwise, we return NULL. The caller is expected to invoke this entry
+ *                     repeatedly until no additional guest mappings that match our criteria are removed.
  *
- *                     If the fault can be handled, this routine will RFI directly,
- *                     otherwise it will return with all registers as in entry.
+ *                     Because this entry point exits through hw_rem_map, our prolog pushes its frame.
  *
- *                     Upon entry, state and all registers have been saved in savearea.
- *                     This is pointed to by R13.
- *                     IR and DR are off, interrupts are masked,
- *                     Floating point be disabled.
- *                     R3 is the interrupt code.
+ *                     Parameters:
+ *                             r3 : physent, 32-bit kernel virtual address
+ *                             r4 : host pmap, 32-bit kernel virtual address
  *
- *                     If we bail, we must restore cr5, and all registers except 6 and
- *                     3.
+ *                     Volatile register usage (for linkage through hrmJoin):
+ *                             r4 : high-order 32 bits of guest virtual address
+ *                             r5 : low-order 32 bits of guest virtual address
+ *                             r11: saved MSR image
  *
+ *                     Non-volatile register usage:
+ *                             r26: VMM extension block's physical address
+ *                             r27: host pmap's physical address
+ *                             r28: guest pmap's physical address
+ *     
  */
-       
+
                        .align  5
-                       .globl  EXT(handlePF)
+                       .globl  EXT(hw_scrub_guest)
+
+LEXT(hw_scrub_guest)
+                       stwu    r1,-(FM_ALIGN(hrmStackSize)+FM_SIZE)(r1)        ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r15,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r16,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r17,FM_ARG0+0x08(r1)            ; Save a register
+                       mfsprg  r2,2                                            ; Get feature flags 
+                       stw             r18,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r19,FM_ARG0+0x10(r1)            ; Save a register
+                       stw             r20,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r21,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r22,FM_ARG0+0x1C(r1)            ; Save a register
+                       mtcrf   0x02,r2                                         ; move pf64Bit cr6
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save a register
+                       stw             r24,FM_ARG0+0x24(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x28(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x2C(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x30(r1)            ; Save a register
+                       li              r6,0                                            ; Set no next address return
+                       stw             r28,FM_ARG0+0x34(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x38(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x3C(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x40(r1)            ; Save a register
+                       stw             r6,FM_ARG0+0x44(r1)                     ; Save address to save next mapped vaddr
+                       stw             r0,(FM_ALIGN(hrmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)      ; Save the return
+
+                       lwz             r11,pmapVmmExt(r4)                      ; get VMM pmap extension block vaddr
+
+                       bt++    pf64Bitb,hsg64Salt                      ; Test for 64-bit machine
+                       lwz             r26,pmapVmmExtPhys+4(r4)        ; Get VMM pmap extension block paddr
+                       lwz             r9,pmapvr+4(r4)                         ; Get 32-bit virt<->real conversion salt
+                       b               hsgStart                                        ; Get to work
+
+hsg64Salt:     ld              r26,pmapVmmExtPhys(r4)          ; Get VMM pmap extension block paddr
+                       ld              r9,pmapvr+4(r4)                         ; Get 64-bit virt<->real conversion salt
+                       
+hsgStart:      bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, enter 64-bit mode
+                       xor             r27,r4,r9                                       ; Convert host pmap_t virt->real
+                       bl              mapPhysLock                                     ; Lock the physent
+
+                       bt++    pf64Bitb,hsg64Scan                      ; Test for 64-bit machine
+
+                       lwz             r12,ppLink+4(r3)                        ; Grab the pointer to the first mapping
+hsg32Loop:     rlwinm. r12,r12,0,~ppFlags                      ; Clean and test mapping address
+                       beq             hsg32Miss                                       ; Did not find one...
+                       lwz             r8,mpFlags(r12)                         ; Get mapping's flags
+                       lhz             r7,mpSpace(r12)                         ; Get mapping's space id
+                       rlwinm  r8,r8,0,mpType                          ; Extract mapping's type code
+                       lis             r28,hi16(EXT(pmapTrans))        ; Get the top of the start of the pmap hash to pmap translate table
+                       xori    r8,r8,mpGuest                           ; Is it a guest mapping?
+                       ori             r28,r28,lo16(EXT(pmapTrans))    ; Get the top of the start of the pmap hash to pmap translate table
+                       slwi    r9,r7,2                                         ; Multiply space by 4
+                       lwz             r28,0(r28)                                      ; Get the actual translation map
+                       lwz             r4,mpVAddr(r12)                         ; Get the top of the vaddr
+                       slwi    r7,r7,3                                         ; Multiply space by 8
+                       lwz             r5,mpVAddr+4(r12)                       ; Get the bottom of the vaddr
+                       add             r7,r7,r9                                        ; Get correct displacement into translate table
+                       add             r28,r28,r7                                      ; Point to the pmap translation
+                       lwz             r28,pmapPAddr+4(r28)            ; Get guest pmap paddr
+                       lwz             r7,pmapVmmExtPhys+4(r28)        ; Get VMM extension block paddr
+                       xor             r7,r7,r26                                       ; Is guest associated with specified host?
+                       or.             r7,r7,r8                                        ; Guest mapping && associated with host?
+                       lwz             r12,mpAlias+4(r12)                      ; Chain on to the next
+                       bne             hsg32Loop                                       ; Try next mapping on alias chain                       
+
+hsg32Hit:      bl              mapPhysUnlock                           ; Unlock physent chain
+                       b               hrmJoin                                         ; Join common path for mapping removal
+                       
+                       .align  5
+hsg32Miss:     bl              mapPhysUnlock                           ; Unlock physent chain
+                       mtmsr   r11                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       li              r3,mapRtEmpty                           ; No mappings found matching specified criteria
+                       b               hrmRetnCmn                                      ; Exit through common epilog
+                       
+                       .align  5                       
+hsg64Scan:     li              r6,ppLFAmask                            ; Get lock, flag, attribute mask seed
+                       ld              r12,ppLink(r3)                          ; Grab the pointer to the first mapping
+                       rotrdi  r6,r6,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+hsg64Loop:     andc.   r12,r12,r6                                      ; Clean and test mapping address
+                       beq             hsg64Miss                                       ; Did not find one...
+                       lwz             r8,mpFlags(r12)                         ; Get mapping's flags
+                       lhz             r7,mpSpace(r12)                         ; Get mapping's space id
+                       rlwinm  r8,r8,0,mpType                          ; Extract mapping's type code
+                       lis             r28,hi16(EXT(pmapTrans))        ; Get the top of the start of the pmap hash to pmap translate table
+                       xori    r8,r8,mpGuest                           ; Is it a guest mapping?
+                       ori             r28,r28,lo16(EXT(pmapTrans))    ; Get the top of the start of the pmap hash to pmap translate table
+                       slwi    r9,r7,2                                         ; Multiply space by 4
+                       lwz             r28,0(r28)                                      ; Get the actual translation map
+                       lwz             r4,mpVAddr(r12)                         ; Get the top of the vaddr
+                       slwi    r7,r7,3                                         ; Multiply space by 8
+                       lwz             r5,mpVAddr+4(r12)                       ; Get the bottom of the vaddr
+                       add             r7,r7,r9                                        ; Get correct displacement into translate table
+                       add             r28,r28,r7                                      ; Point to the pmap translation
+                       ld              r28,pmapPAddr(r28)                      ; Get guest pmap paddr
+                       ld              r7,pmapVmmExtPhys(r28)          ; Get VMM extension block paddr
+                       xor             r7,r7,r26                                       ; Is guest associated with specified host?
+                       or.             r7,r7,r8                                        ; Guest mapping && associated with host?
+                       ld              r12,mpAlias(r12)                        ; Chain on to the next
+                       bne             hsg64Loop                                       ; Try next mapping on alias chain                       
+
+hsg64Hit:      bl              mapPhysUnlock                           ; Unlock physent chain
+                       b               hrmJoin                                         ; Join common path for mapping removal
+                       
+                       .align  5
+hsg64Miss:     bl              mapPhysUnlock                           ; Unlock physent chain
+                       mtmsrd  r11                                                     ; Restore 'rupts, translation
+                       li              r3,mapRtEmpty                           ; No mappings found matching specified criteria
+                       b               hrmRetnCmn                                      ; Exit through common epilog
 
-LEXT(handlePF)
 
 /*
- *                     This first part does a quick check to see if we can handle the fault.
- *                     We can't handle any kind of protection exceptions here, so we pass
- *                     them up to the next level.
+ *                     mapping *hw_find_space(physent, space) - finds the first mapping on physent for specified space
  *
- *                     The mapping lists are kept in MRS (most recently stolen)
- *                     order on queues anchored within from the
- *                     PTEG to which the virtual address hashes.  This is further segregated by
- *                     the low-order 3 bits of the VSID XORed with the segment number and XORed
- *                     with bits 4-7 of the vaddr in an attempt to keep the searches
- *                     short.
- *                     
- *                     MRS is handled by moving the entry to the head of its list when stolen in the
- *                     assumption that it will be revalidated soon.  Entries are created on the head 
- *                     of the list because they will be used again almost immediately.
+ *                     Upon entry, R3 contains a pointer to a physent.  
+ *                     space is the space ID from the pmap in question
  *
- *                     We need R13 set to the savearea, R3 set to the interrupt code, and R2
- *                     set to the per_proc.
+ *                     We return the virtual address of the found mapping in 
+ *                     R3. Note that the mapping busy is bumped.
  *
- *                     NOTE: In order for a page-fault redrive to work, the translation miss
- *                     bit must be set in the DSISR (or SRR1 for IFETCH).  That must occur
- *                     before we come here.
+ *                     Note that this is designed to be called from 32-bit mode with a stack.
+ *
+ *                     We disable translation and all interruptions here.  This keeps is
+ *                     from having to worry about a deadlock due to having anything locked
+ *                     and needing it to process a fault.
+ *     
  */
 
-                       cmplwi  r3,T_INSTRUCTION_ACCESS         /* See if this is for the instruction */
-                       lwz             r8,savesrr1(r13)                        ; Get the MSR to determine mode
-                       beq-    gotIfetch                                       ; We have an IFETCH here...
-                       
-                       lwz             r7,savedsisr(r13)                       /* Get the DSISR */
-                       lwz             r6,savedar(r13)                         /* Get the fault address */
-                       b               ckIfProt                                        ; Go check if this is a protection fault...
-
-gotIfetch:     mr              r7,r8                                           ; IFETCH info is in SRR1
-                       lwz             r6,savesrr0(r13)                        /* Get the instruction address */
-
-ckIfProt:      rlwinm. r7,r7,0,1,1                                     ; Is this a protection exception?
-                       beqlr-                                                          ; Yes... (probably not though)
-
-/*
- *                     We will need to restore registers if we bail after this point.
- *                     Note that at this point several SRs have been changed to the kernel versions.
- *                     Therefore, for these we must build these values.
- */
+                       .align  5
+                       .globl  EXT(hw_find_space)
 
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r5,r6
-                       mr              r4,r3
-                       li              r3,32
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-                       mfsprg  r2,0
-#endif
-                       lwz             r3,PP_USERPMAP(r2)                      ; Get the user pmap (not needed if kernel access, but optimize for user??)
-                       rlwinm. r8,r8,0,MSR_PR_BIT,MSR_PR_BIT   ; Supervisor state access?
-                       rlwinm  r5,r6,6,26,29                           ; Get index to the segment slot
-                       eqv             r1,r1,r1                                        ; Fill the bottom with foxes
-                       bne+    notsuper                                        ; Go do the user mode interrupt stuff...
-                       
-                       cmplwi  cr1,r5,SR_COPYIN_NUM*4          ; See if this is the copyin/copyout segment
-                       rlwinm  r3,r6,24,8,11                           ; Make the kernel VSID
-                       bne+    cr1,havevsid                            ; We are done if we do not want the copyin/out guy...
-                       
-                       mfsr    r3,SR_COPYIN                            ; Get the copy vsid
-                       b               havevsid                                        ; Join up...
-
-                       .align  5
-
-notsuper:      addi    r5,r5,PMAP_SEGS                         ; Get offset to table
-                       lwzx    r3,r3,r5                                        ; Get the VSID
-
-havevsid:      mfspr   r5,sdr1                                         /* Get hash table base and size */
-                       cror    cr1_eq,cr0_eq,cr0_eq            ; Remember if kernel fault for later
-                       rlwinm  r9,r6,2,2,5                                     ; Move nybble 1 up to 0 (keep aligned with VSID)
-                       rlwimi  r1,r5,16,0,15                           /* Make table size -1 out of mask */
-                       rlwinm  r3,r3,6,2,25                            /* Position the space for the VSID */
-                       rlwinm  r7,r6,26,10,25                          /* Isolate the page index */
-                       xor             r9,r9,r3                                        ; Splooch vaddr nybble 0 (from VSID) and 1 together
-                       or              r8,r5,r1                                        /* Point to the last byte in table */
-                       xor             r7,r7,r3                                        /* Get primary hash */
-                       rlwinm  r3,r3,1,1,24                            /* Position VSID for pte ID */
-                       addi    r8,r8,1                                         /* Point to the PTEG Control Area */
-                       rlwinm  r9,r9,8,27,29                           ; Get splooched bits in place
-                       and             r7,r7,r1                                        /* Wrap the hash */
-                       rlwimi  r3,r6,10,26,31                          /* Move API into pte ID */
-                       add             r8,r8,r7                                        /* Point to our PCA entry */
-                       rlwinm  r12,r3,27,27,29                         ; Get low 3 bits of the VSID for look-aside hash
-                       la              r11,PCAhash(r8)                         /* Point to the mapping hash area */
-                       xor             r9,r9,r12                                       ; Finish splooching nybble 0, 1, and the low bits of the VSID
+LEXT(hw_find_space)
+                       stwu    r1,-(FM_SIZE)(r1)                       ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       mr              r8,r4                                           ; Remember the space
+                       stw             r0,(FM_SIZE+FM_LR_SAVE)(r1)     ; Save the return
 
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
 
-/*
- *                     We have about as much as we need to start searching the autogen (aka block maps)
- *                     and mappings.  From here on, any kind of failure will bail, and
- *                     contention will either bail or restart from here.
- *
- *                     
- */
+                       bl              mapPhysLock                                     ; Lock the physent
+                       bt++    pf64Bitb,hfsSF                          ; skip if 64-bit (only they take the hint)
+               
+                       lwz             r12,ppLink+4(r3)                        ; Grab the pointer to the first mapping
                        
-                       li              r12,1                                           /* Get the locked value */
-                       dcbt    0,r11                                           /* We'll need the hash area in a sec, so get it */
-                       add             r11,r11,r9                                      /* Point to the right mapping hash slot */
+hfsSrc32:      rlwinm. r12,r12,0,~ppFlags                      ; Clean and test mapping address
+                       beq             hfsNone                                         ; Did not find one...
                        
-ptegLck:       lwarx   r10,0,r8                                        /* Get the PTEG lock */
-                       mr.             r10,r10                                         /* Is it locked? */
-                       bne-    ptegLckw                                        /* Yeah... */
-                       stwcx.  r12,0,r8                                        /* Take take it */
-                       bne-    ptegLck                                         /* Someone else was trying, try again... */
-                       b               ptegSXg                                         /* All done... */
+                       lhz             r10,mpSpace(r12)                        ; Get the space
                        
-                       .align  4
-
-ptegLckw:      mr.             r10,r10                                         /* Check if it's already held */
-                       beq+    ptegLck                                         /* It's clear... */
-                       lwz             r10,0(r8)                                       /* Get lock word again... */
-                       b               ptegLckw                                        /* Wait... */
+                       cmplw   r10,r8                                          ; Is this one of ours?
+                       beq             hfsFnd                                          ; Yes...
                        
+                       lwz             r12,mpAlias+4(r12)                      ; Chain on to the next
+                       b               hfsSrc32                                        ; Check it out...
+
                        .align  5
+               
+hfsSF:         li              r0,ppLFAmask
+                       ld              r12,ppLink(r3)                          ; Get the pointer to the first mapping
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
                        
-                       nop                                                                     ; Force ISYNC to last instruction in IFETCH
-                       nop                                                                     
-                       nop
-
-ptegSXg:       isync                                                           /* Make sure we haven't used anything yet */
-
-                       lwz             r9,0(r11)                                       /* Pick up first mapping block */
-                       mr              r5,r11                                          /* Get the address of the anchor */
-                       mr              r7,r9                                           /* Save the first in line */
-                       b               findmap                                         ; Take space and force loop to cache line
-               
-findmap:       mr.             r12,r9                                          /* Are there more? */
-                       beq-    tryAuto                                         /* Nope, nothing in mapping list for us... */
-                       
-                       lwz             r10,mmPTEv(r12)                         /* Get unique PTE identification */
-                       lwz             r9,mmhashnext(r12)                      /* Get the chain, just in case */
-                       cmplw   r10,r3                                          /* Did we hit our PTE? */
-                       lwz             r0,mmPTEent(r12)                        /* Get the pointer to the hash table entry */
-                       mr              r5,r12                                          /* Save the current as previous */
-                       bne-    findmap                                         ; Nothing here, try the next...
-
-;                      Cache line boundary here
-
-                       cmplwi  cr1,r0,0                                        /* Is there actually a PTE entry in the hash? */
-                       lwz             r2,mmphysent(r12)                       /* Get the physical entry */
-                       bne-    cr1,MustBeOK                            /* There's an entry in the hash table, so, this must 
-                                                                                                  have been taken care of already... */
-                       lis             r4,0x8000                                       ; Tell PTE inserter that this was not an auto
-                       cmplwi  cr2,r2,0                                        /* Is there a physical entry? */
-                       li              r0,0x0100                                       /* Force on the reference bit whenever we make a PTE valid */
-                       bne+    cr2,gotphys                                     /* Skip down if we have a physical entry */
-                       li              r0,0x0180                                       /* When there is no physical entry, force on
-                                                                                                  both R and C bits to keep hardware from
-                                                                                                  updating the PTE to set them.  We don't
-                                                                                                  keep track of RC for I/O areas, so this is ok */
-                       
-gotphys:       lwz             r2,mmPTEr(r12)                          ; Get the second part of the PTE
-                       b               insert                                          /* Go insert into the PTEG... */
-
-MustBeOK:      li              r10,0                                           /* Get lock clear value */
-                       li              r3,T_IN_VAIN                            /* Say that we handled it */
-                       stw             r10,PCAlock(r8)                         /* Clear the PTEG lock */
-
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,33
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Blow back and handle exception */
-
-
-                       
-/*
- *                     We couldn't find it in the mapping list.  As a last try, we will
- *                     see if we can autogen it from the block mapped list.
- *     
- *                     A block mapped area is defined as a contiguous virtual area that is mapped to 
- *                     a contiguous physical area.  The olde-tyme IBM VM/XA Interpretive Execution
- *                     architecture referred to this as a V=F, or Virtual = Fixed area. 
- *
- *                     We consider a V=F area to be a single entity, adjacent areas can not be merged
- *                     or overlapped.  The protection and memory attributes are the same and reference
- *                     and change indications are not kept. The areas are not considered part of the
- *                     physical RAM of the machine and do not have any associated physical table
- *                     entries. Their primary use is intended for mapped I/O areas (e.g., framebuffers)
- *                     although certain areas of RAM, such as the kernel V=R memory, can be mapped.
- *
- *                     We also have a problem in the case of copyin/out: that access is done
- *                     within the kernel for a user address. Unfortunately, the user isn't
- *                     necessarily the current guy.  That means that we don't have access to the
- *                     right autogen list. We can't support this kind of access. So, we need to do
- *                     a quick check here and cause a fault if an attempt to copyin or out to
- *                     any autogenned area.
- *
- *                     The lists must be kept short.
- *
- *                     NOTE:  kernel_pmap_store must be in V=R storage!!!!!!!!!!!!!!
- */
-                       .align  5
-
-tryAuto:       rlwinm. r11,r3,0,5,24                           ; Check if this is a kernel VSID
-                       lis             r10,HIGH_ADDR(EXT(kernel_pmap_store)+PMAP_BMAPS)        ; Get the top part of kernel block map anchor
-                       crandc  cr0_eq,cr1_eq,cr0_eq            ; Set if kernel access and non-zero VSID (copyin or copyout)
-                       mfsprg  r11,0                                           ; Get the per_proc area
-                       beq-    cr0,realFault                                   ; Can not autogen for copyin/copyout...
-                       ori             r10,r10,LOW_ADDR(EXT(kernel_pmap_store)+PMAP_BMAPS)     ; Get the bottom part
-                       beq-    cr1,bmInKernel                          ; We are in kernel... (cr1 set way back at entry)
-                       
-                       lwz             r10,PP_USERPMAP(r11)            ; Get the user pmap
-                       la              r10,PMAP_BMAPS(r10)                     ; Point to the chain anchor
-                       b               bmInKernel                                      ; Jump over alignment gap...
-                       nop
-                       nop
-                       nop
-                       nop
-                       nop
-                       nop                                             
-bmInKernel:
-#ifndef CHIP_ERRATA_MAX_V1
-                       lwarx   r9,0,r10        
-#endif /* CHIP_ERRATA_MAX_V1 */
-
-bmapLck:       lwarx   r9,0,r10                                        ; Get the block map anchor and lock
-                       rlwinm. r5,r9,0,31,31                           ; Is it locked?
-                       ori             r5,r5,1                                         ; Set the lock
-                       bne-    bmapLckw                                        ; Yeah...
-                       stwcx.  r5,0,r10                                        ; Lock the bmap list
-                       bne-    bmapLck                                         ; Someone else was trying, try again...
-                       b               bmapSXg                                         ; All done...
-                       
-                       .align  4
-
-bmapLckw:      rlwinm. r5,r9,0,31,31                           ; Check if it is still held
-                       beq+    bmapLck                                         ; Not no more...
-                       lwz             r9,0(r10)                                       ; Get lock word again...
-                       b               bmapLckw                                        ; Check it out...
-                       
-                       .align  5
-                       
-                       nop                                                                     ; Force ISYNC to last instruction in IFETCH
-                       nop                                                                     
-                       nop
-
-bmapSXg:       rlwinm. r4,r9,0,0,26                            ; Clear out flags and lock
-                       isync                                                           ; Make sure we have not used anything yet
-                       bne+    findAuto                                        ; We have something, let us go...
-                       
-bmapNone:      stw             r9,0(r10)                                       ; Unlock it, we have nothing here
-                                                                                               ; No sync here because we have not changed anything
+hfsSrc64:      andc.   r12,r12,r0                                      ; Clean and test mapping address
+                       beq             hfsNone                                         ; Did not find one...
                        
-/*
- *                     When we come here, we know that we can't handle this.  Restore whatever
- *                     state that we trashed and go back to continue handling the interrupt.
- */
-
-realFault:     li              r10,0                                           /* Get lock clear value */
-                       lwz             r3,saveexception(r13)           /* Figure out the exception code again */
-                       stw             r10,PCAlock(r8)                         /* Clear the PTEG lock */
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,33
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Blow back and handle exception */
-                       
-                       .align  5
-                       
-findAuto:      mr.             r4,r4                                           ; Is there more?
-                       beq-    bmapNone                                        ; No more...
-                       lwz             r5,bmstart(r4)                          ; Get the bottom of range
-                       lwz             r11,bmend(r4)                           ; Get the top of range
-                       cmplw   cr0,r6,r5                                       ; Are we before the entry?
-                       cmplw   cr1,r6,r11                                      ; Are we after the entry?
-                       cror    cr1_eq,cr0_lt,cr1_gt            ; Set cr1_eq if new not in range
-                       bne+    cr1,faGot                                       ; Found it...
-                       
-                       lwz             r4,bmnext(r4)                           ; Get the next one
-                       b               findAuto                                        ; Check it out...
+                       lhz             r10,mpSpace(r12)                        ; Get the space
                        
-faGot:         
-                       lwz             r7,blkFlags(r4)                         ; Get the flags
-                       rlwinm. r7,r7,0,blkRembit,blkRembit     ; is this mapping partially removed
-                       bne             bmapNone                                        ; Pending remove, bail out
-                       rlwinm  r6,r6,0,0,19                            ; Round to page
-                       lwz             r2,bmPTEr(r4)                           ; Get the real part of the PTE
-                       sub             r5,r6,r5                                        ; Get offset into area
-                       stw             r9,0(r10)                                       ; Unlock it, we are done with it (no sync needed)
-                       add             r2,r2,r5                                        ; Adjust the real address
+                       cmplw   r10,r8                                          ; Is this one of ours?
+                       beq             hfsFnd                                          ; Yes...
                        
-                       lis             r4,0x8080                                       /* Indicate that this was autogened */
-                       li              r0,0x0180                                       /* Autogenned areas always set RC bits.
-                                                                                                  This keeps the hardware from having
-                                                                                                  to do two storage writes */
+                       ld              r12,mpAlias(r12)                        ; Chain on to the next
+                       b               hfsSrc64                                        ; Check it out...
                        
-/*
- *                     Here where we insert the PTE into the hash.  The PTE image is in R3, R2. 
- *                     The PTEG allocation controls are a bit map of the state of the PTEG. The
- *                     PCAlock bits are a temporary lock for the specified PTE.  PCAfree indicates that
- *                     the PTE slot is empty. PCAauto means that it comes from an autogen area.  These
- *                     guys do not keep track of reference and change and are actually "wired".
- *                     They're easy to maintain. PCAsteal
- *                     is a sliding position mask used to "randomize" PTE slot stealing.  All 4 of these
- *                     fields fit in a single word and are loaded and stored under control of the
- *                     PTEG control area lock (PCAlock).
- *
- *                     Note that PCAauto does not contribute to the steal calculations at all.  Originally
- *                     it did, autogens were second in priority.  This can result in a pathalogical
- *                     case where an instruction can not make forward progress, or one PTE slot
- *                     thrashes.
- *
- *                     Physically, the fields are arranged:
- *                             0: PCAfree
- *                             1: PCAauto
- *                             2: PCAlock
- *                             3: PCAsteal
- */
-                       
-insert:                lwz             r10,PCAallo(r8)                         /* Get the PTEG controls */
-                       eqv             r6,r6,r6                                        /* Get all ones */              
-                       mr              r11,r10                                         /* Make a copy */
-                       rlwimi  r6,r10,8,16,23                          /* Insert sliding steal position */
-                       rlwimi  r11,r11,24,24,31                        /* Duplicate the locked field */
-                       addi    r6,r6,-256                                      /* Form mask */
-                       rlwimi  r11,r11,16,0,15                         /* This gives us a quadrupled lock mask */
-                       rlwinm  r5,r10,31,24,0                          /* Slide over the mask for next time */
-                       mr              r9,r10                                          /* Make a copy to test */
-                       not             r11,r11                                         /* Invert the quadrupled lock */
-                       or              r2,r2,r0                                        /* Force on R, and maybe C bit */
-                       and             r9,r9,r11                                       /* Remove the locked guys */
-                       rlwimi  r5,r5,8,24,24                           /* Wrap bottom bit to top in mask */
-                       rlwimi  r9,r11,0,16,31                          /* Put two copies of the unlocked entries at the end */
-                       rlwinm  r6,r6,0,16,7                            ; Remove the autogens from the priority calculations
-                       rlwimi  r10,r5,0,24,31                          /* Move steal map back in */
-                       and             r9,r9,r6                                        /* Set the starting point for stealing */
-
-/*                     So, now we have in R9:
-                               byte 0 = ~locked & free 
-                               byte 1 = 0 
-                               byte 2 = ~locked & (PCAsteal - 1)
-                               byte 3 = ~locked
-
-                               Each bit position represents (modulo 8) a PTE. If it is 1, it is available for 
-                               allocation at its priority level, left to right.  
-                               
-                       Additionally, the PCA steal field in R10 has been rotated right one bit.
-*/
-                       
-
-                       rlwinm  r21,r10,8,0,7                           ; Isolate just the old autogen bits
-                       cntlzw  r6,r9                                           /* Allocate a slot */
-                       mr              r14,r12                                         /* Save our mapping for later */
-                       cmplwi  r6,32                                           ; Was there anything available?
-                       rlwinm  r7,r6,29,30,31                          /* Get the priority slot we got this from */
-                       rlwinm  r6,r6,0,29,31                           ; Isolate bit position
-                       srw             r11,r4,r6                                       /* Position the PTEG control bits */
-                       slw             r21,r21,r6                                      ; Move corresponding old autogen flag to bit 0
-                       mr              r22,r11                                         ; Get another copy of the selected slot
-                       
-                       beq-    realFault                                       /* Arghh, no slots! Take the long way 'round... */
-                       
-                                                                                               /* Remember, we've already set up the mask pattern
-                                                                                                  depending upon how we got here:
-                                                                                                    if got here from simple mapping, R4=0x80000000,
-                                                                                                    if we got here from autogen it is 0x80800000. */
-                       
-                       rlwinm  r6,r6,3,26,28                           /* Start calculating actual PTE address */
-                       rlwimi  r22,r22,24,8,15                         ; Duplicate selected slot in second byte
-                       rlwinm. r11,r11,0,8,15                          /* Isolate just the auto bit (remember about it too) */
-                       andc    r10,r10,r22                                     /* Turn off the free and auto bits */
-                       add             r6,r8,r6                                        /* Get position into PTEG control area */
-                       cmplwi  cr1,r7,1                                        /* Set the condition based upon the old PTE type */
-                       sub             r6,r6,r1                                        /* Switch it to the hash table */
-                       or              r10,r10,r11                                     /* Turn auto on if it is (PTEG control all set up now) */                       
-                       subi    r6,r6,1                                         /* Point right */
-                       stw             r10,PCAallo(r8)                         /* Allocate our slot */
-                       dcbt    br0,r6                                          ; Touch in the PTE
-                       bne             wasauto                                         /* This was autogenned... */
-                       
-                       stw             r6,mmPTEent(r14)                        /* Link the mapping to the PTE slot */
+                       .align  5
                        
-/*
- *                     So, now we're here and what exactly do we have?  We've got: 
- *                             1)      a full PTE entry, both top and bottom words in R3 and R2
- *                             2)      an allocated slot in the PTEG.
- *                             3)      R8 still points to the PTEG Control Area (PCA)
- *                             4)      R6 points to the PTE entry.
- *                             5)      R1 contains length of the hash table-1. We use this to back-translate
- *                                     a PTE to a virtual address so we can invalidate TLBs.
- *                             6)      R11 has a copy of the PCA controls we set.
- *                             7a)     R7 indicates what the PTE slot was before we got to it. 0 shows
- *                                     that it was empty and 2 or 3, that it was
- *                                     a we've stolen a live one. CR1 is set to LT for empty and GT
- *                                     otherwise.
- *                             7b)     Bit 0 of R21 is 1 if the stolen PTE was autogenned
- *                             8)      So far as our selected PTE, it should be valid if it was stolen
- *                                     and invalid if not.  We could put some kind of assert here to
- *                                     check, but I think that I'd rather leave it in as a mysterious,
- *                                     non-reproducable bug.
- *                             9)      The new PTE's mapping has been moved to the front of its PTEG hash list
- *                                     so that it's kept in some semblance of a MRU list.
- *                        10)  R14 points to the mapping we're adding.
- *
- *                     So, what do we have to do yet?
- *                             1)      If we stole a slot, we need to invalidate the PTE completely.
- *                             2)      If we stole one AND it was not an autogen, 
- *                                     copy the entire old PTE (including R and C bits) to its mapping.
- *                             3)      Set the new PTE in the PTEG and make sure it is valid.
- *                             4)      Unlock the PTEG control area.
- *                             5)      Go back to the interrupt handler, changing the interrupt
- *                                     code to "in vain" which will restore the registers and bail out.
- *
- */
-wasauto:       oris    r3,r3,0x8000                            /* Turn on the valid bit */
-                       blt+    cr1,slamit                                      /* It was empty, go slam it on in... */
-                       
-                       lwz             r10,0(r6)                                       /* Grab the top part of the PTE */
-                       rlwinm  r12,r6,6,4,19                           /* Match up the hash to a page boundary */
-                       rlwinm  r5,r10,5,4,19                           /* Extract the VSID to a page boundary */
-                       rlwinm  r10,r10,0,1,31                          /* Make it invalid */
-                       xor             r12,r5,r12                                      /* Calculate vaddr */
-                       stw             r10,0(r6)                                       /* Invalidate the PTE */
-                       rlwinm  r5,r10,7,27,29                          ; Move nybble 0 up to subhash position
-                       rlwimi  r12,r10,1,0,3                           /* Move in the segment portion */
-                       lis             r9,HIGH_ADDR(EXT(tlb_system_lock))      /* Get the TLBIE lock */
-                       xor             r5,r5,r10                                       ; Splooch nybble 0 and 1
-                       rlwimi  r12,r10,22,4,9                          /* Move in the API */
-                       ori             r9,r9,LOW_ADDR(EXT(tlb_system_lock))    /* Grab up the bottom part */
-                       rlwinm  r4,r10,27,27,29                         ; Get low 3 bits of the VSID for look-aside hash
-                       
-                       sync                                                            /* Make sure the invalid is stored */
-
-                       xor             r4,r4,r5                                        ; Finish splooching nybble 0, 1, and the low bits of the VSID
-                                               
-tlbhang:       lwarx   r5,0,r9                                         /* Get the TLBIE lock */
-               
-                       rlwinm  r4,r4,0,27,29                           ; Clean up splooched hash value
+hfsFnd:                mr              r8,r3                                           ; Save the physent
+                       mr              r3,r12                                          ; Point to the mapping
+                       bl              mapBumpBusy                                     ; If we found it, bump up the busy count so the mapping does not disapear
 
-                       mr.             r5,r5                                           /* Is it locked? */
-                       add             r4,r4,r8                                        /* Point to the offset into the PCA area */
-                       li              r5,1                                            /* Get our lock word */
-                       bne-    tlbhang                                         /* It's locked, go wait... */
+                       mr              r3,r8                                           ; Get back the physical entry
+                       li              r7,0xFFF                                        ; Get a page size mask
+                       bl              mapPhysUnlock                           ; Time to unlock the physical entry
+               
+                       andc    r3,r12,r7                                       ; Move the mapping back down to a page  
+                       lwz             r3,mbvrswap+4(r3)                       ; Get last half of virtual to real swap
+                       xor             r12,r3,r12                                      ; Convert to virtual
+                       b               hfsRet                                          ; Time to return
                        
-                       la              r4,PCAhash(r4)                          /* Point to the start of the hash chain for the PTE we're replacing */
+                       .align  5
                        
-                       stwcx.  r5,0,r9                                         /* Try to get it */
-                       bne-    tlbhang                                         /* We was beat... */
+hfsNone:       bl              mapPhysUnlock                           ; Time to unlock the physical entry
                        
-                       mfspr   r7,pvr                                          /* Find out what kind of machine we are */
-                       li              r5,0                                            /* Lock clear value */
-                       rlwinm  r7,r7,16,16,31                          /* Isolate CPU type */
+hfsRet:                bt++    pf64Bitb,hfsSF3                         ; skip if 64-bit (only they take the hint)...
 
-                       tlbie   r12                                                     /* Invalidate it everywhere */
+                       mtmsr   r11                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               hfsRetnCmn                                      ; Join the common return code...
 
-                       cmplwi  r7,3                                            /* Is this a 603? */
-                       stw             r5,0(r9)                                        /* Clear the lock */
-                       
-                       beq-    its603                                          /* It's a 603, skip the tlbsync... */
-                       
-                       eieio                                                           /* Make sure that the tlbie happens first */
-                       tlbsync                                                         /* wait for everyone to catch up */
-                       isync                                                           
-                       
-its603:                rlwinm. r21,r21,0,0,0                           ; See if we just stole an autogenned entry
-                       sync                                                            /* Make sure of it all */
+hfsSF3:                mtmsrd  r11                                                     ; Restore enables/translation/etc.
+                       isync
 
-                       bne             slamit                                          ; The old was an autogen, time to slam the new in...
-                       
-                       lwz             r9,4(r6)                                        /* Get the real portion of old PTE */
-                       lwz             r7,0(r4)                                        /* Get the first element.  We can't get to here
-                                                                                                  if we aren't working with a mapping... */
-                       mr              r0,r7                                           ; Save pointer to first element
-                                                                                                  
-findold:       mr              r1,r11                                          ; Save the previous guy
-                       mr.             r11,r7                                          /* Copy and test the chain */
-                       beq-    bebad                                           /* Assume it's not zero... */
-                       
-                       lwz             r5,mmPTEv(r11)                          /* See if this is the old active one */
-                       cmplw   cr2,r11,r14                                     /* Check if this is actually the new one */
-                       cmplw   r5,r10                                          /* Is this us?  (Note: valid bit kept off in mappings) */
-                       lwz             r7,mmhashnext(r11)                      /* Get the next one in line */
-                       beq-    cr2,findold                                     /* Don't count the new one... */
-                       cmplw   cr2,r11,r0                                      ; Check if we are first on the list
-                       bne+    findold                                         /* Not it (and assume the worst)... */
-                       
-                       lwz             r12,mmphysent(r11)                      /* Get the pointer to the physical entry */
-                       beq-    cr2,nomove                                      ; We are first, no need to requeue...
+;
+;                      NOTE: we have not used any registers other than the volatiles to this point
+;
+
+hfsRetnCmn:    mr              r3,r12                                          ; Get the mapping or a 0 if we failed
+
+#if DEBUG
+                       mr.             r3,r3                                           ; Anything to return?
+                       beq             hfsRetnNull                                     ; Nope
+                       lwz             r11,mpFlags(r3)                         ; Get mapping flags
+                       rlwinm  r0,r11,0,mpType                         ; Isolate the mapping type
+                       cmplwi  r0,mpGuest                                      ; Shadow guest mapping?
+                       beq             hfsPanic                                        ; Yup, kick the bucket
+hfsRetnNull:
+#endif
+
+                       lwz             r12,(FM_SIZE+FM_LR_SAVE)(r1)    ; Restore the return
+
+                       mtlr    r12                                                     ; Restore the return
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
 
-                       stw             r11,0(r4)                                       ; Chain us to the head
-                       stw             r0,mmhashnext(r11)                      ; Chain the old head to us
-                       stw             r7,mmhashnext(r1)                       ; Unlink us
+hfsPanic:      lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
 
-nomove:                li              r5,0                                            /* Clear this on out */
+;
+;                      mapping *hw_find_map(pmap, va, *nextva) - Looks up a vaddr in a pmap
+;                      Returns 0 if not found or the virtual address of the mapping if
+;                      if is.  Also, the mapping has the busy count bumped.
+;
+                       .align  5
+                       .globl  EXT(hw_find_map)
+
+LEXT(hw_find_map)
+                       stwu    r1,-(FM_ALIGN((31-25+1)*4)+FM_SIZE)(r1) ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r25,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x04(r1)            ; Save a register
+                       mr              r25,r6                                          ; Remember address of next va
+                       stw             r27,FM_ARG0+0x08(r1)            ; Save a register
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x10(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r0,(FM_ALIGN((31-26+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+
+#if DEBUG
+                       lwz             r11,pmapFlags(r3)                       ; Get pmaps flags
+                       rlwinm. r11,r11,0,pmapVMgsaa            ; Is guest shadow assist active? 
+                       bne             hfmPanic                                        ; Call not valid for guest shadow assist pmap
+#endif
                        
-                       mr.             r12,r12                                         /* Is there a physical entry? */
-                       stw             r5,mmPTEent(r11)                        ; Clear the PTE entry pointer
-                       li              r5,pepte1                                       /* Point to the PTE last half */
-                       stw             r9,mmPTEr(r11)                          ; Squirrel away the whole thing (RC bits are in here)
+                       lwz             r6,pmapvr(r3)                           ; Get the first part of the VR translation for pmap
+                       lwz             r7,pmapvr+4(r3)                         ; Get the second part
+
+
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
+
+                       mr              r27,r11                                         ; Remember the old MSR
+                       mr              r26,r12                                         ; Remember the feature bits
+
+                       xor             r28,r3,r7                                       ; Change the common 32- and 64-bit half
+
+                       bf--    pf64Bitb,hfmSF1                         ; skip if 32-bit...
                        
-                       beq-    mrgmrcx                                         ; No physical entry for this one...
+                       rldimi  r28,r6,32,0                                     ; Shift the fixed upper part of the physical over and cram in top
+
+hfmSF1:                mr              r29,r4                                          ; Save top half of vaddr
+                       mr              r30,r5                                          ; Save the bottom half
+                                               
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne--   hfmBadLock                                      ; Nope...
+
+                       mr              r3,r28                                          ; get the pmap address
+                       mr              r4,r29                                          ; Get bits 0:31 to look for
+                       mr              r5,r30                                          ; Get bits 32:64
                        
-                       rlwinm  r11,r9,0,23,24                          /* Keep only the RC bits */
+                       bl              EXT(mapSearch)                          ; Go see if we can find it (note: R7 comes back with mpFlags)
 
-mrgmrcx:       lwarx   r9,r5,r12                                       /* Get the master copy */
-                       or              r9,r9,r11                                       /* Merge in latest RC */
-                       stwcx.  r9,r5,r12                                       /* Save it back */
-                       bne-    mrgmrcx                                         /* If it changed, try again... */
+                       rlwinm  r0,r7,0,mpRIPb,mpRIPb           ; Find remove in progress bit
+                       mr.             r31,r3                                          ; Save the mapping if we found it
+                       cmplwi  cr1,r0,0                                        ; Are we removing?
+                       mr              r29,r4                                          ; Save next va high half
+                       crorc   cr0_eq,cr0_eq,cr1_eq            ; Not found or removing
+                       mr              r30,r5                                          ; Save next va low half
+                       li              r6,0                                            ; Assume we did not find it
+                       li              r26,0xFFF                                       ; Get a mask to relocate to start of mapping page
 
-/*
- *                     Here's where we finish up.  We save the real part of the PTE, eieio it, to make sure it's
- *                     out there before the top half (with the valid bit set).
- */
+                       bt--    cr0_eq,hfmNotFnd                        ; We did not find it...
 
-slamit:                stw             r2,4(r6)                                        /* Stash the real part */
-                       li              r4,0                                            /* Get a lock clear value */
-                       eieio                                                           /* Erect a barricade */
-                       stw             r3,0(r6)                                        /* Stash the virtual part and set valid on */
-
-                       stw             r4,PCAlock(r8)                          /* Clear the PCA lock */
-
-                       li              r3,T_IN_VAIN                            /* Say that we handled it */
-                       sync                                                            /* Go no further until the stores complete */
-#if PERFTIMES && DEBUG
-                       mflr    r11
-                       mr              r4,r3
-                       li              r3,33
-                       bl              EXT(dbgLog2)                                            ; Start of hw_add_map
-                       mr              r3,r4
-                       mtlr    r11
-#endif
-                       blr                                                                     /* Back to the fold... */
-                                       
-bebad:         lis             r0,HIGH_ADDR(Choke)                     /* We have a kernel choke!!! */
-                       ori             r0,r0,LOW_ADDR(Choke)                           
-                       sc                                                                      /* Firmware Heimlich maneuver */
-                       
-/*
- *                     This walks the hash table or DBATs to locate the physical address of a virtual one.
- *                     The space is provided.  If it is the kernel space, the DBATs are searched first.  Failing
- *                     that, the hash table is accessed. Zero is returned for failure, so it must be special cased.
- *                     This is usually used for debugging, so we try not to rely
- *                     on anything that we don't have to.
- */
+                       bl              mapBumpBusy                                     ; If we found it, bump up the busy count so the mapping does not disapear
 
-ENTRY(LRA, TAG_NO_FRAME_USED)
+                       andc    r4,r31,r26                                      ; Get back to the mapping page start
 
-                       mfsprg  r8,2                                            ; Get feature flags 
-                       mfmsr   r10                                                     /* Save the current MSR */
-                       rlwinm  r10,r10,0,MSR_FP_BIT+1,MSR_FP_BIT-1     ; Force floating point off
-                       rlwinm  r10,r10,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1   ; Force vectors off
-                       mtcrf   0x04,r8                                         ; Set the features                      
-                       xoris   r5,r3,HIGH_ADDR(PPC_SID_KERNEL)         /* Clear the top half if equal */
-                       andi.   r9,r10,0x7FCF                           /* Turn off interrupts and translation */
-                       eqv             r12,r12,r12                                     /* Fill the bottom with foxes */
+;                      Note: we can treat 32- and 64-bit the same here. Because we are going from
+;                      physical to virtual and we only do 32-bit virtual, we only need the low order
+;                      word of the xor.
 
-                       bt              pfNoMSRirb,lraNoMSR                     ; No MSR...
+                       lwz             r4,mbvrswap+4(r4)                       ; Get last half of virtual to real swap
+                       li              r6,-1                                           ; Indicate we found it and it is not being removed
+                       xor             r31,r31,r4                                      ; Flip to virtual
 
-                       mtmsr   r9                                                      ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               lraNoMSRx
+hfmNotFnd:     la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+
+                       rlwinm  r3,r31,0,0,31                           ; Move mapping to return register and clear top of register if 64-bit
+                       and             r3,r3,r6                                        ; Clear if not found or removing
+
+hfmReturn:     bt++    pf64Bitb,hfmR64                         ; Yes...
+
+                       mtmsr   r27                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               hfmReturnC                                      ; Join common...
+
+hfmR64:                mtmsrd  r27                                                     ; Restore enables/translation/etc.
+                       isync                                                           
                        
-lraNoMSR:      
-                       mr              r7,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r9                                           ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r7
-lraNoMSRx:
-
-                       cmplwi  r5,LOW_ADDR(PPC_SID_KERNEL)     /* See if this is kernel space */
-                       rlwinm  r11,r3,6,6,25                           /* Position the space for the VSID */
-                       isync                                                           /* Purge pipe */
-                       bne-    notkernsp                                       /* This is not for the kernel... */             
-                       
-                       mfspr   r5,dbat0u                                       /* Get the virtual address and length */
-                       eqv             r8,r8,r8                                        /* Get all foxes */
-                       rlwinm. r0,r5,0,30,30                           /* Check if valid for supervisor state */
-                       rlwinm  r7,r5,0,0,14                            /* Clean up the base virtual address */
-                       beq-    ckbat1                                          /* not valid, skip this one... */
-                       sub             r7,r4,r7                                        /* Subtract out the base */
-                       rlwimi  r8,r5,15,0,14                           /* Get area length - 1 */
-                       mfspr   r6,dbat0l                                       /* Get the real part */
-                       cmplw   r7,r8                                           /* Check if it is in the range */
-                       bng+    fndbat                                          /* Yup, she's a good un... */
-
-ckbat1:                mfspr   r5,dbat1u                                       /* Get the virtual address and length */                        
-                       eqv             r8,r8,r8                                        /* Get all foxes */
-                       rlwinm. r0,r5,0,30,30                           /* Check if valid for supervisor state */
-                       rlwinm  r7,r5,0,0,14                            /* Clean up the base virtual address */
-                       beq-    ckbat2                                          /* not valid, skip this one... */
-                       sub             r7,r4,r7                                        /* Subtract out the base */
-                       rlwimi  r8,r5,15,0,14                           /* Get area length - 1 */
-                       mfspr   r6,dbat1l                                       /* Get the real part */
-                       cmplw   r7,r8                                           /* Check if it is in the range */
-                       bng+    fndbat                                          /* Yup, she's a good un... */
-                       
-ckbat2:                mfspr   r5,dbat2u                                       /* Get the virtual address and length */
-                       eqv             r8,r8,r8                                        /* Get all foxes */
-                       rlwinm. r0,r5,0,30,30                           /* Check if valid for supervisor state */
-                       rlwinm  r7,r5,0,0,14                            /* Clean up the base virtual address */
-                       beq-    ckbat3                                          /* not valid, skip this one... */
-                       sub             r7,r4,r7                                        /* Subtract out the base */
-                       rlwimi  r8,r5,15,0,14                           /* Get area length - 1 */
-                       mfspr   r6,dbat2l                                       /* Get the real part */
-                       cmplw   r7,r8                                           /* Check if it is in the range */
-                       bng-    fndbat                                          /* Yup, she's a good un... */
-                       
-ckbat3:                mfspr   r5,dbat3u                                       /* Get the virtual address and length */
-                       eqv             r8,r8,r8                                        /* Get all foxes */
-                       rlwinm. r0,r5,0,30,30                           /* Check if valid for supervisor state */
-                       rlwinm  r7,r5,0,0,14                            /* Clean up the base virtual address */
-                       beq-    notkernsp                                       /* not valid, skip this one... */
-                       sub             r7,r4,r7                                        /* Subtract out the base */
-                       rlwimi  r8,r5,15,0,14                           /* Get area length - 1 */
-                       mfspr   r6,dbat3l                                       /* Get the real part */
-                       cmplw   r7,r8                                           /* Check if it is in the range */
-                       bgt+    notkernsp                                       /* No good... */
-                       
-fndbat:                rlwinm  r6,r6,0,0,14                            /* Clean up the real address */
-                       mtmsr   r10                                                     /* Restore state */
-                       add             r3,r7,r6                                        /* Relocate the offset to real */
-                       isync                                                           /* Purge pipe */
-                       blr                                                                     /* Bye, bye... */
-
-notkernsp:     mfspr   r5,sdr1                                         /* Get hash table base and size */
-                       rlwimi  r11,r4,30,2,5                           /* Insert the segment no. to make a VSID */
-                       rlwimi  r12,r5,16,0,15                          /* Make table size -1 out of mask */
-                       rlwinm  r7,r4,26,10,25                          /* Isolate the page index */
-                       andc    r5,r5,r12                                       /* Clean up the hash table */
-                       xor             r7,r7,r11                                       /* Get primary hash */
-                       rlwinm  r11,r11,1,1,24                          /* Position VSID for pte ID */
-                       and             r7,r7,r12                                       /* Wrap the hash */
-                       rlwimi  r11,r4,10,26,31                         /* Move API into pte ID */
-                       add             r5,r7,r5                                        /* Point to the PTEG */
-                       oris    r11,r11,0x8000                          /* Slam on valid bit so's we don't match an invalid one */
-
-                       li              r9,8                                            /* Get the number of PTEs to check */
-                       lwz             r6,0(r5)                                        /* Preload the virtual half */
-                       
-fndpte:                subi    r9,r9,1                                         /* Count the pte */
-                       lwz             r3,4(r5)                                        /* Get the real half */
-                       cmplw   cr1,r6,r11                                      /* Is this what we want? */
-                       lwz             r6,8(r5)                                        /* Start to get the next virtual half */
-                       mr.             r9,r9                                           /* Any more to try? */
-                       addi    r5,r5,8                                         /* Bump to next slot */
-                       beq             cr1,gotxlate                            /* We found what we were looking for... */
-                       bne+    fndpte                                          /* Go try the next PTE... */
-                       
-                       mtmsr   r10                                                     /* Restore state */
-                       li              r3,0                                            /* Show failure */
-                       isync                                                           /* Purge pipe */
-                       blr                                                                     /* Leave... */
-
-gotxlate:      mtmsr   r10                                                     /* Restore state */
-                       rlwimi  r3,r4,0,20,31                           /* Cram in the page displacement */
-                       isync                                                           /* Purge pipe */
-                       blr                                                                     /* Return... */
+hfmReturnC:    stw             r29,0(r25)                                      ; Save the top of the next va
+                       stw             r30,4(r25)                                      ; Save the bottom of the next va
+                       lwz             r0,(FM_ALIGN((31-25+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+                       lwz             r25,FM_ARG0+0x00(r1)            ; Restore a register
+                       lwz             r26,FM_ARG0+0x04(r1)            ; Restore a register
+                       and             r3,r3,r6                                        ; Clear return if the mapping is being removed
+                       lwz             r27,FM_ARG0+0x08(r1)            ; Restore a register
+                       mtlr    r0                                                      ; Restore the return
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore a register
+                       lwz             r29,FM_ARG0+0x10(r1)            ; Restore a register
+                       lwz             r30,FM_ARG0+0x14(r1)            ; Restore a register
+                       lwz             r31,FM_ARG0+0x18(r1)            ; Restore a register
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
+                       
+                       .align  5
+                       
+hfmBadLock:    li              r3,1                                            ; Set lock time out error code
+                       b               hfmReturn                                       ; Leave....
 
+hfmPanic:      lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
 
 
 /*
- *                     struct blokmap *hw_add_blk(pmap_t pmap, struct blokmap *bmr)
- *     
- *                     This is used to add a block mapping entry to the MRU list whose top
- *                     node is anchored at bmaps.  This is a real address and is also used as
- *                     the lock.
- *
- *                     Overlapping areas are not allowed.  If we find one, we return it's address and
- *                     expect the upper layers to panic.  We only check this for a debug build...
+ *                     void hw_clear_maps(void) 
  *
+ *                     Remove all mappings for all phys entries.
+ *     
+ * 
  */
 
                        .align  5
-                       .globl  EXT(hw_add_blk)
+                       .globl  EXT(hw_clear_maps)
 
-LEXT(hw_add_blk)
+LEXT(hw_clear_maps)
+                       mflr    r10                                                     ; Save the link register
+            mfcr       r9                                                      ; Save the condition register
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
 
-                       mfsprg  r9,2                                            ; Get feature flags 
-                       lwz             r6,PMAP_PMAPVR(r3)                      ; Get the v to r translation
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       xor             r3,r3,r6                                        ; Get real address of bmap anchor
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
-                       la              r3,PMAP_BMAPS(r3)                       ; Point to bmap header
-                       
-                       bt              pfNoMSRirb,habNoMSR                     ; No MSR...
+                       lis             r5,hi16(EXT(pmap_mem_regions))          ; Point to the start of the region table
+                       ori             r5,r5,lo16(EXT(pmap_mem_regions))       ; Point to the start of the region table                        
 
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               habNoMSRx
-                       
-habNoMSR:      
-                       mr              r9,r0
-                       mr              r8,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r8
-                       mr              r0,r9
-habNoMSRx:
-                       
-abLck:         lwarx   r9,0,r3                                         ; Get the block map anchor and lock
-                       rlwinm. r8,r9,0,31,31                           ; Is it locked?
-                       ori             r8,r9,1                                         ; Set the lock
-                       bne-    abLckw                                          ; Yeah...
-                       stwcx.  r8,0,r3                                         ; Lock the bmap list
-                       bne-    abLck                                           ; Someone else was trying, try again...
-                       b               abSXg                                           ; All done...
-                       
-                       .align  4
+hcmNextRegion:
+                       lwz             r3,mrPhysTab(r5)                        ; Get the actual table address
+                       lwz             r0,mrStart(r5)                          ; Get start of table entry
+                       lwz             r4,mrEnd(r5)                            ; Get end of table entry
+                       addi    r5,r5,mrSize                            ; Point to the next regions
+
+                       cmplwi  r3,0                                            ; No more regions?
+                       beq--   hcmDone                                         ; Leave...
+
+                       sub             r4,r4,r0                                        ; Calculate physical entry count
+            addi       r4,r4,1
+            mtctr      r4
+
+                       bt++    pf64Bitb,hcmNextPhys64          ; 64-bit version
 
-abLckw:                rlwinm. r5,r9,0,31,31                           ; Check if it is still held
-                       beq+    abLck                                           ; Not no more...
-                       lwz             r9,0(r3)                                        ; Get lock word again...
-                       b               abLckw                                          ; Check it out...
+
+hcmNextPhys32:
+                       lwz             r4,ppLink+4(r3)                         ; Grab the pointer to the first mapping
+            addi       r3,r3,physEntrySize                     ; Next phys_entry
                        
+hcmNextMap32:
+                       rlwinm. r4,r4,0,~ppFlags                        ; Clean and test mapping address
+                       beq             hcmNoMap32                                      ; Did not find one...
+
+                       lwz             r0,mpPte(r4)                            ; Grab the offset to the PTE
+                       rlwinm  r0,r0,0,~mpHValid                       ; Clear out valid bit
+                       stw             r0,mpPte(r4)                            ; Get the quick pointer again
+
+                       lwz             r4,mpAlias+4(r4)                        ; Chain on to the next
+                       b               hcmNextMap32                            ; Check it out...
+hcmNoMap32:
+            bdnz       hcmNextPhys32
+            b          hcmNextRegion
+
+
                        .align  5
+hcmNextPhys64:
+                       li              r0,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       ld              r4,ppLink(r3)                           ; Get the pointer to the first mapping
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+            addi       r3,r3,physEntrySize                     ; Next phys_entry
                        
-                       nop                                                                     ; Force ISYNC to last instruction in IFETCH
-                       nop                                                                     
+hcmNextMap64:
+                       andc.   r4,r4,r0                                        ; Clean and test mapping address
+                       beq             hcmNoMap64                                      ; Did not find one...
 
-abSXg:         rlwinm  r11,r9,0,0,26                           ; Clear out flags and lock
-                       isync                                                           ; Make sure we have not used anything yet
+                       lwz             r0,mpPte(r4)                            ; Grab the offset to the PTE
+                       rlwinm  r0,r0,0,~mpHValid                       ; Clear out valid bit
+                       stw             r0,mpPte(r4)                            ; Get the quick pointer again
 
-;
-;
-;
+                       ld              r4,mpAlias(r4)                          ; Chain on to the next
+                       li              r0,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       b               hcmNextMap64                            ; Check it out...
+hcmNoMap64:
+            bdnz       hcmNextPhys64
+            b          hcmNextRegion
 
-                       lwz             r7,bmstart(r4)                          ; Get start
-                       lwz             r8,bmend(r4)                            ; Get end               
-                       mr              r2,r11                                          ; Get chain
-       
-abChk:         mr.             r10,r2                                          ; End of chain?
-                       beq             abChkD                                          ; Yes, chain is ok...
-                       lwz             r5,bmstart(r10)                         ; Get start of current area
-                       lwz             r6,bmend(r10)                           ; Get end of current area
-                       
-                       cmplw   cr0,r8,r5                                       ; Is the end of the new before the old?
-                       cmplw   cr1,r8,r6                                       ; Is the end of the new after the old?
-                       cmplw   cr6,r6,r7                                       ; Is the end of the old before the new?
-                       cror    cr1_eq,cr0_lt,cr1_gt            ; Set cr1_eq if new not in old
-                       cmplw   cr7,r6,r8                                       ; Is the end of the old after the new?
-                       lwz             r2,bmnext(r10)                          ; Get pointer to the next
-                       cror    cr6_eq,cr6_lt,cr7_gt            ; Set cr2_eq if old not in new
-                       crand   cr1_eq,cr1_eq,cr6_eq            ; Set cr1_eq if no overlap
-                       beq+    cr1,abChk                                       ; Ok check the next...
-                       
-                       lwz             r8,blkFlags(r10)                        ; Get the flags
-                       rlwinm. r8,r8,0,blkRembit,blkRembit     ; Check the blkRem bit
-                       beq             abRet                                           ; Is the mapping partially removed
-                       ori             r10,r10,2                                       ; Indicate that this block is partially removed
-abRet:
-                       stw             r9,0(r3)                                        ; Unlock
-                       mtmsr   r0                                                      ; Restore xlation and rupts
-                       mr              r3,r10                                          ; Pass back the overlap
-                       isync                                                           ;  
-                       blr                                                                     ; Return...
 
-abChkD:                stw             r11,bmnext(r4)                          ; Chain this on in
-                       rlwimi  r4,r9,0,27,31                           ; Copy in locks and flags
-                       sync                                                            ; Make sure that is done
-                       
-                       stw             r4,0(r3)                                        ; Unlock and chain the new first one
-                       mtmsr   r0                                                      ; Restore xlation and rupts
-                       li              r3,0                                            ; Pass back a no failure return code
+                       .align  5
+hcmDone:
+                       mtlr    r10                                                     ; Restore the return
+                       mtcr    r9                                                      ; Restore the condition register
+                       bt++    pf64Bitb,hcmDone64                      ; 64-bit version
+hcmDone32:
+                       mtmsr   r11                                                     ; Restore translation/mode/etc.
                        isync
-                       blr                                                                     ; Return...
+                       blr                                                                     ; Leave...
+
+hcmDone64:
+                       mtmsrd  r11                                                     ; Restore translation/mode/etc.
+                       isync
+                       blr                                                                     ; Leave...
+
 
 
 /*
- *                     struct blokmap *hw_rem_blk(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
- *     
- *                     This is used to remove a block mapping entry from the list that
- *                     is anchored at bmaps.  bmaps is a virtual address and is also used as
- *                     the lock.
+ *                     unsigned int hw_walk_phys(pp, preop, op, postop, parm, opmod) 
+ *                             walks all mapping for a physical page and performs
+ *                             specified operations on each.
  *
- *                     Note that this function clears a single block that contains
- *                     any address within the range sva to eva (inclusive).  To entirely
- *                     clear any range, hw_rem_blk must be called repeatedly until it
- *                     returns a 0.
+ *                     pp is unlocked physent
+ *                     preop is operation to perform on physent before walk.  This would be
+ *                             used to set cache attribute or protection
+ *                     op is the operation to perform on each mapping during walk
+ *                     postop is operation to perform in the phsyent after walk.  this would be
+ *                             used to set or reset the RC bits.
+ *                     opmod modifies the action taken on any connected PTEs visited during
+ *                             the mapping walk.
  *
- *                     The block is removed from the list and all hash table entries
- *                     corresponding to the mapped block are invalidated and the TLB
- *                     entries are purged.  If the block is large, this could take
- *                     quite a while. We need to hash every possible address in the
- *                     range and lock down the PCA.
+ *                     We return the RC bits from before postop is run.
  *
- *                     If we attempt to remove a permanent entry, we will not do it.
- *                     The block address will be ored with 1 and returned.
+ *                     Note that this is designed to be called from 32-bit mode with a stack.
  *
+ *                     We disable translation and all interruptions here.  This keeps is
+ *                     from having to worry about a deadlock due to having anything locked
+ *                     and needing it to process a fault.
  *
+ *                     We lock the physent, execute preop, and then walk each mapping in turn. 
+ *                     If there is a PTE, it is invalidated and the RC merged into the physent.
+ *                     Then we call the op function.
+ *                     Then we revalidate the PTE.
+ *                     Once all all mappings are finished, we save the physent RC and call the 
+ *                     postop routine.  Then we unlock the physent and return the RC.
+ *     
+ * 
  */
 
                        .align  5
-                       .globl  EXT(hw_rem_blk)
-
-LEXT(hw_rem_blk)
-
-                       mfsprg  r9,2                                            ; Get feature flags
-                       lwz             r6,PMAP_PMAPVR(r3)                      ; Get the v to r translation
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       xor             r3,r3,r6                                        ; Get real address of bmap anchor
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
-                       la              r3,PMAP_BMAPS(r3)                       ; Point to the bmap chain head
+                       .globl  EXT(hw_walk_phys)
+
+LEXT(hw_walk_phys)
+                       stwu    r1,-(FM_ALIGN((31-24+1)*4)+FM_SIZE)(r1) ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r24,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x08(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x0C(r1)            ; Save a register
+                       mr              r24,r8                                          ; Save the parm
+                       mr              r25,r7                                          ; Save the parm
+                       stw             r28,FM_ARG0+0x10(r1)            ; Save a register
+                       stw             r29,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x1C(r1)            ; Save a register
+                       stw             r0,(FM_ALIGN((31-24+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
+                       
+                       mfsprg  r26,0                                           ; (INSTRUMENTATION)
+                       lwz             r27,hwWalkPhys(r26)                     ; (INSTRUMENTATION)
+                       addi    r27,r27,1                                       ; (INSTRUMENTATION)
+                       stw             r27,hwWalkPhys(r26)                     ; (INSTRUMENTATION)
+                       la              r26,hwWalkFull(r26)                     ; (INSTRUMENTATION)
+                       slwi    r12,r24,2                                       ; (INSTRUMENTATION)
+                       lwzx    r27,r26,r12                                     ; (INSTRUMENTATION)
+                       addi    r27,r27,1                                       ; (INSTRUMENTATION)
+                       stwx    r27,r26,r12                                     ; (INSTRUMENTATION)
+               
+                       mr              r26,r11                                         ; Save the old MSR
+                       lis             r27,hi16(hwpOpBase)                     ; Get high order of op base
+                       slwi    r4,r4,7                                         ; Convert preop to displacement
+                       ori             r27,r27,lo16(hwpOpBase)         ; Get low order of op base
+                       slwi    r5,r5,7                                         ; Convert op to displacement
+                       add             r12,r4,r27                                      ; Point to the preop routine
+                       slwi    r28,r6,7                                        ; Convert postop to displacement
+                       mtctr   r12                                                     ; Set preop routine     
+                       add             r28,r28,r27                                     ; Get the address of the postop routine
+                       add             r27,r5,r27                                      ; Get the address of the op routine                     
 
-                       bt              pfNoMSRirb,hrbNoMSR                     ; No MSR...
+                       bl              mapPhysLock                                     ; Lock the physent
 
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hrbNoMSRx
+                       mr              r29,r3                                          ; Save the physent address
                        
-hrbNoMSR:      
-                       mr              r9,r0
-                       mr              r8,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r8
-                       mr              r0,r9
-hrbNoMSRx:
-                       li              r7,0
-                       cmp             cr5,r0,r7                                       ; Request to invalidate the ptes
-                       b               rbLck
-
-rbunlink:
-                       lwz             r4,bmstart(r10)                         ; Get start of current mapping
-                       lwz             r5,bmend(r10)                           ; Get end of current mapping
-                       cmp             cr5,r3,r3                                       ; Request to unlink the mapping
+                       bt++    pf64Bitb,hwp64                          ; skip if 64-bit (only they take the hint)
+                       
+                       bctrl                                                           ; Call preop routine
+                       bne-    hwpEarly32                                      ; preop says to bail now...
 
-rbLck:         lwarx   r9,0,r3                                         ; Get the block map anchor and lock
-                       rlwinm. r8,r9,0,31,31                           ; Is it locked?
-                       ori             r8,r9,1                                         ; Set the lock
-                       bne-    rbLckw                                          ; Yeah...
-                       stwcx.  r8,0,r3                                         ; Lock the bmap list
-                       bne-    rbLck                                           ; Someone else was trying, try again...
-                       b               rbSXg                                           ; All done...
+                       cmplwi  r24,hwpMergePTE                         ; Classify operation modifier                   
+                       mtctr   r27                                                     ; Set up the op function address
+                       lwz             r31,ppLink+4(r3)                        ; Grab the pointer to the first mapping
+                       blt             hwpSrc32                                        ; Do TLB invalidate/purge/merge/reload for each mapping
+                       beq             hwpMSrc32                                       ; Do TLB merge for each mapping
+                       
+hwpQSrc32:     rlwinm. r31,r31,0,~ppFlags                      ; Clean and test mapping address
+                       beq             hwpNone32                                       ; Did not find one...
                        
-                       .align  4
+                       bctrl                                                           ; Call the op function
+                       
+                       bne-    hwpEarly32                                      ; op says to bail now...
+                       lwz             r31,mpAlias+4(r31)                      ; Chain on to the next
+                       b               hwpQSrc32                                       ; Check it out...
 
-rbLckw:                rlwinm. r11,r9,0,31,31                          ; Check if it is still held
-                       beq+    rbLck                                           ; Not no more...
-                       lwz             r9,0(r3)                                        ; Get lock word again...
-                       b               rbLckw                                          ; Check it out...
+                       .align  5                       
+hwpMSrc32:     rlwinm. r31,r31,0,~ppFlags                      ; Clean and test mapping address
+                       beq             hwpNone32                                       ; Did not find one...
                        
-                       .align  5
+                       bl              mapMergeRC32                            ; Merge reference and change into mapping and physent
+                       bctrl                                                           ; Call the op function
                        
-                       nop                                                                     ; Force ISYNC to last instruction in IFETCH
-                       nop                                                                     
+                       bne-    hwpEarly32                                      ; op says to bail now...
+                       lwz             r31,mpAlias+4(r31)                      ; Chain on to the next
+                       b               hwpMSrc32                                       ; Check it out...
 
-rbSXg:         rlwinm. r2,r9,0,0,26                            ; Clear out flags and lock
-                       mr              r10,r3                                          ; Keep anchor as previous pointer
-                       isync                                                           ; Make sure we have not used anything yet
+                       .align  5                       
+hwpSrc32:      rlwinm. r31,r31,0,~ppFlags                      ; Clean and test mapping address
+                       beq             hwpNone32                                       ; Did not find one...
+                                               
+;
+;                      Note: mapInvPte32 returns the PTE in R3 (or 0 if none), PTE high in R4, 
+;                      PTE low in R5.  The PCA address is in R7.  The PTEG come back locked.
+;                      If there is no PTE, PTE low is obtained from mapping
+;
+                       bl              mapInvPte32                                     ; Invalidate and lock PTE, also merge into physent
+               
+                       bctrl                                                           ; Call the op function
+
+                       crmove  cr1_eq,cr0_eq                           ; Save the return code
+                                               
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+                       beq-    hwpNxt32                                        ; Nope...
                        
-                       beq-    rbMT                                            ; There is nothing in the list
+                       stw             r5,4(r3)                                        ; Store second half of PTE
+                       eieio                                                           ; Make sure we do not reorder
+                       stw             r4,0(r3)                                        ; Revalidate the PTE
                        
-rbChk:         mr              r12,r10                                         ; Save the previous
-                       mr.             r10,r2                                          ; End of chain?
-                       beq             rbMT                                            ; Yes, nothing to do...
-                       lwz             r11,bmstart(r10)                        ; Get start of current area
-                       lwz             r6,bmend(r10)                           ; Get end of current area
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock the PCA
                        
-                       cmplw   cr0,r5,r11                                      ; Is the end of range before the start of the area?
-                       cmplw   cr1,r4,r6                                       ; Is the start of range after the end of the area?
-                       cror    cr1_eq,cr0_lt,cr1_gt            ; Set cr1_eq if new not in range
-                       lwz             r2,bmnext(r10)                          ; Get the next one
-                       beq+    cr1,rbChk                                       ; Not this one, check the next...
+hwpNxt32:      bne-    cr1,hwpEarly32                          ; op says to bail now...
+                       lwz             r31,mpAlias+4(r31)                      ; Chain on to the next
+                       b               hwpSrc32                                        ; Check it out...
 
-                       cmplw   cr1,r12,r3                                      ; Is the current mapping the first one?
-
-                       bne             cr5,rbblkRem                            ; Do we have to unchain the mapping
+                       .align  5
 
-                       bne             cr1,rbnFirst                            ; Yes, is this the first mapping?
-                       rlwimi  r9,r2,0,0,26                            ; Yes, Change the lock value
-                       ori             r2,r9,1                                         ; Turn on the lock bit
-rbnFirst:
-                       stw             r2,bmnext(r12)                          ; Unchain us
-                       sync
-                       b               rbDone
+hwpNone32:     mtctr   r28                                                     ; Get the post routine address
+                       
+                       lwz             r30,ppLink+4(r29)                       ; Save the old RC
+                       mr              r3,r29                                          ; Get the physent address
+                       bctrl                                                           ; Call post routine
 
-rbblkRem:
-               
-                       lwz             r8,blkFlags(r10)                        ; Get the flags
+                       bl              mapPhysUnlock                           ; Unlock the physent
                        
-                       rlwinm. r7,r8,0,blkPermbit,blkPermbit   ; is this a permanent block?
+                       mtmsr   r26                                                     ; Restore translation/mode/etc.
+                       isync
                        
-                       bne-    rbPerm                                          ; This is permanent, do not remove...
+                       b               hwpReturn                                       ; Go restore registers and return...
 
-                       rlwinm. r7,r8,0,blkRembit,blkRembit     ; is this mapping partially removed
+                       .align  5
 
-                       beq             rbblkRemcont                            ; If not, check the max size
-                       lwz             r11,bmcurrent(r10)                      ; If yes, resume for the current page
+hwpEarly32:    lwz             r30,ppLink+4(r29)                       ; Save the old RC
+                       mr              r3,r29                                          ; Get the physent address
+                       bl              mapPhysUnlock                           ; Unlock the physent
+                       
+                       mtmsr   r26                                                     ; Restore translation/mode/etc.
+                       isync
+                       
+                       b               hwpReturn                                       ; Go restore registers and return...
 
-                       cmp             cr5,r11,r6                                      ; No partial remove left
-                       beq             cr5, rbpendret                          ; But there is  a pending remove
+                       .align  5
+               
+hwp64:         bctrl                                                           ; Call preop routine
+                       bne--   hwpEarly64                                      ; preop says to bail now...
+                       
+                       cmplwi  r24,hwpMergePTE                         ; Classify operation modifier                   
+                       mtctr   r27                                                     ; Set up the op function address
+                       
+                       li              r24,ppLFAmask
+                       ld              r31,ppLink(r3)                          ; Get the pointer to the first mapping
+                       rotrdi  r24,r24,ppLFArrot                       ; Rotate clean up mask to get 0xF0000000000000000F
+                       blt             hwpSrc64                                        ; Do TLB invalidate/purge/merge/reload for each mapping
+                       beq             hwpMSrc64                                       ; Do TLB merge for each mapping
+                       
+hwpQSrc64:     andc.   r31,r31,r24                                     ; Clean and test mapping address
+                       beq             hwpNone64                                       ; Did not find one...
 
-rbblkRemcont:
-                       bne             rbblkRemcont1                           ; Is it the first remove
+                       bctrl                                                           ; Call the op function
 
-                       oris    r8,r8,hi16(blkRem)                      ; Yes
-                       stw             r8,blkFlags(r10)                        ; set the blkRem bit in blkFlags
+                       bne--   hwpEarly64                                      ; op says to bail now...
+                       ld              r31,mpAlias(r31)                        ; Chain on to the next
+                       b               hwpQSrc64                                       ; Check it out...
 
-rbblkRemcont1:
-                       lis             r5,hi16(BLKREMMAX*4096)                 ; Load maximun size tear down
-                       ori             r5,r5,lo16(BLKREMMAX*4096)              ; Load maximun size tear down
-                       sub             r7,r6,r11                                       ; Get the remaining size to tear down
-                       cmp             cr5,r7,r5                                       ; Compare against the maximun size
-                       ble             cr5,rbfullblk                           ; If less or equal, go remove the mapping
+                       .align  5                       
+hwpMSrc64:     andc.   r31,r31,r24                                     ; Clean and test mapping address
+                       beq             hwpNone64                                       ; Did not find one...
 
-                       add             r7,r11,r5                                       ; Add the max size tear down to the current page
-                       stw             r7,bmcurrent(r10)                       ; Update the current page
-                       subi    r6,r7,1                                         ; Set the current end of the partial tear down
-                       b               rbcont
+                       bl              mapMergeRC64                            ; Merge reference and change into mapping and physent
+                       bctrl                                                           ; Call the op function
 
-rbfullblk:
-                       stw             r6,bmcurrent(r10)                       ; Update the current page
+                       bne--   hwpEarly64                                      ; op says to bail now...
+                       ld              r31,mpAlias(r31)                        ; Chain on to the next
+                       b               hwpMSrc64                                       ; Check it out...
 
-rbcont:
-                       lwz             r8,bmspace(r10)                         ; Get the VSID
-                       sync
-                       stw             r9,0(r3)                                        ; Unlock and chain the new first one
-                       
-                       eqv             r4,r4,r4                                        ; Fill the bottom with foxes
-                       mfspr   r12,sdr1                                        ; Get hash table base and size
-                       rlwinm  r8,r8,6,0,25                            ; Align VSID to PTEG
-                       rlwimi  r4,r12,16,0,15                          ; Make table size - 1 out of mask
-                       andc    r12,r12,r4                                      ; Clean up address of hash table
-                       rlwinm  r5,r11,26,6,25                          ; Rotate virtual start address into PTEG units
-                       add             r12,r12,r4                                      ; Point to PCA - 1
-                       rlwinm  r6,r6,26,6,25                           ; Rotate virtual end address into PTEG units
-                       addi    r12,r12,1                                       ; Point to PCA base
-                       sub             r6,r6,r5                                        ; Get the total number of PTEGs to clear
-                       cmplw   r6,r4                                           ; See if this wraps all the way around
-                       blt             rbHash                                          ; Nope, length is right
-                       subi    r6,r4,32+31                                     ; Back down to correct length
-                       
-rbHash:                rlwinm  r5,r5,0,10,25                           ; Keep only the page index
-                       xor             r2,r8,r5                                        ; Hash into table
-                       and             r2,r2,r4                                        ; Wrap into the table
-                       add             r2,r2,r12                                       ; Point right at the PCA
-
-rbLcka:                lwarx   r7,0,r2                                         ; Get the PTEG lock
-                       mr.             r7,r7                                           ; Is it locked?
-                       bne-    rbLckwa                                         ; Yeah...
-                       li              r7,1                                            ; Get the locked value
-                       stwcx.  r7,0,r2                                         ; Take it
-                       bne-    rbLcka                                          ; Someone else was trying, try again...
-                       b               rbSXga                                          ; All done... 
-
-rbLckwa:       mr.             r7,r7                                           ; Check if it is already held
-                       beq+    rbLcka                                          ; It is clear...
-                       lwz             r7,0(r2)                                        ; Get lock word again...
-                       b               rbLckwa                                         ; Wait...
-                       
-rbSXga:                isync                                                           ; Make sure nothing used yet
-                       lwz             r7,PCAallo(r2)                          ; Get the allocation word
-                       rlwinm. r11,r7,8,0,7                            ; Isolate the autogenerated PTEs
-                       or              r7,r7,r11                                       ; Release the autogen slots
-                       beq+    rbAintNone                                      ; There are not any here
-                       mtcrf   0xC0,r11                                        ; Set the branch masks for autogens
-                       sub             r11,r2,r4                                       ; Move back to the hash table + 1
-                       rlwinm  r7,r7,0,16,7                            ; Clear the autogen field
-                       subi    r11,r11,1                                       ; Point to the PTEG
-                       stw             r7,PCAallo(r2)                          ; Update the flags
-                       li              r7,0                                            ; Get an invalid PTE value
-
-                       bf              0,rbSlot1                                       ; No autogen here
-                       stw             r7,0x00(r11)                            ; Invalidate PTE
-rbSlot1:       bf              1,rbSlot2                                       ; No autogen here
-                       stw             r7,0x08(r11)                            ; Invalidate PTE
-rbSlot2:       bf              2,rbSlot3                                       ; No autogen here
-                       stw             r7,0x10(r11)                            ; Invalidate PTE
-rbSlot3:       bf              3,rbSlot4                                       ; No autogen here
-                       stw             r7,0x18(r11)                            ; Invalidate PTE
-rbSlot4:       bf              4,rbSlot5                                       ; No autogen here
-                       stw             r7,0x20(r11)                            ; Invalidate PTE
-rbSlot5:       bf              5,rbSlot6                                       ; No autogen here
-                       stw             r7,0x28(r11)                            ; Invalidate PTE
-rbSlot6:       bf              6,rbSlot7                                       ; No autogen here
-                       stw             r7,0x30(r11)                            ; Invalidate PTE
-rbSlot7:       bf              7,rbSlotx                                       ; No autogen here
-                       stw             r7,0x38(r11)                            ; Invalidate PTE
-rbSlotx:
-
-rbAintNone:    li              r7,0                                            ; Clear this out
-                       sync                                                            ; To make SMP happy
-                       addic.  r6,r6,-64                                       ; Decrement the count
-                       stw             r7,PCAlock(r2)                          ; Release the PTEG lock
-                       addi    r5,r5,64                                        ; Move up by adjusted page number
-                       bge+    rbHash                                          ; Not done...
-       
-                       sync                                                            ; Make sure the memory is quiet
-                       
+                       .align  5                       
+hwpSrc64:      andc.   r31,r31,r24                                     ; Clean and test mapping address
+                       beq             hwpNone64                                       ; Did not find one...
 ;
-;                      Here we take the easy way out and just purge the entire TLB. This is 
-;                      certainly faster and definitly easier than blasting just the correct ones
-;                      in the range, we only need one lock and one TLBSYNC. We would hope
-;                      that most blocks are more than 64 pages (256K) and on every machine
-;                      up to Book E, 64 TLBIEs will invalidate the entire table.
+;                      Note: mapInvPte64 returns the PTE in R3 (or 0 if none), PTE high in R4, 
+;                      PTE low in R5. PTEG comes back locked if there is one
 ;
+                       bl              mapInvPte64                                     ; Invalidate and lock PTEG, also merge into physent
 
-                       li              r5,64                                           ; Get number of TLB entries to purge
-                       lis             r12,HIGH_ADDR(EXT(tlb_system_lock))     ; Get the TLBIE lock
-                       li              r6,0                                            ; Start at 0
-                       ori             r12,r12,LOW_ADDR(EXT(tlb_system_lock))  ; Grab up the bottom part
-                                               
-rbTlbL:                lwarx   r2,0,r12                                        ; Get the TLBIE lock
-                       mr.             r2,r2                                           ; Is it locked?
-                       li              r2,1                                            ; Get our lock value
-                       bne-    rbTlbL                                          ; It is locked, go wait...
-                       stwcx.  r2,0,r12                                        ; Try to get it
-                       bne-    rbTlbL                                          ; We was beat...
-       
-rbTlbN:                addic.  r5,r5,-1                                        ; See if we did them all
-                       tlbie   r6                                                      ; Invalidate it everywhere
-                       addi    r6,r6,0x1000                            ; Up to the next page
-                       bgt+    rbTlbN                                          ; Make sure we have done it all...
+                       bctrl                                                           ; Call the op function
+
+                       crmove  cr1_eq,cr0_eq                           ; Save the return code
                        
-                       mfspr   r5,pvr                                          ; Find out what kind of machine we are
-                       li              r2,0                                            ; Lock clear value
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+                       beq--   hwpNxt64                                        ; Nope...
                        
-                       rlwinm  r5,r5,16,16,31                          ; Isolate CPU type
-                       cmplwi  r5,3                                            ; Is this a 603?
-                       sync                                                            ; Make sure all is quiet
-                       beq-    rbits603a                                       ; It is a 603, skip the tlbsync...
+                       std             r5,8(r3)                                        ; Save bottom of PTE
+                       eieio                                                           ; Make sure we do not reorder 
+                       std             r4,0(r3)                                        ; Revalidate the PTE
                        
-                       eieio                                                           ; Make sure that the tlbie happens first
-                       tlbsync                                                         ; wait for everyone to catch up
-                       isync                                                           
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock the PCA
 
-rbits603a:     sync                                                            ; Wait for quiet again
-                       stw             r2,0(r12)                                       ; Unlock invalidates
+hwpNxt64:      bne--   cr1,hwpEarly64                          ; op says to bail now...
+                       ld              r31,mpAlias(r31)                        ; Chain on to the next
+                       b               hwpSrc64                                        ; Check it out...
+       
+                       .align  5
                        
-                       sync                                                            ; Make sure that is done
+hwpNone64:     mtctr   r28                                                     ; Get the post routine address
                        
-                       ble             cr5,rbunlink                            ; If all ptes are flush, go unlink the mapping
-                       mtmsr   r0                                                      ; Restore xlation and rupts
-                       mr              r3,r10                                          ; Pass back the removed block in progress
-                       ori             r3,r3,2                                         ; Indicate that the block remove isn't completed yet
-                       isync
-                       blr                                                                     ; Return...
+                       lwz             r30,ppLink+4(r29)                       ; Save the old RC
+                       mr              r3,r29                                          ; Get the physent address
+                       bctrl                                                           ; Call post routine
 
-rbpendret:
-                       stw             r9,0(r3)                                        ; Unlock
-                       mtmsr   r0                                                      ; Restore xlation and rupts
-                       mr              r3,r10                                          ; Pass back the removed block in progress
-                       ori             r3,r3,2                                         ; Indicate that the block remove isn't completed yet
+                       bl              mapPhysUnlock                           ; Unlock the physent
+                       
+                       mtmsrd  r26                                                     ; Restore translation/mode/etc.
                        isync
-                       blr                                                                     ; Return...
+                       b               hwpReturn                                       ; Go restore registers and return...
 
+                       .align  5
 
-rbMT:          stw             r9,0(r3)                                        ; Unlock
-                       mtmsr   r0                                                      ; Restore xlation and rupts
-                       li              r3,0                                            ; Say we did not find one
-                       isync
-                       blr                                                                     ; Return...
-                       
-rbPerm:                stw             r9,0(r3)                                        ; Unlock
-                       mtmsr   r0                                                      ; Restore xlation and rupts
-                       ori             r3,r10,1                                        ; Say we did not remove it
-                       isync
-                       blr                                                                     ; Return...
+hwpEarly64:    lwz             r30,ppLink+4(r29)                       ; Save the old RC
+                       mr              r3,r29                                          ; Get the physent address
+                       bl              mapPhysUnlock                           ; Unlock the physent
+                       
+                       mtmsrd  r26                                                     ; Restore translation/mode/etc.
+                       isync                   
+
+hwpReturn:     lwz             r0,(FM_ALIGN((31-24+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Restore the return
+                       lwz             r24,FM_ARG0+0x00(r1)            ; Restore a register
+                       lwz             r25,FM_ARG0+0x04(r1)            ; Restore a register
+                       lwz             r26,FM_ARG0+0x08(r1)            ; Restore a register
+                       mr              r3,r30                                          ; Pass back the RC
+                       lwz             r27,FM_ARG0+0x0C(r1)            ; Restore a register
+                       lwz             r28,FM_ARG0+0x10(r1)            ; Restore a register
+                       mtlr    r0                                                      ; Restore the return
+                       lwz             r29,FM_ARG0+0x14(r1)            ; Restore a register
+                       lwz             r30,FM_ARG0+0x18(r1)            ; Restore a register
+                       lwz             r31,FM_ARG0+0x1C(r1)            ; Restore a register
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
 
-rbDone:                stw     r9,0(r3)                                        ; Unlock
-                       mtmsr   r0                                                      ; Restore xlation and rupts
-                       mr      r3,r10                                          ; Pass back the removed block
-                       isync
-                       blr                                                                     ; Return...
 
-/*
- *                     hw_select_mappings(struct mappingflush *mappingflush)
- *
- *                     Input: PCA addr
- *                     Ouput: up to 8 user mappings
- *
- *                     hw_select_mappings() scans every PCA mapping hash lists and select
- *                     the last user mapping if it exists.
- *
- */
+;
+;                      The preop/op/postop function table.
+;                      Each function must be 64-byte aligned and be no more than
+;                      16 instructions.  If more than 16, we must fix address calculations
+;                      at the start of hwpOpBase
+;
+;                      The routine must set CR0_EQ in order to continue scan.
+;                      If CR0_EQ is not set, an early return from the function is made.
+;
 
-                       .align  5
-                       .globl  EXT(hw_select_mappings)
+                       .align  7
+                       
+hwpOpBase:
 
-LEXT(hw_select_mappings)
-                       mr              r5,r3                                           ; Get the mapping flush addr
-                       mfmsr   r12                                                     ; Get the MSR 
-                       rlwinm  r12,r12,0,MSR_FP_BIT+1,MSR_FP_BIT-1     ; Force floating point off
-                       rlwinm  r12,r12,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1   ; Force vectors off
-                       mfsprg  r9,2                                            ; Get feature flags
-                       andi.   r0,r12,0x7FCF                           ; Disable translation and interruptions
-                       mtcrf   0x04,r9                                         ; Set the features
-                       bt              pfNoMSRirb,hvmNoMSR                     ; No MSR...
-                       mtmsr   r0
-                       isync
-                       b               hvmNoMSRx
-hvmNoMSR:
-                       mr              r3,r0                                           ; Get the new MSR
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       sc
-hvmNoMSRx:
-                       mr              r0,r12
-                       li              r11,1                                           ; Get the locked value 
-
-hvmptegLckx:   
-                       lwz             r3,MFpcaptr(r5)                         ; Get the PCA pointer
-                       lwarx   r10,0,r3                                        ; Get the PTEG lock
-                       mr.             r10,r10                                         ; Is it locked?
-                       bne-    hvmptegLckwx                            ; Yeah...
-                       stwcx.  r11,0,r3                                        ; Take take it
-                       bne-    hvmptegLckx                                     ; Someone else was trying, try again...
-                       b               hvmptegSXgx                                     ; All done...
-
-                       .align  4
-
-hvmptegLckwx:
-                       mr.             r10,r10                                         ; Check if it is already held
-                       beq+    hvmptegLckx                                     ; It's clear...
-                       lwz             r10,0(r3)                                       ; Get lock word again...
-                       b               hvmptegLckwx                            ; Wait...
-
-                       .align  4
-
-hvmptegSXgx:
-                       isync                                                           ; Make sure we haven't used anything yet
-
-                       li              r11,8                                           ; set count to 8 
-
-                       lwz             r6,PCAhash(r3)                          ; load the first mapping hash list
-                       la              r12,PCAhash(r3)                         ; Point to the mapping hash area
-                       la              r4,MFmapping(r5)                        ; Point to the mapping flush mapping area
-                       li              r7,0                                            ; Load zero
-                       stw             r7,MFmappingcnt(r5)                     ; Set the current count to 0
-hvmnexthash:
-                       li              r10,0                                           ; Mapping test
-
-hvmfindmap:
-                       mr.             r6,r6                                           ; Test if the hash list current pointer is zero
-                       beq             hvmfindmapret                           ; Did we hit the end of the hash list
-                       lwz             r7,mmPTEv(r6)                           ; Pick up our virtual ID
-                       rlwinm  r8,r7,5,0,19                            ; Pick VSID 20 lower bits
-                       mr.             r8,r8
-                       beq             hvmfindmapnext                          ; Skip Kernel VSIDs
-                       rlwinm  r8,r7,1,0,3                                     ; Extract the Segment index 
-                       rlwinm  r9,r7,22,4,9                            ; Extract API 6 upper bits
-                       or              r8,r8,r9                                        ; Add to the virtual address
-                       rlwinm  r9,r7,31,6,25                           ; Pick VSID 19 lower bits
-                       xor             r9,r9,r3                                        ; Exclusive or with the PCA address
-                       rlwinm  r9,r9,6,10,19                           ; Extract API 10 lower bits
-                       or              r8,r8,r9                                        ; Add to the virtual address
-
-                       stw             r8,4(r4)                                        ; Store the virtual address
-                       lwz             r8,mmpmap(r6)                           ; Get the pmap
-                       stw             r8,0(r4)                                        ; Store the pmap
-                       li              r10,1                                           ; Found one
-
-hvmfindmapnext:
-                       lwz             r6,mmhashnext(r6)                       ; Pick up next mapping block
-                       b               hvmfindmap                                      ; Scan the next mapping
-hvmfindmapret:
-                       mr.             r10,r10                                         ; Found mapping
-                       beq             hvmnexthashprep                         ; If not, do not update the mappingflush array
-                       lwz             r7,MFmappingcnt(r5)                     ; Get the current count
-                       addi    r7,r7,1                                         ; Increment the current count
-                       stw             r7,MFmappingcnt(r5)                     ; Store the current count
-                       addi    r4,r4,MFmappingSize                     ; Point to the next mapping flush entry
-hvmnexthashprep:
-                       addi    r12,r12,4                                       ; Load the next hash list
-                       lwz             r6,0(r12)                                       ; Load the next hash list entry
-                       subi    r11,r11,1                                       ; Decrement hash list index 
-                       mr.             r11,r11                                         ; Test for a remaining hash list
-                       bne             hvmnexthash                                     ; Loop to scan the next hash list
-
-                       li              r10,0
-                       stw             r10,0(r3)                                       ; Unlock the hash list
-                       mtmsr   r0                                                      ; Restore translation and interruptions
-                       isync
-                       blr
+;                      Function 0 - No operation
 
-/*
- *                     vm_offset_t hw_cvp_blk(pmap_t pmap, vm_offset_t va)
- *     
- *                     This is used to translate a virtual address within a block mapping entry
- *                     to a physical address.  If not found, 0 is returned.
- *
- */
+hwpNoop:       cmplw   r0,r0                                           ; Make sure CR0_EQ is set
+                       blr                                                                     ; Just return...
 
                        .align  5
-                       .globl  EXT(hw_cvp_blk)
-
-LEXT(hw_cvp_blk)
 
-                       mfsprg  r9,2                                            ; Get feature flags
-                       lwz             r6,PMAP_PMAPVR(r3)                      ; Get the v to r translation
-                       mfmsr   r0                                                      /* Save the MSR  */
-                       rlwinm  r0,r0,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       rlwinm  r0,r0,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       rlwinm  r12,r0,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Clear interruptions */
-                       mtcrf   0x04,r9                                         ; Set the features                      
-                       xor             r3,r3,r6                                        ; Get real address of bmap anchor
-                       rlwinm  r12,r12,0,28,25                         /* Clear IR and DR */
-                       la              r3,PMAP_BMAPS(r3)                       ; Point to chain header
+;                      This is the continuation of function 4 - Set attributes in mapping
 
-                       bt              pfNoMSRirb,hcbNoMSR                     ; No MSR...
+;                      We changed the attributes of a mapped page.  Make sure there are no cache paradoxes.
+;                      NOTE: Do we have to deal with i-cache here?
 
-                       mtmsr   r12                                                     ; Translation and all off
-                       isync                                                           ; Toss prefetch
-                       b               hcbNoMSRx
-                       
-hcbNoMSR:      
-                       mr              r9,r0
-                       mr              r8,r3
-                       li              r0,loadMSR                                      ; Get the MSR setter SC
-                       mr              r3,r12                                          ; Get new MSR
-                       sc                                                                      ; Set it
-                       mr              r3,r8
-                       mr              r0,r9
-hcbNoMSRx:
-
-cbLck:         lwarx   r9,0,r3                                         ; Get the block map anchor and lock
-                       rlwinm. r8,r9,0,31,31                           ; Is it locked?
-                       ori             r8,r9,1                                         ; Set the lock
-                       bne-    cbLckw                                          ; Yeah...
-                       stwcx.  r8,0,r3                                         ; Lock the bmap list
-                       bne-    cbLck                                           ; Someone else was trying, try again...
-                       b               cbSXg                                           ; All done...
-                       
-                       .align  4
-
-cbLckw:                rlwinm. r5,r9,0,31,31                           ; Check if it is still held
-                       beq+    cbLck                                           ; Not no more...
-                       lwz             r9,0(r3)                                        ; Get lock word again...
-                       b               cbLckw                                          ; Check it out...
-                       
-                       .align  5
-                       
-                       nop                                                                     ; Force ISYNC to last instruction in IFETCH
-                       nop
-                       nop
-                       nop
-                       nop
-
-cbSXg:         rlwinm. r11,r9,0,0,26                           ; Clear out flags and lock
-                       li              r2,0                                            ; Assume we do not find anything                        
-                       isync                                                           ; Make sure we have not used anything yet
-
-cbChk:         mr.             r11,r11                                         ; Is there more?
-                       beq-    cbDone                                          ; No more...
-                       lwz             r5,bmstart(r11)                         ; Get the bottom of range
-                       lwz             r12,bmend(r11)                          ; Get the top of range
-                       cmplw   cr0,r4,r5                                       ; Are we before the entry?
-                       cmplw   cr1,r4,r12                                      ; Are we after of the entry?
-                       cror    cr1_eq,cr0_lt,cr1_gt            ; Set cr1_eq if new not in range
-                       beq-    cr1,cbNo                                        ; We are not in the range...
-
-                       lwz             r2,bmPTEr(r11)                          ; Get the real part of the PTE
-                       sub             r5,r4,r5                                        ; Get offset into area
-                       rlwinm  r2,r2,0,0,19                            ; Clean out everything but the page
-                       add             r2,r2,r5                                        ; Adjust the real address
-
-cbDone:                stw             r9,0(r3)                                        ; Unlock it, we are done with it (no sync needed)
-                       mtmsr   r0                                                      ; Restore translation and interrupts...
-                       isync                                                           ; Make sure it is on
-                       mr              r3,r2                                           ; Set return physical address
-                       blr                                                                     ; Leave...
+hwpSAM:                li              r11,4096                                        ; Get page size
                        
-                       .align  5
+hwpSAMinvd:    sub.    r11,r11,r9                                      ; Back off a line
+                       dcbf    r11,r5                                          ; Flush the line in the data cache
+                       bgt++   hwpSAMinvd                                      ; Go do the rest of it...
                        
-cbNo:          lwz             r11,bmnext(r11)                         ; Link next
-                       b               cbChk                                           ; Check it out...
+                       sync                                                            ; Make sure it is done
+
+                       li              r11,4096                                        ; Get page size
                        
+hwpSAMinvi:    sub.    r11,r11,r9                                      ; Back off a line
+                       icbi    r11,r5                                          ; Flush the line in the icache
+                       bgt++   hwpSAMinvi                                      ; Go do the rest of it...
                        
-/*
- *                     hw_set_user_space(pmap) 
- *                     hw_set_user_space_dis(pmap) 
- *
- *                     Indicate whether memory space needs to be switched.
- *                     We really need to turn off interrupts here, because we need to be non-preemptable
- *
- *                     hw_set_user_space_dis is used when interruptions are already disabled. Mind the
- *                     register usage here.   The VMM switch code in vmachmon.s that calls this
- *                     know what registers are in use.  Check that if these change.
- */
+                       sync                                                            ; Make sure it is done
 
+                       cmpw    r0,r0                                           ; Make sure we return CR0_EQ
+                       blr                                                                     ; Return...
 
-       
-                       .align  5
-                       .globl  EXT(hw_set_user_space)
-
-LEXT(hw_set_user_space)
 
-                       mfmsr   r10                                                     /* Get the current MSR */
-                       rlwinm  r10,r10,0,MSR_FP_BIT+1,MSR_FP_BIT-1     ; Force floating point off
-                       rlwinm  r10,r10,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1   ; Force vectors off
-                       rlwinm  r9,r10,0,MSR_EE_BIT+1,MSR_EE_BIT-1      /* Turn off 'rupts */
-                       mtmsr   r9                                                      /* Disable 'em */
-                       lwz             r7,PMAP_PMAPVR(r3)                      ; Get the v to r translation
-                       lwz             r4,PMAP_SPACE(r3)                       ; Get the space
-                       mfsprg  r6,0                                            /* Get the per_proc_info address */
-                       xor             r3,r3,r7                                        ; Get real address of bmap anchor
-                       stw             r4,PP_USERSPACE(r6)                     /* Show our new address space */
-                       stw             r3,PP_USERPMAP(r6)                      ; Show our real pmap address
-                       mtmsr   r10                                                     /* Restore interruptions */
-                       blr                                                                     /* Return... */
-       
-                       .align  5
-                       .globl  EXT(hw_set_user_space_dis)
+;                      Function 1 - Set protection in physent (obsolete)
 
-LEXT(hw_set_user_space_dis)
+                       .set    .,hwpOpBase+(1*128)                     ; Generate error if previous function too long
 
-                       lwz             r7,PMAP_PMAPVR(r3)                      ; Get the v to r translation
-                       lwz             r4,PMAP_SPACE(r3)                       ; Get the space
-                       mfsprg  r6,0                                            ; Get the per_proc_info address
-                       xor             r3,r3,r7                                        ; Get real address of bmap anchor
-                       stw             r4,PP_USERSPACE(r6)                     ; Show our new address space
-                       stw             r3,PP_USERPMAP(r6)                      ; Show our real pmap address
+hwpSPrtPhy: cmplw      r0,r0                                           ; Make sure we return CR0_EQ
                        blr                                                                     ; Return...
-       
+                       
 
-/*                     struct mapping *hw_cpv(struct mapping *mp) - Converts a physcial mapping CB address to virtual
- *
- */
+;                      Function 2 - Set protection in mapping
 
-                       .align  5
-                       .globl  EXT(hw_cpv)
+;                      NOTE: Changes to no-execute permission are ignored
 
-LEXT(hw_cpv)
-                       
-                       rlwinm. r4,r3,0,0,19                            ; Round back to the mapping block allocation control block
-                       mfmsr   r10                                                     ; Get the current MSR
-                       beq-    hcpvret                                         ; Skip if we are passed a 0...
-                       rlwinm  r10,r10,0,MSR_FP_BIT+1,MSR_FP_BIT-1     ; Force floating point off
-                       rlwinm  r10,r10,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1   ; Force vectors off
-                       andi.   r9,r10,0x7FEF                           ; Turn off interrupts and data translation
-                       mtmsr   r9                                                      ; Disable DR and EE
-                       isync
-                       
-                       lwz             r4,mbvrswap(r4)                         ; Get the conversion value
-                       mtmsr   r10                                                     ; Interrupts and DR back on
-                       isync
-                       xor             r3,r3,r4                                        ; Convert to physical
+                       .set    .,hwpOpBase+(2*128)                     ; Generate error if previous function too long
 
-hcpvret:       rlwinm  r3,r3,0,0,26                            ; Clean out any flags
-                       blr
+hwpSPrtMap:    lwz             r9,mpFlags(r31)                         ; Get the mapping flags
+                       lwz             r8,mpVAddr+4(r31)                       ; Get the protection part of mapping
+                       rlwinm. r9,r9,0,mpPermb,mpPermb         ; Is the mapping permanent?
+                       li              r0,lo16(mpPP)                           ; Get protection bits
+                       crnot   cr0_eq,cr0_eq                           ; Change CR0_EQ to true if mapping is permanent
+                       rlwinm  r2,r25,0,mpPP                           ; Isolate new protection bits 
+                       beqlr--                                                         ; Leave if permanent mapping (before we trash R5)...
+                       andc    r5,r5,r0                                        ; Clear the old prot bits
+                       or              r5,r5,r2                                        ; Move in the new prot bits
+                       rlwimi  r8,r5,0,20,31                           ; Copy into the mapping copy
+                       cmpw    r0,r0                                           ; Make sure we return CR0_EQ
+                       stw             r8,mpVAddr+4(r31)                       ; Set the flag part of mapping
+                       blr                                                                     ; Leave...
+                       
+;                      Function 3 - Set attributes in physent
 
+                       .set    .,hwpOpBase+(3*128)                     ; Generate error if previous function too long
 
-/*                     struct mapping *hw_cvp(struct mapping *mp) - Converts a virtual mapping CB address to physcial
- *
- *                     Translation must be on for this
- *
- */
+hwpSAtrPhy:    li              r5,ppLink                                       ; Get offset for flag part of physent
 
-                       .align  5
-                       .globl  EXT(hw_cvp)
+hwpSAtrPhX:    lwarx   r4,r5,r29                                       ; Get the old flags
+                       rlwimi  r4,r25,0,ppIb,ppGb                      ; Stick in the new attributes
+                       stwcx.  r4,r5,r29                                       ; Try to stuff it
+                       bne--   hwpSAtrPhX                                      ; Try again...
+;                      Note: CR0_EQ is set because of stwcx.
+                       blr                                                                     ; Return...
+                       
+;                      Function 4 - Set attributes in mapping
+
+                       .set    .,hwpOpBase+(4*128)                     ; Generate error if previous function too long
+
+hwpSAtrMap:    lwz             r9,mpFlags(r31)                         ; Get the mapping flags
+                       lwz             r8,mpVAddr+4(r31)                       ; Get the attribute part of mapping
+                       li              r2,mpM                                          ; Force on coherent
+                       rlwinm. r9,r9,0,mpPermb,mpPermb         ; Is the mapping permanent?
+                       li              r0,lo16(mpWIMG)                         ; Get wimg mask         
+                       crnot   cr0_eq,cr0_eq                           ; Change CR0_EQ to true if mapping is permanent
+                       rlwimi  r2,r25,32-(mpIb-32-ppIb),mpIb-32,mpIb-32
+                                                                                               ; Copy in the cache inhibited bit
+                       beqlr--                                                         ; Leave if permanent mapping (before we trash R5)...
+                       andc    r5,r5,r0                                        ; Clear the old wimg
+                       rlwimi  r2,r25,32-(mpGb-32-ppGb),mpGb-32,mpGb-32
+                                                                                               ; Copy in the guarded bit
+                       mfsprg  r9,2                                            ; Feature flags
+                       or              r5,r5,r2                                        ; Move in the new wimg
+                       rlwimi  r8,r5,0,20,31                           ; Copy into the mapping copy
+                       lwz             r2,mpPAddr(r31)                         ; Get the physical address
+                       li              r0,0xFFF                                        ; Start a mask
+                       andi.   r9,r9,pf32Byte+pf128Byte        ; Get cache line size
+                       rlwinm  r5,r0,0,1,0                                     ; Copy to top half
+                       stw             r8,mpVAddr+4(r31)                       ; Set the flag part of mapping
+                       rlwinm  r2,r2,12,1,0                            ; Copy to top and rotate to make physical address with junk left
+                       and             r5,r5,r2                                        ; Clean stuff in top 32 bits
+                       andc    r2,r2,r0                                        ; Clean bottom too
+                       rlwimi  r5,r2,0,0,31                            ; Insert low 23 to make full physical address
+                       b               hwpSAM                                          ; Join common
+                       
+;                      NOTE: we moved the remainder of the code out of here because it
+;                      did not fit in the 128 bytes allotted.  It got stuck into the free space
+;                      at the end of the no-op function.
+
+
+
+                       
+;                      Function 5 - Clear reference in physent
+
+                       .set    .,hwpOpBase+(5*128)                     ; Generate error if previous function too long
+
+hwpCRefPhy:    li              r5,ppLink+4                                     ; Get offset for flag part of physent
+
+hwpCRefPhX:    lwarx   r4,r5,r29                                       ; Get the old flags
+                       rlwinm  r4,r4,0,ppRb+1-32,ppRb-1-32     ; Clear R
+                       stwcx.  r4,r5,r29                                       ; Try to stuff it
+                       bne--   hwpCRefPhX                                      ; Try again...
+;                      Note: CR0_EQ is set because of stwcx.
+                       blr                                                                     ; Return...
 
-LEXT(hw_cvp)
                        
-                       rlwinm  r4,r3,0,0,19                            ; Round back to the mapping block allocation control block                      
-                       rlwinm  r3,r3,0,0,26                            ; Clean out any flags
-                       lwz             r4,mbvrswap(r4)                         ; Get the conversion value
-                       xor             r3,r3,r4                                        ; Convert to virtual
-                       blr
+;                      Function 6 - Clear reference in mapping 
 
+                       .set    .,hwpOpBase+(6*128)                     ; Generate error if previous function too long
 
-/*                     int mapalc(struct mappingblok *mb) - Finds, allocates, and checks a free mapping entry in a block
- *
- *                     Lock must already be held on mapping block list
+hwpCRefMap:    li              r0,lo16(mpR)                            ; Get reference bit
+                       lwz             r8,mpVAddr+4(r31)                       ; Get the flag part of mapping
+                       andc    r5,r5,r0                                        ; Clear in PTE copy
+                       andc    r8,r8,r0                                        ; and in the mapping
+                       cmpw    r0,r0                                           ; Make sure we return CR0_EQ
+                       stw             r8,mpVAddr+4(r31)                       ; Set the flag part of mapping
+                       blr                                                                     ; Return...
+
+                       
+;                      Function 7 - Clear change in physent
+
+                       .set    .,hwpOpBase+(7*128)                     ; Generate error if previous function too long
+
+hwpCCngPhy:    li              r5,ppLink+4                                     ; Get offset for flag part of physent
+
+hwpCCngPhX:    lwarx   r4,r5,r29                                       ; Get the old flags
+                       rlwinm  r4,r4,0,ppCb+1-32,ppCb-1-32     ; Clear C
+                       stwcx.  r4,r5,r29                                       ; Try to stuff it
+                       bne--   hwpCCngPhX                                      ; Try again...
+;                      Note: CR0_EQ is set because of stwcx.
+                       blr                                                                     ; Return...
+                       
+                       
+;                      Function 8 - Clear change in mapping
+
+                       .set    .,hwpOpBase+(8*128)                     ; Generate error if previous function too long
+
+hwpCCngMap:    li              r0,lo16(mpC)                            ; Get change bit
+                       lwz             r8,mpVAddr+4(r31)                       ; Get the flag part of mapping
+                       andc    r5,r5,r0                                        ; Clear in PTE copy
+                       andc    r8,r8,r0                                        ; and in the mapping
+                       cmpw    r0,r0                                           ; Make sure we return CR0_EQ
+                       stw             r8,mpVAddr+4(r31)                       ; Set the flag part of mapping
+                       blr                                                                     ; Return...
+
+                       
+;                      Function 9 - Set reference in physent
+
+                       .set    .,hwpOpBase+(9*128)                     ; Generate error if previous function too long
+
+hwpSRefPhy:    li              r5,ppLink+4                                     ; Get offset for flag part of physent
+
+hwpSRefPhX:    lwarx   r4,r5,r29                                       ; Get the old flags
+                       ori             r4,r4,lo16(ppR)                         ; Set the reference
+                       stwcx.  r4,r5,r29                                       ; Try to stuff it
+                       bne--   hwpSRefPhX                                      ; Try again...
+;                      Note: CR0_EQ is set because of stwcx.
+                       blr                                                                     ; Return...
+
+                       
+;                      Function 10 - Set reference in mapping
+
+                       .set    .,hwpOpBase+(10*128)            ; Generate error if previous function too long
+
+hwpSRefMap:    lwz             r8,mpVAddr+4(r31)                       ; Get the flag part of mapping
+                       ori             r8,r8,lo16(mpR)                         ; Set reference in mapping
+                       cmpw    r0,r0                                           ; Make sure we return CR0_EQ
+                       stw             r8,mpVAddr+4(r31)                       ; Set the flag part of mapping
+                       blr                                                                     ; Return...
+                       
+;                      Function 11 - Set change in physent
+
+                       .set    .,hwpOpBase+(11*128)            ; Generate error if previous function too long
+
+hwpSCngPhy:    li              r5,ppLink+4                                     ; Get offset for flag part of physent
+
+hwpSCngPhX:    lwarx   r4,r5,r29                                       ; Get the old flags
+                       ori             r4,r4,lo16(ppC)                         ; Set the change bit
+                       stwcx.  r4,r5,r29                                       ; Try to stuff it
+                       bne--   hwpSCngPhX                                      ; Try again...
+;                      Note: CR0_EQ is set because of stwcx.
+                       blr                                                                     ; Return...
+                       
+;                      Function 12 - Set change in mapping
+
+                       .set    .,hwpOpBase+(12*128)            ; Generate error if previous function too long
+
+hwpSCngMap:    lwz             r8,mpVAddr+4(r31)                       ; Get the flag part of mapping
+                       ori             r8,r8,lo16(mpC)                         ; Set chage in mapping
+                       cmpw    r0,r0                                           ; Make sure we return CR0_EQ
+                       stw             r8,mpVAddr+4(r31)                       ; Set the flag part of mapping
+                       blr                                                                     ; Return...
+
+;                      Function 13 - Test reference in physent
+
+                       .set    .,hwpOpBase+(13*128)            ; Generate error if previous function too long
+                       
+hwpTRefPhy:    lwz             r0,ppLink+4(r29)                        ; Get the flags from physent    
+                       rlwinm. r0,r0,0,ppRb-32,ppRb-32         ; Isolate reference bit and see if 0
+                       blr                                                                     ; Return (CR0_EQ set to continue if reference is off)...
+
+
+;                      Function 14 - Test reference in mapping
+
+                       .set    .,hwpOpBase+(14*128)            ; Generate error if previous function too long
+                       
+hwpTRefMap:    rlwinm. r0,r5,0,mpRb-32,mpRb-32         ; Isolate reference bit and see if 0
+                       blr                                                                     ; Return (CR0_EQ set to continue if reference is off)...
+
+
+;                      Function 15 - Test change in physent
+
+                       .set    .,hwpOpBase+(15*128)            ; Generate error if previous function too long
+                       
+hwpTCngPhy:    lwz             r0,ppLink+4(r29)                        ; Get the flags from physent    
+                       rlwinm. r0,r0,0,ppCb-32,ppCb-32         ; Isolate change bit and see if 0
+                       blr                                                                     ; Return (CR0_EQ set to continue if change is off)...
+
+
+;                      Function 16 - Test change in mapping
+
+                       .set    .,hwpOpBase+(16*128)            ; Generate error if previous function too long
+                       
+hwpTCngMap:    rlwinm. r0,r5,0,mpCb-32,mpCb-32         ; Isolate change bit and see if 0
+                       blr                                                                     ; Return (CR0_EQ set to continue if change is off)...
+
+
+;                      Function 17 - Test reference and change in physent
+
+                       .set    .,hwpOpBase+(17*128)            ; Generate error if previous function too long
+
+hwpTRefCngPhy:                 
+                       lwz             r0,ppLink+4(r29)                        ; Get the flags from physent    
+                       rlwinm  r0,r0,0,ppRb-32,ppCb-32         ; Isolate reference and change bits
+                       cmplwi  r0,lo16(ppR|ppC)                        ; cr0_eq <- ((R == 1) && (C == 1))
+                       crnot   cr0_eq,cr0_eq                           ; cr0_eq <- ((R == 0) || (C == 0))
+                       blr                                                                     ; Return (CR0_EQ set to continue if either R or C is off)...
+
+
+;                      Function 18 - Test reference and change in mapping
+
+                       .set    .,hwpOpBase+(18*128)            ; Generate error if previous function too long
+hwpTRefCngMap:
+                       rlwinm  r0,r5,0,mpRb-32,mpCb-32         ; Isolate reference and change bits from mapping
+                       cmplwi  r0,lo16(mpR|mpC)                        ; cr0_eq <- ((R == 1) && (C == 1))
+                       crnot   cr0_eq,cr0_eq                           ; cr0_eq <- ((R == 0) || (C == 0))
+                       blr                                                                     ; Return (CR0_EQ set to continue if either R or C is off)...
+
+
+;                      Function 19 - Clear reference and change in physent
+
+                       .set    .,hwpOpBase+(19*128)            ; Generate error if previous function too long
+hwpCRefCngPhy:
+                       li              r5,ppLink+4                                     ; Get offset for flag part of physent
+
+hwpCRefCngPhX:
+                       lwarx   r4,r5,r29                                       ; Get the old flags
+                       andc    r4,r4,r25                                       ; Clear R and C as specified by mask
+                       stwcx.  r4,r5,r29                                       ; Try to stuff it
+                       bne--   hwpCRefCngPhX                           ; Try again...
+;                      Note: CR0_EQ is set because of stwcx.
+                       blr                                                                     ; Return...
+
+
+;                      Function 20 - Clear reference and change in mapping
+
+                       .set    .,hwpOpBase+(20*128)            ; Generate error if previous function too long
+hwpCRefCngMap:
+                       srwi    r0,r25,(ppRb - mpRb)            ; Align reference/change clear mask (phys->map)
+                       lwz             r8,mpVAddr+4(r31)                       ; Get the flag part of mapping
+                       andc    r5,r5,r0                                        ; Clear in PTE copy
+                       andc    r8,r8,r0                                        ; and in the mapping
+                       cmpw    r0,r0                                           ; Make sure we return CR0_EQ
+                       stw             r8,mpVAddr+4(r31)                       ; Set the flag part of mapping
+                       blr                                                                     ; Return...
+
+
+                       .set    .,hwpOpBase+(21*128)            ; Generate error if previous function too long
+
+;
+;                      unsigned int hw_protect(pmap, va, prot, *nextva) - Changes protection on a specific mapping.
+;                      
+;                      Returns:
+;                              mapRtOK     - if all is ok
+;                              mapRtBadLk  - if mapping lock fails
+;                              mapRtPerm   - if mapping is permanent
+;                              mapRtNotFnd - if mapping is not found
+;                              mapRtBlock  - if mapping is a block
+;
+                       .align  5
+                       .globl  EXT(hw_protect)
+
+LEXT(hw_protect)
+                       stwu    r1,-(FM_ALIGN((31-24+1)*4)+FM_SIZE)(r1) ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r24,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x04(r1)            ; Save a register
+                       mr              r25,r7                                          ; Remember address of next va
+                       stw             r26,FM_ARG0+0x08(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r28,FM_ARG0+0x10(r1)            ; Save a register
+                       mr              r24,r6                                          ; Save the new protection flags
+                       stw             r29,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x1C(r1)            ; Save a register
+                       stw             r0,(FM_ALIGN((31-24+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+
+#if DEBUG
+                       lwz             r11,pmapFlags(r3)                       ; Get pmaps flags
+                       rlwinm. r11,r11,0,pmapVMgsaa            ; Is guest shadow assist active? 
+                       bne             hpPanic                                         ; Call not valid for guest shadow assist pmap
+#endif
+                       
+                       lwz             r6,pmapvr(r3)                           ; Get the first part of the VR translation for pmap
+                       lwz             r7,pmapvr+4(r3)                         ; Get the second part
+
+
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
+
+                       mr              r27,r11                                         ; Remember the old MSR
+                       mr              r26,r12                                         ; Remember the feature bits
+
+                       xor             r28,r3,r7                                       ; Change the common 32- and 64-bit half
+
+                       bf--    pf64Bitb,hpSF1                          ; skip if 32-bit...
+                       
+                       rldimi  r28,r6,32,0                                     ; Shift the fixed upper part of the physical over and cram in top
+
+hpSF1:         mr              r29,r4                                          ; Save top half of vaddr
+                       mr              r30,r5                                          ; Save the bottom half
+                                               
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne--   hpBadLock                                       ; Nope...
+
+                       mr              r3,r28                                          ; get the pmap address
+                       mr              r4,r29                                          ; Get bits 0:31 to look for
+                       mr              r5,r30                                          ; Get bits 32:64
+                       
+                       bl              EXT(mapSearch)                          ; Go see if we can find it (note: R7 comes back with mpFlags)
+
+                       rlwinm. r0,r7,0,mpType                          ; Is this a normal mapping?
+                       crmove  cr1_eq,cr0_eq                           ; cr1_eq <- this is a normal mapping
+                       andi.   r0,r7,mpPerm|mpRIP                      ; Is it permanent or being removed?
+                       cror    cr1_eq,cr0_eq,cr1_eq        ; cr1_eq <- normal mapping and not permanent and not being removed
+                       mr.             r31,r3                                          ; Save the mapping if we found it
+                       mr              r29,r4                                          ; Save next va high half
+                       mr              r30,r5                                          ; Save next va low half
+                       
+                       beq--   hpNotFound                                      ; Not found...
+
+                       bf--    cr1_eq,hpNotAllowed                     ; Something special is happening...
+                       
+                       bt++    pf64Bitb,hpDo64                         ; Split for 64 bit
+                       
+                       bl              mapInvPte32                                     ; Invalidate and lock PTEG, also merge into physent
+                                               
+                       rlwimi  r5,r24,0,mpPPb-32,mpPPe-32      ; Stick in the new pp (note that we ignore no-execute for 32-bit)
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+
+                       stb             r5,mpVAddr+7(r31)                       ; Set the new pp field (do not muck with the rest)                      
+
+                       beq--   hpNoOld32                                       ; Nope...
+                       
+                       stw             r5,4(r3)                                        ; Store second half of PTE
+                       eieio                                                           ; Make sure we do not reorder
+                       stw             r4,0(r3)                                        ; Revalidate the PTE
+
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock PCA
+               
+hpNoOld32:     la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+
+                       li              r3,mapRtOK                                      ; Set normal return             
+                       b               hpR32                                           ; Join common...
+
+                       .align  5                       
+                       
+                       
+hpDo64:                bl              mapInvPte64                                     ; Invalidate and lock PTEG, also merge into physent
+                                               
+                       rldimi  r5,r24,0,mpNb                           ; Stick in the new no-exectue and pp bits
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+
+                       stb             r5,mpVAddr+7(r31)                       ; Set the new pp field (do not muck with the rest)                      
+
+                       beq--   hpNoOld64                                       ; Nope...
+                       
+                       std             r5,8(r3)                                        ; Store second half of PTE
+                       eieio                                                           ; Make sure we do not reorder
+                       std             r4,0(r3)                                        ; Revalidate the PTE
+
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock PCA
+
+hpNoOld64:     la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+
+                       li              r3,mapRtOK                                      ; Set normal return             
+                       b               hpR64                                           ; Join common...
+
+                       .align  5                                                       
+                                               
+hpReturn:      bt++    pf64Bitb,hpR64                          ; Yes...
+
+hpR32:         mtmsr   r27                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               hpReturnC                                       ; Join common...
+
+hpR64:         mtmsrd  r27                                                     ; Restore enables/translation/etc.
+                       isync                                                           
+                       
+hpReturnC:     stw             r29,0(r25)                                      ; Save the top of the next va
+                       stw             r30,4(r25)                                      ; Save the bottom of the next va
+                       lwz             r0,(FM_ALIGN((31-24+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+                       lwz             r24,FM_ARG0+0x00(r1)            ; Save a register
+                       lwz             r25,FM_ARG0+0x04(r1)            ; Save a register
+                       lwz             r26,FM_ARG0+0x08(r1)            ; Save a register
+                       mtlr    r0                                                      ; Restore the return
+                       lwz             r27,FM_ARG0+0x0C(r1)            ; Save a register
+                       lwz             r28,FM_ARG0+0x10(r1)            ; Save a register
+                       lwz             r29,FM_ARG0+0x14(r1)            ; Save a register
+                       lwz             r30,FM_ARG0+0x18(r1)            ; Save a register
+                       lwz             r31,FM_ARG0+0x1C(r1)            ; Save a register
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
+                       
+                       .align  5
+                       
+hpBadLock:     li              r3,mapRtBadLk                           ; Set lock time out error code
+                       b               hpReturn                                        ; Leave....
+                       
+hpNotFound:    la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       
+                       li              r3,mapRtNotFnd                          ; Set that we did not find the requested page
+                       b               hpReturn                                        ; Leave....
+                       
+hpNotAllowed:  
+                       rlwinm. r0,r7,0,mpRIPb,mpRIPb           ; Is it actually being removed?
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bne--   hpNotFound                                      ; Yeah...
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       
+                       li              r3,mapRtBlock                           ; Assume it was a block
+                       rlwinm  r0,r7,0,mpType                          ; Isolate mapping type
+                       cmplwi  r0,mpBlock                                      ; Is this a block mapping?
+                       beq++   hpReturn                                        ; Yes, leave...
+                       
+                       li              r3,mapRtPerm                            ; Set that we hit a permanent page
+                       b               hpReturn                                        ; Leave....
+
+hpPanic:       lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
+                       
+
+;
+;                      int hw_test_rc(pmap, va, reset) - tests RC on a specific va
+;                      
+;                      Returns following code ORed with RC from mapping
+;                              mapRtOK     - if all is ok
+;                              mapRtBadLk  - if mapping lock fails
+;                              mapRtNotFnd - if mapping is not found
+;
+                       .align  5
+                       .globl  EXT(hw_test_rc)
+
+LEXT(hw_test_rc)
+                       stwu    r1,-(FM_ALIGN((31-24+1)*4)+FM_SIZE)(r1) ; Make some space on the stack
+                       mflr    r0                                                      ; Save the link register
+                       stw             r24,FM_ARG0+0x00(r1)            ; Save a register
+                       stw             r25,FM_ARG0+0x04(r1)            ; Save a register
+                       stw             r26,FM_ARG0+0x08(r1)            ; Save a register
+                       stw             r27,FM_ARG0+0x0C(r1)            ; Save a register
+                       stw             r28,FM_ARG0+0x10(r1)            ; Save a register
+                       mr              r24,r6                                          ; Save the reset request
+                       stw             r29,FM_ARG0+0x14(r1)            ; Save a register
+                       stw             r30,FM_ARG0+0x18(r1)            ; Save a register
+                       stw             r31,FM_ARG0+0x1C(r1)            ; Save a register
+                       stw             r0,(FM_ALIGN((31-24+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+
+#if DEBUG
+                       lwz             r11,pmapFlags(r3)                       ; Get pmaps flags
+                       rlwinm. r11,r11,0,pmapVMgsaa            ; Is guest shadow assist active? 
+                       bne             htrPanic                                        ; Call not valid for guest shadow assist pmap
+#endif
+                       
+                       lwz             r6,pmapvr(r3)                           ; Get the first part of the VR translation for pmap
+                       lwz             r7,pmapvr+4(r3)                         ; Get the second part
+
+
+                       bl              EXT(mapSetUp)                           ; Turn off interrupts, translation, and possibly enter 64-bit
+
+                       mr              r27,r11                                         ; Remember the old MSR
+                       mr              r26,r12                                         ; Remember the feature bits
+
+                       xor             r28,r3,r7                                       ; Change the common 32- and 64-bit half
+
+                       bf--    pf64Bitb,htrSF1                         ; skip if 32-bit...
+                       
+                       rldimi  r28,r6,32,0                                     ; Shift the fixed upper part of the physical over and cram in top
+
+htrSF1:                mr              r29,r4                                          ; Save top half of vaddr
+                       mr              r30,r5                                          ; Save the bottom half
+                                               
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       li              r25,0                                           ; Clear RC
+                       bne--   htrBadLock                                      ; Nope...
+
+                       mr              r3,r28                                          ; get the pmap address
+                       mr              r4,r29                                          ; Get bits 0:31 to look for
+                       mr              r5,r30                                          ; Get bits 32:64
+                       
+                       bl              EXT(mapSearch)                          ; Go see if we can find it (R7 comes back with mpFlags)
+
+                       rlwinm. r0,r7,0,mpType                          ; Is this a normal mapping?
+                       crmove  cr1_eq,cr0_eq                           ; cr1_eq <- this is a normal mapping
+                       andi.   r0,r7,mpPerm|mpRIP                      ; Is it permanent or being removed?
+                       crand   cr1_eq,cr0_eq,cr1_eq        ; cr1_eq <- normal mapping and not permanent and not being removed
+                       mr.             r31,r3                                          ; Save the mapping if we found it
+                       crandc  cr1_eq,cr1_eq,cr0_eq            ; cr1_eq <- found & normal & not permanent & not being removed
+                       
+                       bf--    cr1_eq,htrNotFound                      ; Not found, something special, or being removed...
+                       
+                       bt++    pf64Bitb,htrDo64                        ; Split for 64 bit
+                       
+                       bl              mapInvPte32                                     ; Invalidate and lock PTEG, also merge into physent
+                                               
+                       cmplwi  cr1,r24,0                                       ; Do we want to clear RC?
+                       lwz             r12,mpVAddr+4(r31)                      ; Get the bottom of the mapping vaddr field
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+                       li              r0,lo16(mpR|mpC)                        ; Get bits to clear
+
+                       and             r25,r5,r0                                       ; Save the RC bits
+                       beq++   cr1,htrNoClr32                          ; Nope...
+                       
+                       andc    r12,r12,r0                                      ; Clear mapping copy of RC
+                       andc    r5,r5,r0                                        ; Clear PTE copy of RC
+                       sth             r12,mpVAddr+6(r31)                      ; Set the new RC                        
+
+htrNoClr32:    beq--   htrNoOld32                                      ; No previously valid PTE...
+                       
+                       sth             r5,6(r3)                                        ; Store updated RC
+                       eieio                                                           ; Make sure we do not reorder
+                       stw             r4,0(r3)                                        ; Revalidate the PTE
+
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock PCA
+
+htrNoOld32:    la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       li              r3,mapRtOK                                      ; Set normal return             
+                       b               htrR32                                          ; Join common...
+
+                       .align  5                       
+                       
+                       
+htrDo64:       bl              mapInvPte64                                     ; Invalidate and lock PTEG, also merge into physent
+                                               
+                       cmplwi  cr1,r24,0                                       ; Do we want to clear RC?
+                       lwz             r12,mpVAddr+4(r31)                      ; Get the bottom of the mapping vaddr field
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+                       li              r0,lo16(mpR|mpC)                        ; Get bits to clear
+
+                       and             r25,r5,r0                                       ; Save the RC bits
+                       beq++   cr1,htrNoClr64                          ; Nope...
+                       
+                       andc    r12,r12,r0                                      ; Clear mapping copy of RC
+                       andc    r5,r5,r0                                        ; Clear PTE copy of RC
+                       sth             r12,mpVAddr+6(r31)                      ; Set the new RC                        
+
+htrNoClr64:    beq--   htrNoOld64                                      ; Nope, no pevious pte...
+                       
+                       sth             r5,14(r3)                                       ; Store updated RC
+                       eieio                                                           ; Make sure we do not reorder
+                       std             r4,0(r3)                                        ; Revalidate the PTE
+
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock PCA
+
+htrNoOld64:    la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       li              r3,mapRtOK                                      ; Set normal return             
+                       b               htrR64                                          ; Join common...
+
+                       .align  5                                                       
+                                               
+htrReturn:     bt++    pf64Bitb,htrR64                         ; Yes...
+
+htrR32:                mtmsr   r27                                                     ; Restore enables/translation/etc.
+                       isync
+                       b               htrReturnC                                      ; Join common...
+
+htrR64:                mtmsrd  r27                                                     ; Restore enables/translation/etc.
+                       isync                                                           
+                       
+htrReturnC:    lwz             r0,(FM_ALIGN((31-24+1)*4)+FM_SIZE+FM_LR_SAVE)(r1)       ; Save the return
+                       or              r3,r3,r25                                       ; Send the RC bits back
+                       lwz             r24,FM_ARG0+0x00(r1)            ; Save a register
+                       lwz             r25,FM_ARG0+0x04(r1)            ; Save a register
+                       lwz             r26,FM_ARG0+0x08(r1)            ; Save a register
+                       mtlr    r0                                                      ; Restore the return
+                       lwz             r27,FM_ARG0+0x0C(r1)            ; Save a register
+                       lwz             r28,FM_ARG0+0x10(r1)            ; Save a register
+                       lwz             r29,FM_ARG0+0x14(r1)            ; Save a register
+                       lwz             r30,FM_ARG0+0x18(r1)            ; Save a register
+                       lwz             r31,FM_ARG0+0x1C(r1)            ; Save a register
+                       lwz             r1,0(r1)                                        ; Pop the stack
+                       blr                                                                     ; Leave...
+                       
+                       .align  5
+                       
+htrBadLock:    li              r3,mapRtBadLk                           ; Set lock time out error code
+                       b               htrReturn                                       ; Leave....
+                       
+htrNotFound:   
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       
+                       li              r3,mapRtNotFnd                          ; Set that we did not find the requested page
+                       b               htrReturn                                       ; Leave....
+
+htrPanic:      lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show that we failed some kind of mapping thing
+                       sc
+                       
+
+;
+;
+;                      mapFindLockPN - find and lock physent for a given page number
+;
+;
+                       .align  5
+mapFindLockPN:
+                       lis             r9,hi16(EXT(pmap_mem_regions))          ; Point to the start of the region table
+                       mr              r2,r3                                           ; Save our target
+                       ori             r9,r9,lo16(EXT(pmap_mem_regions))       ; Point to the start of the region table                        
+
+mapFLPNitr:    lwz             r3,mrPhysTab(r9)                        ; Get the actual table address
+                       lwz             r5,mrStart(r9)                          ; Get start of table entry
+                       lwz             r0,mrEnd(r9)                            ; Get end of table entry
+                       addi    r9,r9,mrSize                            ; Point to the next slot
+                       cmplwi  cr7,r3,0                                        ; Are we at the end of the table?
+                       cmplw   r2,r5                                           ; See if we are in this table
+                       cmplw   cr1,r2,r0                                       ; Check end also
+                       sub             r4,r2,r5                                        ; Calculate index to physical entry
+                       beq--   cr7,mapFLPNmiss                         ; Leave if we did not find an entry...
+                       cror    cr0_lt,cr0_lt,cr1_gt            ; Set CR0_LT if it is NOT this entry
+                       slwi    r4,r4,3                                         ; Get offset to physical entry
+
+                       blt--   mapFLPNitr                                      ; Did not find it...
+                       
+                       add             r3,r3,r4                                        ; Point right to the slot
+                       b               mapPhysLock                                     ; Join common lock code
+
+mapFLPNmiss:
+                       li              r3,0                                            ; Show that we did not find it
+                       blr                                                                     ; Leave...                      
+                       
+
+;
+;                      mapPhysFindLock - find physent list and lock it
+;                      R31 points to mapping
+;
+                       .align  5
+                       
+mapPhysFindLock:       
+                       lbz             r4,mpFlags+1(r31)                       ; Get the index into the physent bank table
+                       lis             r3,ha16(EXT(pmap_mem_regions))  ; Get high order of physent table (note use of ha16 to get value appropriate for an addi of low part)
+                       rlwinm  r4,r4,2,24,29                           ; Mask index bits and convert to byte offset
+                       addi    r4,r4,lo16(EXT(pmap_mem_regions))       ; Get low part of address of entry
+                       add             r3,r3,r4                                        ; Point to table entry
+                       lwz             r5,mpPAddr(r31)                         ; Get physical page number
+                       lwz             r7,mrStart(r3)                          ; Get the start of range
+                       lwz             r3,mrPhysTab(r3)                        ; Get the start of the entries for this bank
+                       sub             r6,r5,r7                                        ; Get index to physent
+                       rlwinm  r6,r6,3,0,28                            ; Get offset to physent
+                       add             r3,r3,r6                                        ; Point right to the physent
+                       b               mapPhysLock                                     ; Join in the lock...
+
+;
+;                      mapPhysLock - lock a physent list
+;                      R3 contains list header
+;
+                       .align  5
+
+mapPhysLockS:
+                       li              r2,lgKillResv                           ; Get a spot to kill reservation
+                       stwcx.  r2,0,r2                                         ; Kill it...
+                       
+mapPhysLockT:
+                       lwz             r2,ppLink(r3)                           ; Get physent chain header
+                       rlwinm. r2,r2,0,0,0                                     ; Is lock clear?
+                       bne--   mapPhysLockT                            ; Nope, still locked...
+                       
+mapPhysLock:   
+                       lwarx   r2,0,r3                                         ; Get the lock
+                       rlwinm. r0,r2,0,0,0                                     ; Is it locked?
+                       oris    r0,r2,0x8000                            ; Set the lock bit
+                       bne--   mapPhysLockS                            ; It is locked, spin on it...
+                       stwcx.  r0,0,r3                                         ; Try to stuff it back...
+                       bne--   mapPhysLock                                     ; Collision, try again...
+                       isync                                                           ; Clear any speculations
+                       blr                                                                     ; Leave...
+                       
+
+;
+;                      mapPhysUnlock - unlock a physent list
+;                      R3 contains list header
+;
+                       .align  5
+                       
+mapPhysUnlock: 
+                       lwz             r0,ppLink(r3)                           ; Get physent chain header
+                       rlwinm  r0,r0,0,1,31                            ; Clear the lock bit
+                       eieio                                                           ; Make sure unlock comes last
+                       stw             r0,ppLink(r3)                           ; Unlock the list
+                       blr
+
+;
+;                      mapPhysMerge - merge the RC bits into the master copy
+;                      R3 points to the physent 
+;                      R4 contains the RC bits
+;
+;                      Note: we just return if RC is 0
+;
+                       .align  5
+                       
+mapPhysMerge:  
+                       rlwinm. r4,r4,PTE1_REFERENCED_BIT+(64-ppRb),ppRb-32,ppCb-32     ; Isolate RC bits
+                       la              r5,ppLink+4(r3)                         ; Point to the RC field
+                       beqlr--                                                         ; Leave if RC is 0...
+                       
+mapPhysMergeT:
+                       lwarx   r6,0,r5                                         ; Get the RC part
+                       or              r6,r6,r4                                        ; Merge in the RC
+                       stwcx.  r6,0,r5                                         ; Try to stuff it back...
+                       bne--   mapPhysMergeT                           ; Collision, try again...
+                       blr                                                                     ; Leave...
+
+;
+;                      Sets the physent link pointer and preserves all flags
+;                      The list is locked
+;                      R3 points to physent
+;                      R4 has link to set
+;
+
+                       .align  5
+
+mapPhyCSet32:
+                       la              r5,ppLink+4(r3)                         ; Point to the link word
+
+mapPhyCSetR:
+                       lwarx   r2,0,r5                                         ; Get the link and flags
+                       rlwimi  r4,r2,0,ppFlags                         ; Insert the flags
+                       stwcx.  r4,0,r5                                         ; Stick them back
+                       bne--   mapPhyCSetR                                     ; Someone else did something, try again...
+                       blr                                                                     ; Return...
+
+                       .align  5
+
+mapPhyCSet64:
+                       li              r0,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+               
+mapPhyCSet64x:
+                       ldarx   r2,0,r3                                         ; Get the link and flags
+                       and             r5,r2,r0                                        ; Isolate the flags
+                       or              r6,r4,r5                                        ; Add them to the link
+                       stdcx.  r6,0,r3                                         ; Stick them back
+                       bne--   mapPhyCSet64x                           ; Someone else did something, try again...
+                       blr                                                                     ; Return...                                             
+
+;
+;                      mapBumpBusy - increment the busy count on a mapping
+;                      R3 points to mapping
+;
+
+                       .align  5
+
+mapBumpBusy:
+                       lwarx   r4,0,r3                                         ; Get mpBusy
+                       addis   r4,r4,0x0100                            ; Bump the busy count
+                       stwcx.  r4,0,r3                                         ; Save it back
+                       bne--   mapBumpBusy                                     ; This did not work, try again...
+                       blr                                                                     ; Leave...
+
+;
+;                      mapDropBusy - increment the busy count on a mapping
+;                      R3 points to mapping
+;
+
+                       .globl  EXT(mapping_drop_busy)
+                       .align  5
+
+LEXT(mapping_drop_busy)
+mapDropBusy:
+                       lwarx   r4,0,r3                                         ; Get mpBusy
+                       addis   r4,r4,0xFF00                            ; Drop the busy count
+                       stwcx.  r4,0,r3                                         ; Save it back
+                       bne--   mapDropBusy                                     ; This did not work, try again...
+                       blr                                                                     ; Leave...
+
+;
+;                      mapDrainBusy - drain the busy count on a mapping
+;                      R3 points to mapping
+;                      Note: we already have a busy for ourselves. Only one
+;                      busy per processor is allowed, so we just spin here
+;                      waiting for the count to drop to 1.
+;                      Also, the mapping can not be on any lists when we do this
+;                      so all we are doing is waiting until it can be released.
+;
+
+                       .align  5
+
+mapDrainBusy:
+                       lwz             r4,mpFlags(r3)                          ; Get mpBusy
+                       rlwinm  r4,r4,8,24,31                           ; Clean it up
+                       cmplwi  r4,1                                            ; Is is just our busy?
+                       beqlr++                                                         ; Yeah, it is clear...
+                       b               mapDrainBusy                            ; Try again...
+
+
+       
+;
+;                      handleDSeg - handle a data segment fault
+;                      handleISeg - handle an instruction segment fault
+;
+;                      All that we do here is to map these to DSI or ISI and insure
+;                      that the hash bit is not set.  This forces the fault code
+;                      to also handle the missing segment.
+;
+;                      At entry R2 contains per_proc, R13 contains savarea pointer,
+;                      and R11 is the exception code.
+;
+
+                       .align  5
+                       .globl  EXT(handleDSeg)
+
+LEXT(handleDSeg)
+
+                       li              r11,T_DATA_ACCESS                       ; Change fault to DSI
+                       stw             r11,saveexception(r13)          ; Change the exception code from seg fault to PTE miss
+                       b               EXT(handlePF)                           ; Join common...
+
+                       .align  5
+                       .globl  EXT(handleISeg)
+
+LEXT(handleISeg)
+
+                       li              r11,T_INSTRUCTION_ACCESS        ; Change fault to ISI
+                       stw             r11,saveexception(r13)          ; Change the exception code from seg fault to PTE miss
+                       b               EXT(handlePF)                           ; Join common...
+
+
+/*
+ *                     handlePF - handle a page fault interruption
+ *
+ *                     At entry R2 contains per_proc, R13 contains savarea pointer,
+ *                     and R11 is the exception code.
+ *
+ *                     This first part does a quick check to see if we can handle the fault.
+ *                     We canot handle any kind of protection exceptions here, so we pass
+ *                     them up to the next level.
+ *
+ *                     NOTE: In order for a page-fault redrive to work, the translation miss
+ *                     bit must be set in the DSISR (or SRR1 for IFETCH).  That must occur
+ *                     before we come here.
+ */
+
+                       .align  5
+                       .globl  EXT(handlePF)
+
+LEXT(handlePF)
+
+                       mfsprg  r12,2                                           ; Get feature flags 
+                       cmplwi  r11,T_INSTRUCTION_ACCESS                ; See if this is for the instruction 
+                       lwz             r8,savesrr1+4(r13)                      ; Get the MSR to determine mode
+                       mtcrf   0x02,r12                                        ; move pf64Bit to cr6
+                       lis             r0,hi16(dsiNoEx|dsiProt|dsiInvMode|dsiAC)       ; Get the types that we cannot handle here
+                       lwz             r18,SAVflags(r13)                       ; Get the flags
+                       
+                       beq--   gotIfetch                                       ; We have an IFETCH here...
+                       
+                       lwz             r27,savedsisr(r13)                      ; Get the DSISR
+                       lwz             r29,savedar(r13)                        ; Get the first half of the DAR
+                       lwz             r30,savedar+4(r13)                      ; And second half
+
+                       b               ckIfProt                                        ; Go check if this is a protection fault...
+
+gotIfetch:     andis.  r27,r8,hi16(dsiValid)           ; Clean this up to construct a DSISR value
+                       lwz             r29,savesrr0(r13)                       ; Get the first half of the instruction address
+                       lwz             r30,savesrr0+4(r13)                     ; And second half
+                       stw             r27,savedsisr(r13)                      ; Save the "constructed" DSISR
+
+ckIfProt:      and.    r4,r27,r0                                       ; Is this a non-handlable exception?
+                       li              r20,64                                          ; Set a limit of 64 nests for sanity check
+                       bne--   hpfExit                                         ; Yes... (probably not though)
+                       
+;
+;                      Note: if the RI is on, we are accessing user space from the kernel, therefore we
+;                      should be loading the user pmap here.
+;
+
+                       andi.   r0,r8,lo16(MASK(MSR_PR)|MASK(MSR_RI))   ; Are we addressing user or kernel space?
+                       lis             r8,hi16(EXT(kernel_pmap_phys))  ; Assume kernel
+                       mr              r19,r2                                          ; Remember the per_proc
+                       ori             r8,r8,lo16(EXT(kernel_pmap_phys))       ; Assume kernel (bottom of address)
+                       mr              r23,r30                                         ; Save the low part of faulting address
+                       beq--   hpfInKern                                       ; Skip if we are in the kernel
+                       la              r8,ppUserPmap(r19)                      ; Point to the current user pmap
+                       
+hpfInKern:     mr              r22,r29                                         ; Save the high part of faulting address
+                       
+                       bt--    pf64Bitb,hpf64a                         ; If 64-bit, skip the next bit...
+
+;
+;                      On 32-bit machines we emulate a segment exception by loading unused SRs with a
+;                      predefined value that corresponds to no address space.  When we see that value
+;                      we turn off the PTE miss bit in the DSISR to drive the code later on that will
+;                      cause the proper SR to be loaded.
+;
+
+                       lwz             r28,4(r8)                                       ; Pick up the pmap
+                       rlwinm. r18,r18,0,SAVredriveb,SAVredriveb       ; Was this a redrive?
+                       mr              r25,r28                                         ; Save the original pmap (in case we nest)
+                       lwz             r0,pmapFlags(r28)                       ; Get pmap's flags
+                       bne             hpfGVtest                                       ; Segs are not ours if so...
+                       mfsrin  r4,r30                                          ; Get the SR that was used for translation
+                       cmplwi  r4,invalSpace                           ; Is this a simulated segment fault?
+                       bne++   hpfGVtest                                       ; No...
+                       
+                       rlwinm  r27,r27,0,dsiMissb+1,dsiMissb-1 ; Clear the PTE miss bit in DSISR
+                       b               hpfGVtest                                       ; Join on up...
+                       
+                       .align  5
+
+                       nop                                                                     ; Push hpfNest to a 32-byte boundary
+                       nop                                                                     ; Push hpfNest to a 32-byte boundary
+                       nop                                                                     ; Push hpfNest to a 32-byte boundary
+
+hpf64a:                ld              r28,0(r8)                                       ; Get the pmap pointer (64-bit)
+                       mr              r25,r28                                         ; Save the original pmap (in case we nest)
+                       lwz             r0,pmapFlags(r28)                       ; Get pmap's flags
+                       
+hpfGVtest:     rlwinm. r0,r0,0,pmapVMgsaa                      ; Using guest shadow mapping assist?
+                       bne             hpfGVxlate                                      ; Yup, do accelerated shadow stuff
+
+;
+;                      This is where we loop descending nested pmaps
+;
+
+hpfNest:       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       addi    r20,r20,-1                                      ; Count nest try
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne--   hpfBadLock                                      ; Nope...
+
+                       mr              r3,r28                                          ; Get the pmap pointer
+                       mr              r4,r22                                          ; Get top of faulting vaddr
+                       mr              r5,r23                                          ; Get bottom of faulting vaddr
+                       bl              EXT(mapSearch)                          ; Go see if we can find it (R7 gets mpFlags)
+
+                       rlwinm  r0,r7,0,mpRIPb,mpRIPb           ; Are we removing this one?
+                       mr.             r31,r3                                          ; Save the mapping if we found it
+                       cmplwi  cr1,r0,0                                        ; Check for removal
+                       crorc   cr0_eq,cr0_eq,cr1_eq            ; Merge not found and removing
+                       
+                       bt--    cr0_eq,hpfNotFound                      ; Not found or removing...
+
+                       rlwinm  r0,r7,0,mpType                          ; Isolate mapping type
+                       cmplwi  r0,mpNest                                       ; Are we again nested?
+                       cmplwi  cr1,r0,mpLinkage                        ; Are we a linkage type?
+                       cror    cr0_eq,cr1_eq,cr0_eq            ; cr0_eq <- nested or linkage type?
+                       mr              r26,r7                                          ; Get the flags for this mapping (passed back from search call)
+                       
+                       lhz             r21,mpSpace(r31)                        ; Get the space
+
+                       bne++   hpfFoundIt                                      ; No, we found our guy...
+                       
+
+#if pmapTransSize != 12
+#error pmapTrans entry size is not 12 bytes!!!!!!!!!!!! It is pmapTransSize
+#endif
+                       cmplwi  r0,mpLinkage                            ; Linkage mapping?
+                       cmplwi  cr1,r20,0                                       ; Too many nestings?
+                       beq--   hpfSpclNest                                     ; Do we need to do special handling?
+
+hpfCSrch:      lhz             r21,mpSpace(r31)                        ; Get the space
+                       lwz             r8,mpNestReloc(r31)                     ; Get the vaddr relocation
+                       lwz             r9,mpNestReloc+4(r31)           ; Get the vaddr relocation bottom half
+                       la              r3,pmapSXlk(r28)                        ; Point to the old pmap search lock
+                       lis             r0,0x8000                                       ; Get 0xFFFFFFFF80000000
+                       lis             r10,hi16(EXT(pmapTrans))        ; Get the translate table
+                       add             r0,r0,r0                                        ; Get 0xFFFFFFFF00000000 for 64-bit or 0 for 32-bit
+                       blt--   cr1,hpfNestTooMuch                      ; Too many nestings, must be a loop...
+                       or              r23,r23,r0                                      ; Make sure a carry will propagate all the way in 64-bit
+                       slwi    r11,r21,3                                       ; Multiply space by 8
+                       ori             r10,r10,lo16(EXT(pmapTrans))    ; Get the translate table low part
+                       addc    r23,r23,r9                                      ; Relocate bottom half of vaddr
+                       lwz             r10,0(r10)                                      ; Get the actual translation map
+                       slwi    r12,r21,2                                       ; Multiply space by 4
+                       add             r10,r10,r11                                     ; Add in the higher part of the index
+                       rlwinm  r23,r23,0,0,31                          ; Clean up the relocated address (does nothing in 32-bit)
+                       adde    r22,r22,r8                                      ; Relocate the top half of the vaddr
+                       add             r12,r12,r10                                     ; Now we are pointing at the space to pmap translation entry
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       
+                       bt++    pf64Bitb,hpfGetPmap64           ; Separate handling for 64-bit machines
+                       lwz             r28,pmapPAddr+4(r12)            ; Get the physical address of the new pmap
+                       cmplwi  r28,0                                           ; Is the pmap paddr valid?
+                       bne+    hpfNest                                         ; Nest into new pmap...
+                       b               hpfBadPmap                                      ; Handle bad pmap
+                       
+hpfGetPmap64:
+                       ld              r28,pmapPAddr(r12)                      ; Get the physical address of the new pmap
+                       cmpldi  r28,0                                           ; Is the pmap paddr valid?
+                       bne++   hpfNest                                         ; Nest into new pmap...
+                       b               hpfBadPmap                                      ; Handle bad pmap                       
+
+
+;
+;                      Error condition.  We only allow 64 nestings.  This keeps us from having to 
+;                      check for recusive nests when we install them.
+;
+               
+                       .align  5
+
+hpfNestTooMuch:
+                       lwz             r20,savedsisr(r13)                      ; Get the DSISR
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list (R3 good from above)
+                       ori             r20,r20,1                                       ; Indicate that there was a nesting problem 
+                       stw             r20,savedsisr(r13)                      ; Stash it
+                       lwz             r11,saveexception(r13)          ; Restore the exception code
+                       b               EXT(PFSExit)                            ; Yes... (probably not though)
+
+;
+;                      Error condition - lock failed - this is fatal
+;
+               
+                       .align  5
+
+hpfBadLock:
+                       lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failMapping                          ; Show mapping failure
+                       sc
+                       
+;
+;                      Error condition - space id selected an invalid pmap - fatal
+;
+
+                       .align  5
+                       
+hpfBadPmap:
+                       lis             r0,hi16(Choke)                          ; System abend
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       li              r3,failPmap                                     ; Show invalid pmap
+                       sc
+                       
+;
+;                      Did not find any kind of mapping
+;
+
+                       .align  5
+                       
+hpfNotFound:
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock it
+                       lwz             r11,saveexception(r13)          ; Restore the exception code
+                       
+hpfExit:                                                                               ; We need this because we can not do a relative branch
+                       b               EXT(PFSExit)                            ; Yes... (probably not though)
+
+
+;
+;                      Here is where we handle special mappings.  So far, the only use is to load a 
+;                      processor specific segment register for copy in/out handling.
+;
+;                      The only (so far implemented) special map is used for copyin/copyout.
+;                      We keep a mapping of a "linkage" mapping in the per_proc.
+;                      The linkage mapping is basically a nested pmap that is switched in
+;                      as part of context switch.  It relocates the appropriate user address
+;                      space slice into the right place in the kernel.
+;
+
+                       .align  5
+
+hpfSpclNest:   
+                       la              r31,ppUMWmp(r19)                        ; Just point to the mapping
+                       oris    r27,r27,hi16(dsiLinkage)        ; Show that we had a linkage mapping here
+                       b               hpfCSrch                                        ; Go continue search...
+
+
+;
+;                      We have now found a mapping for the address we faulted on. 
+;                      
+
+;
+;                      Here we go about calculating what the VSID should be. We concatanate
+;                      the space ID (14 bits wide) 3 times.  We then slide the vaddr over
+;                      so that bits 0:35 are in 14:49 (leaves a hole for one copy of the space ID).
+;                      Then we XOR and expanded space ID and the shifted vaddr.  This gives us
+;                      the VSID.  
+;
+;                      This is used both for segment handling and PTE handling
+;
+
+
+#if maxAdrSpb != 14
+#error maxAdrSpb (address space id size) is not 14 bits!!!!!!!!!!!!
+#endif
+
+;                      Important non-volatile registers at this point ('home' means the final pmap/mapping found
+;              when a multi-level mapping has been successfully searched):
+;                              r21: home space id number
+;                              r22: relocated high-order 32 bits of vaddr
+;                              r23: relocated low-order 32 bits of vaddr       
+;                              r25: pmap physical address
+;                              r27: dsisr
+;                              r28: home pmap physical address
+;                              r29: high-order 32 bits of faulting vaddr
+;                              r30: low-order 32 bits of faulting vaddr
+;                              r31: mapping's physical address
+
+                       .align  5
+                       
+hpfFoundIt:    lwz             r12,pmapFlags(r28)                      ; Get the pmap flags so we can find the keys for this segment
+hpfGVfound:    rlwinm. r0,r27,0,dsiMissb,dsiMissb      ; Did we actually miss the segment?
+                       rlwinm  r15,r23,18,14,17                        ; Shift 32:35 (0:3) of vaddr just above space ID
+                       rlwinm  r20,r21,28,22,31                        ; Shift upper 10 bits of space into high order
+                       rlwinm  r14,r22,18,14,31                        ; Shift 0:17 of vaddr over
+                       rlwinm  r0,r27,0,dsiLinkageb,dsiLinkageb        ; Isolate linkage mapping flag
+                       rlwimi  r21,r21,14,4,17                         ; Make a second copy of space above first
+                       cmplwi  cr5,r0,0                                        ; Did we just do a special nesting?
+                       rlwimi  r15,r22,18,0,13                         ; Shift 18:31 of vaddr just above shifted 32:35 
+                       crorc   cr0_eq,cr0_eq,cr5_eq            ; Force outselves through the seg load code if special nest
+                       rlwimi  r21,r21,28,0,3                          ; Get low order of 3rd copy of space at top of register
+                       xor             r14,r14,r20                                     ; Calculate the top half of VSID
+                       xor             r15,r15,r21                                     ; Calculate the bottom half of the VSID
+                       rlwinm  r14,r14,12,15,19                        ; Slide the top of the VSID over to correct position (trim for 65 bit addressing)
+                       rlwinm  r12,r12,9,20,22                         ; Isolate and position key for cache entry
+                       rlwimi  r14,r15,12,20,31                        ; Slide top of bottom of VSID over into the top
+                       rlwinm  r15,r15,12,0,19                         ; Slide the last nybble into the low order segment position
+                       or              r12,r12,r15                                     ; Add key into the bottom of VSID
+;
+;                      Note: ESID is in R22:R23 pair; VSID is in R14:R15; cache form VSID is R14:R12
+                       
+                       bne++   hpfPteMiss                                      ; Nope, normal PTE miss...
+
+;
+;                      Here is the only place that we make an entry in the pmap segment cache.
+;
+;                      Note that we do not make an entry in the segment cache for special
+;                      nested mappings.  This makes the copy in/out segment get refreshed
+;                      when switching threads.
+;
+;                      The first thing that we do is to look up the ESID we are going to load
+;                      into a segment in the pmap cache.  If it is already there, this is
+;                      a segment that appeared since the last time we switched address spaces.
+;                      If all is correct, then it was another processors that made the cache
+;                      entry.  If not, well, it is an error that we should die on, but I have
+;                      not figured a good way to trap it yet.
+;
+;                      If we get a hit, we just bail, otherwise, lock the pmap cache, select
+;                      an entry based on the generation number, update the cache entry, and 
+;                      also update the pmap sub-tag as well.  The sub-tag is a table of 4 bit
+;                      entries that correspond to the last 4 bits (32:35 for 64-bit and 
+;                      0:3 for 32-bit) of the ESID.
+;
+;                      Then we unlock and bail.
+;
+;                      First lock it.  Then select a free slot or steal one based on the generation
+;                      number. Then store it, update the allocation flags, and unlock.
+;
+;                      The cache entry contains an image of the ESID/VSID pair we would load for
+;                      64-bit architecture.  For 32-bit, it is a simple transform to an SR image.
+;
+;                      Remember, this cache entry goes in the ORIGINAL pmap (saved in R25), not
+;                      the current one, which may have changed because we nested.
+;
+;                      Also remember that we do not store the valid bit in the ESID.  If we 
+;                      od, this will break some other stuff.
+;
+
+                       bne--   cr5,hpfNoCacheEnt2                      ; Skip the cache entry if this is a "special nest" fault....
+                       
+                       mr              r3,r25                                          ; Point to the pmap
+                       mr              r4,r29                                          ; ESID high half
+                       mr              r5,r30                                          ; ESID low half
+                       bl              pmapCacheLookup                         ; Go see if this is in the cache already
+                       
+                       mr.             r3,r3                                           ; Did we find it?
+                       mr              r4,r11                                          ; Copy this to a different register
+
+                       bne--   hpfNoCacheEnt                           ; Yes, we found it, no need to make another entry...
+                       
+                       lwz             r10,pmapSCSubTag(r25)           ; Get the first part of the sub-tag lookup table
+                       lwz             r11,pmapSCSubTag+4(r25)         ; Get the second part of the sub-tag lookup table
+                       
+                       cntlzw  r7,r4                                           ; Find a free slot
+
+                       subi    r6,r7,pmapSegCacheUse           ; We end up with a negative if we find one
+                       rlwinm  r30,r30,0,0,3                           ; Clean up the ESID
+                       srawi   r6,r6,31                                        ; Get 0xFFFFFFFF if we have one, 0 if not
+                       addi    r5,r4,1                                         ; Bump the generation number
+                       and             r7,r7,r6                                        ; Clear bit number if none empty
+                       andc    r8,r4,r6                                        ; Clear generation count if we found an empty
+                       rlwimi  r4,r5,0,17,31                           ; Insert the new generation number into the control word                        
+                       or              r7,r7,r8                                        ; Select a slot number
+                       li              r8,0                                            ; Clear
+                       andi.   r7,r7,pmapSegCacheUse-1         ; Wrap into the number we are using
+                       oris    r8,r8,0x8000                            ; Get the high bit on
+                       la              r9,pmapSegCache(r25)            ; Point to the segment cache
+                       slwi    r6,r7,4                                         ; Get index into the segment cache
+                       slwi    r2,r7,2                                         ; Get index into the segment cache sub-tag index
+                       srw             r8,r8,r7                                        ; Get the mask
+                       cmplwi  r2,32                                           ; See if we are in the first or second half of sub-tag
+                       li              r0,0                                            ; Clear
+                       rlwinm  r2,r2,0,27,31                           ; Wrap shift so we do not shift cache entries 8-F out
+                       oris    r0,r0,0xF000                            ; Get the sub-tag mask
+                       add             r9,r9,r6                                        ; Point to the cache slot
+                       srw             r0,r0,r2                                        ; Slide sub-tag mask to right slot (shift work for either half)
+                       srw             r5,r30,r2                                       ; Slide sub-tag to right slot (shift work for either half)
+                       
+                       stw             r29,sgcESID(r9)                         ; Save the top of the ESID
+                       andc    r10,r10,r0                                      ; Clear sub-tag slot in case we are in top
+                       andc    r11,r11,r0                                      ; Clear sub-tag slot in case we are in bottom
+                       stw             r30,sgcESID+4(r9)                       ; Save the bottom of the ESID
+                       or              r10,r10,r5                                      ; Stick in subtag in case top half
+                       or              r11,r11,r5                                      ; Stick in subtag in case bottom half
+                       stw             r14,sgcVSID(r9)                         ; Save the top of the VSID
+                       andc    r4,r4,r8                                        ; Clear the invalid bit for the slot we just allocated
+                       stw             r12,sgcVSID+4(r9)                       ; Save the bottom of the VSID and the key
+                       bge             hpfSCSTbottom                           ; Go save the bottom part of sub-tag
+                       
+                       stw             r10,pmapSCSubTag(r25)           ; Save the top of the sub-tag
+                       b               hpfNoCacheEnt                           ; Go finish up...
+                       
+hpfSCSTbottom:
+                       stw             r11,pmapSCSubTag+4(r25)         ; Save the bottom of the sub-tag
+
+
+hpfNoCacheEnt: 
+                       eieio                                                           ; Make sure cache is updated before lock
+                       stw             r4,pmapCCtl(r25)                        ; Unlock, allocate, and bump generation number
+
+
+hpfNoCacheEnt2:
+                       lwz             r4,ppMapFlags(r19)                      ; Get the protection key modifier
+                       bt++    pf64Bitb,hpfLoadSeg64           ; If 64-bit, go load the segment...
+                                               
+;
+;                      Make and enter 32-bit segment register
+;
+
+                       lwz             r16,validSegs(r19)                      ; Get the valid SR flags
+                       xor             r12,r12,r4                                      ; Alter the storage key before loading segment register
+                       rlwinm  r2,r30,4,28,31                          ; Isolate the segment we are setting
+                       rlwinm  r6,r12,19,1,3                           ; Insert the keys and N bit                     
+                       lis             r0,0x8000                                       ; Set bit 0
+                       rlwimi  r6,r12,20,12,31                         ; Insert 4:23 the VSID
+                       srw             r0,r0,r2                                        ; Get bit corresponding to SR
+                       rlwimi  r6,r14,20,8,11                          ; Get the last nybble of the SR contents                        
+                       or              r16,r16,r0                                      ; Show that SR is valid
+               
+                       mtsrin  r6,r30                                          ; Set the actual SR
+                       
+                       stw             r16,validSegs(r19)                      ; Set the valid SR flags
+               
+                       b               hpfPteMiss                                      ; SR loaded, go do a PTE...
+                       
+;
+;                      Make and enter 64-bit segment look-aside buffer entry.
+;                      Note that the cache entry is the right format except for valid bit.
+;                      We also need to convert from long long to 64-bit register values.
+;
+
+
+                       .align  5
+                       
+hpfLoadSeg64:
+                       ld              r16,validSegs(r19)                      ; Get the valid SLB entry flags
+                       sldi    r8,r29,32                                       ; Move high order address over
+                       sldi    r10,r14,32                                      ; Move high part of VSID over
+                       
+                       not             r3,r16                                          ; Make valids be 0s
+                       li              r0,1                                            ; Prepare to set bit 0
+                       
+                       cntlzd  r17,r3                                          ; Find a free SLB       
+                       xor             r12,r12,r4                                      ; Alter the storage key before loading segment table entry
+                       or              r9,r8,r30                                       ; Form full 64-bit address
+                       cmplwi  r17,63                                          ; Did we find a free SLB entry?         
+                       sldi    r0,r0,63                                        ; Get bit 0 set
+                       or              r10,r10,r12                                     ; Move in low part and keys
+                       addi    r17,r17,1                                       ; Skip SLB 0 always
+                       blt++   hpfFreeSeg                                      ; Yes, go load it...
+
+;
+;                      No free SLB entries, select one that is in use and invalidate it
+;
+                       lwz             r4,ppSegSteal(r19)                      ; Get the next slot to steal
+                       addi    r17,r4,pmapSegCacheUse+1        ; Select stealee from non-cached slots only
+                       addi    r4,r4,1                                         ; Set next slot to steal
+                       slbmfee r7,r17                                          ; Get the entry that is in the selected spot
+                       subi    r2,r4,63-pmapSegCacheUse        ; Force steal to wrap
+                       rldicr  r7,r7,0,35                                      ; Clear the valid bit and the rest
+                       srawi   r2,r2,31                                        ; Get -1 if steal index still in range
+                       slbie   r7                                                      ; Invalidate the in-use SLB entry
+                       and             r4,r4,r2                                        ; Reset steal index when it should wrap
+                       isync                                                           ; 
+                       
+                       stw             r4,ppSegSteal(r19)                      ; Set the next slot to steal
+;
+;                      We are now ready to stick the SLB entry in the SLB and mark it in use
+;
+
+hpfFreeSeg:    
+                       subi    r4,r17,1                                        ; Adjust shift to account for skipping slb 0
+                       mr              r7,r9                                           ; Get a copy of the ESID with bits 36:63 clear
+                       srd             r0,r0,r4                                        ; Set bit mask for allocation
+                       oris    r9,r9,0x0800                            ; Turn on the valid bit
+                       or              r16,r16,r0                                      ; Turn on the allocation flag
+                       rldimi  r9,r17,0,58                                     ; Copy in the SLB entry selector
+                       
+                       beq++   cr5,hpfNoBlow                           ; Skip blowing away the SLBE if this is not a special nest...
+                       slbie   r7                                                      ; Blow away a potential duplicate
+                       
+hpfNoBlow:     slbmte  r10,r9                                          ; Make that SLB entry
+
+                       std             r16,validSegs(r19)                      ; Mark as valid
+                       b               hpfPteMiss                                      ; STE loaded, go do a PTE...
+                       
+;
+;                      The segment has been set up and loaded if need be.  Now we are ready to build the
+;                      PTE and get it into the hash table.
+;
+;                      Note that there is actually a race here.  If we start fault processing on
+;                      a different pmap, i.e., we have descended into a nested pmap, it is possible
+;                      that the nest could have been removed from the original pmap.  We would
+;                      succeed with this translation anyway.  I do not think we need to worry
+;                      about this (famous last words) because nobody should be unnesting anything 
+;                      if there are still people activily using them.  It should be up to the
+;                      higher level VM system to put the kibosh on this.
+;
+;                      There is also another race here: if we fault on the same mapping on more than
+;                      one processor at the same time, we could end up with multiple PTEs for the same
+;                      mapping.  This is not a good thing....   We really only need one of the
+;                      fault handlers to finish, so what we do is to set a "fault in progress" flag in
+;                      the mapping.  If we see that set, we just abandon the handler and hope that by
+;                      the time we restore context and restart the interrupted code, the fault has
+;                      been resolved by the other guy.  If not, we will take another fault.
+;
+               
+;
+;                      NOTE: IMPORTANT - CR7 contains a flag indicating if we have a block mapping or not.
+;                      It is required to stay there until after we call mapSelSlot!!!!
+;
+
+                       .align  5
+                       
+hpfPteMiss:    lwarx   r0,0,r31                                        ; Load the mapping flag field
+                       lwz             r12,mpPte(r31)                          ; Get the quick pointer to PTE
+                       li              r3,mpHValid                                     ; Get the PTE valid bit
+                       andi.   r2,r0,lo16(mpFIP)                       ; Are we handling a fault on the other side?
+                       ori             r2,r0,lo16(mpFIP)                       ; Set the fault in progress flag
+                       crnot   cr1_eq,cr0_eq                           ; Remember if FIP was on
+                       and.    r12,r12,r3                                      ; Isolate the valid bit
+                       crorc   cr0_eq,cr1_eq,cr0_eq            ; Bail if FIP is on.  Then, if already have PTE, bail...
+                       beq--   hpfAbandon                                      ; Yes, other processor is or already has handled this...
+                       rlwinm  r0,r2,0,mpType                          ; Isolate mapping type
+                       cmplwi  r0,mpBlock                                      ; Is this a block mapping?
+                       crnot   cr7_eq,cr0_eq                           ; Remember if we have a block mapping
+                       stwcx.  r2,0,r31                                        ; Store the flags
+                       bne--   hpfPteMiss                                      ; Collision, try again...
+
+                       bt++    pf64Bitb,hpfBldPTE64            ; Skip down to the 64 bit stuff...
+
+;
+;                      At this point we are about to do the 32-bit PTE generation.
+;
+;                      The following is the R14:R15 pair that contains the "shifted" VSID:
+;
+;                             1        2        3        4        4        5      6 
+;           0        8        6        4        2        0        8        6      3
+;          +--------+--------+--------+--------+--------+--------+--------+--------+
+;          |00000000|0000000V|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVV////|////////|    
+;          +--------+--------+--------+--------+--------+--------+--------+--------+                   
+;
+;                      The 24 bits of the 32-bit architecture VSID is in the following:
+;
+;                             1        2        3        4        4        5      6 
+;           0        8        6        4        2        0        8        6      3
+;          +--------+--------+--------+--------+--------+--------+--------+--------+
+;          |////////|////////|////////|////VVVV|VVVVVVVV|VVVVVVVV|VVVV////|////////|    
+;          +--------+--------+--------+--------+--------+--------+--------+--------+                   
+;
+
+
+hpfBldPTE32:
+                       lwz             r25,mpVAddr+4(r31)                      ; Grab the base virtual address for the mapping (32-bit portion)        
+                       lwz             r24,mpPAddr(r31)                        ; Grab the base physical page number for the mapping    
+
+                       mfsdr1  r27                                                     ; Get the hash table base address
+
+                       rlwinm  r0,r23,0,4,19                           ; Isolate just the page index
+                       rlwinm  r18,r23,10,26,31                        ; Extract the API
+                       xor             r19,r15,r0                                      ; Calculate hash << 12
+                       mr              r2,r25                                          ; Save the flag part of the mapping
+                       rlwimi  r18,r14,27,1,4                          ; Move bits 28:31 of the "shifted" VSID into the PTE image
+                       rlwinm  r16,r27,16,7,15                         ; Extract the hash table size
+                       rlwinm  r25,r25,0,0,19                          ; Clear out the flags
+                       slwi    r24,r24,12                                      ; Change ppnum to physical address (note: 36-bit addressing no supported)
+                       sub             r25,r23,r25                                     ; Get offset in mapping to page (0 unless block map)
+                       ori             r16,r16,lo16(0xFFC0)            ; Slap in the bottom of the mask
+                       rlwinm  r27,r27,0,0,15                          ; Extract the hash table base
+                       rlwinm  r19,r19,26,6,25                         ; Shift hash over to make offset into hash table
+                       add             r24,r24,r25                                     ; Adjust to true physical address
+                       rlwimi  r18,r15,27,5,24                         ; Move bits 32:31 of the "shifted" VSID into the PTE image
+                       rlwimi  r24,r2,0,20,31                          ; Slap in the WIMG and prot
+                       and             r19,r19,r16                                     ; Wrap hash table offset into the hash table
+                       ori             r24,r24,lo16(mpR)                       ; Turn on the reference bit right now
+                       rlwinm  r20,r19,28,10,29                        ; Shift hash over to make offset into PCA
+                       add             r19,r19,r27                                     ; Point to the PTEG
+                       subfic  r20,r20,-4                                      ; Get negative offset to PCA
+                       oris    r18,r18,lo16(0x8000)            ; Make sure the valid bit is on
+                       add             r20,r20,r27                                     ; Point to the PCA slot
+               
+;
+;                      We now have a valid PTE pair in R18/R24.  R18 is PTE upper and R24 is PTE lower.
+;                      R19 contains the offset of the PTEG in the hash table. R20 has offset into the PCA.
+;              
+;                      We need to check PTE pointer (mpPte) again after we lock the PTEG.  It is possible 
+;                      that some other processor beat us and stuck in a PTE or that 
+;                      all we had was a simple segment exception and the PTE was there the whole time.
+;                      If we find one a pointer, we are done.
+;
+
+                       mr              r7,r20                                          ; Copy the PCA pointer
+                       bl              mapLockPteg                                     ; Lock the PTEG
+       
+                       lwz             r12,mpPte(r31)                          ; Get the offset to the PTE
+                       mr              r17,r6                                          ; Remember the PCA image
+                       mr              r16,r6                                          ; Prime the post-select PCA image
+                       andi.   r0,r12,mpHValid                         ; Is there a PTE here already?
+                       li              r21,8                                           ; Get the number of slots
+
+                       bne-    cr7,hpfNoPte32                          ; Skip this for a block mapping...
+
+                       bne-    hpfBailOut                                      ; Someone already did this for us...
+
+;
+;                      The mapSelSlot function selects a PTEG slot to use. As input, it uses R6 as a 
+;                      pointer to the PCA.  When it returns, R3 contains 0 if an unoccupied slot was
+;                      selected, 1 if it stole a non-block PTE, or 2 if it stole a block mapped PTE.
+;                      R4 returns the slot index.
+;
+;                      REMEMBER: CR7 indicates that we are building a block mapping.
+;
+
+hpfNoPte32:    subic.  r21,r21,1                                       ; See if we have tried all slots
+                       mr              r6,r17                                          ; Get back the original PCA
+                       rlwimi  r6,r16,0,8,15                           ; Insert the updated steal slot
+                       blt-    hpfBailOut                                      ; Holy Cow, all slots are locked...
+                       
+                       bl              mapSelSlot                                      ; Go select a slot (note that the PCA image is already set up)
+
+                       cmplwi  cr5,r3,1                                        ; Did we steal a slot?
+                       rlwimi  r19,r4,3,26,28                          ; Insert PTE index into PTEG address yielding PTE address
+                       mr              r16,r6                                          ; Remember the PCA image after selection
+                       blt+    cr5,hpfInser32                          ; Nope, no steal...
+                       
+                       lwz             r6,0(r19)                                       ; Get the old PTE
+                       lwz             r7,4(r19)                                       ; Get the real part of the stealee
+                       rlwinm  r6,r6,0,1,31                            ; Clear the valid bit
+                       bgt             cr5,hpfNipBM                            ; Do not try to lock a non-existant physent for a block mapping...
+                       srwi    r3,r7,12                                        ; Change phys address to a ppnum
+                       bl              mapFindPhyTry                           ; Go find and try to lock physent (note: if R3 is 0, there is no physent for this page)
+                       cmplwi  cr1,r3,0                                        ; Check if this is in RAM
+                       bne-    hpfNoPte32                                      ; Could not get it, try for another...
+                       
+                       crmove  cr5_gt,cr1_eq                           ; If we did not find a physent, pretend that this is a block map
+                       
+hpfNipBM:      stw             r6,0(r19)                                       ; Set the invalid PTE
+
+                       sync                                                            ; Make sure the invalid is stored
+                       li              r9,tlbieLock                            ; Get the TLBIE lock
+                       rlwinm  r10,r6,21,0,3                           ; Shift last 4 bits of space to segment part
+                       
+hpfTLBIE32:    lwarx   r0,0,r9                                         ; Get the TLBIE lock 
+                       mfsprg  r4,0                                            ; Get the per_proc
+                       rlwinm  r8,r6,25,18,31                          ; Extract the space ID
+                       rlwinm  r11,r6,25,18,31                         ; Extract the space ID
+                       lwz             r7,hwSteals(r4)                         ; Get the steal count
+                       srwi    r2,r6,7                                         ; Align segment number with hash
+                       rlwimi  r11,r11,14,4,17                         ; Get copy above ourselves
+                       mr.             r0,r0                                           ; Is it locked? 
+                       srwi    r0,r19,6                                        ; Align PTEG offset for back hash
+                       xor             r2,r2,r11                                       ; Get the segment number (plus a whole bunch of extra bits)
+                       xor             r11,r11,r0                                      ; Hash backwards to partial vaddr
+                       rlwinm  r12,r2,14,0,3                           ; Shift segment up
+                       mfsprg  r2,2                                            ; Get feature flags 
+                       li              r0,1                                            ; Get our lock word 
+                       rlwimi  r12,r6,22,4,9                           ; Move up the API
+                       bne-    hpfTLBIE32                                      ; It is locked, go wait...
+                       rlwimi  r12,r11,12,10,19                        ; Move in the rest of the vaddr
+                       
+                       stwcx.  r0,0,r9                                         ; Try to get it
+                       bne-    hpfTLBIE32                                      ; We was beat...
+                       addi    r7,r7,1                                         ; Bump the steal count
+                       
+                       rlwinm. r0,r2,0,pfSMPcapb,pfSMPcapb     ; Can this be an MP box?
+                       li              r0,0                                            ; Lock clear value 
+
+                       tlbie   r12                                                     ; Invalidate it everywhere 
+
+                       
+                       beq-    hpfNoTS32                                       ; Can not have MP on this machine...
+                       
+                       eieio                                                           ; Make sure that the tlbie happens first 
+                       tlbsync                                                         ; Wait for everyone to catch up 
+                       sync                                                            ; Make sure of it all
+
+hpfNoTS32:     stw             r0,tlbieLock(0)                         ; Clear the tlbie lock
+                       
+                       stw             r7,hwSteals(r4)                         ; Save the steal count
+                       bgt             cr5,hpfInser32                          ; We just stole a block mapping...
+                       
+                       lwz             r4,4(r19)                                       ; Get the RC of the just invalidated PTE
+                       
+                       la              r11,ppLink+4(r3)                        ; Point to the master RC copy
+                       lwz             r7,ppLink+4(r3)                         ; Grab the pointer to the first mapping
+                       rlwinm  r2,r4,27,ppRb-32,ppCb-32        ; Position the new RC
+
+hpfMrgRC32:    lwarx   r0,0,r11                                        ; Get the master RC
+                       or              r0,r0,r2                                        ; Merge in the new RC
+                       stwcx.  r0,0,r11                                        ; Try to stick it back
+                       bne-    hpfMrgRC32                                      ; Try again if we collided...
+                       
+                       
+hpfFPnch:      rlwinm. r7,r7,0,~ppFlags                        ; Clean and test mapping address
+                       beq-    hpfLostPhys                                     ; We could not find our mapping.  Kick the bucket...
+                       
+                       lhz             r10,mpSpace(r7)                         ; Get the space
+                       lwz             r9,mpVAddr+4(r7)                        ; And the vaddr
+                       cmplw   cr1,r10,r8                                      ; Is this one of ours?
+                       xor             r9,r12,r9                                       ; Compare virtual address
+                       cmplwi  r9,0x1000                                       ; See if we really match
+                       crand   cr0_eq,cr1_eq,cr0_lt            ; See if both space and vaddr match
+                       beq+    hpfFPnch2                                       ; Yes, found ours...
+                       
+                       lwz             r7,mpAlias+4(r7)                        ; Chain on to the next
+                       b               hpfFPnch                                        ; Check it out...
+
+hpfFPnch2:     sub             r0,r19,r27                                      ; Get offset to the PTEG
+                       stw             r0,mpPte(r7)                            ; Invalidate the quick pointer (keep quick pointer pointing to PTEG)
+                       bl              mapPhysUnlock                           ; Unlock the physent now
+                       
+hpfInser32:    oris    r18,r18,lo16(0x8000)            ; Make sure the valid bit is on
+
+                       stw             r24,4(r19)                                      ; Stuff in the real part of the PTE
+                       eieio                                                           ; Make sure this gets there first
+
+                       stw             r18,0(r19)                                      ; Stuff the virtual part of the PTE and make it valid
+                       mr              r17,r16                                         ; Get the PCA image to save
+                       b               hpfFinish                                       ; Go join the common exit code...
+                       
+                       
+;
+;                      At this point we are about to do the 64-bit PTE generation.
+;
+;                      The following is the R14:R15 pair that contains the "shifted" VSID:
+;
+;                             1        2        3        4        4        5      6 
+;           0        8        6        4        2        0        8        6      3
+;          +--------+--------+--------+--------+--------+--------+--------+--------+
+;          |00000000|0000000V|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVVVVVV|VVVV////|////////|    
+;          +--------+--------+--------+--------+--------+--------+--------+--------+                   
+;
+;
+
+                       .align  5
+
+hpfBldPTE64:
+                       ld              r10,mpVAddr(r31)                        ; Grab the base virtual address for the mapping 
+                       lwz             r24,mpPAddr(r31)                        ; Grab the base physical page number for the mapping    
+
+                       mfsdr1  r27                                                     ; Get the hash table base address
+
+                       sldi    r11,r22,32                                      ; Slide top of adjusted EA over
+                       sldi    r14,r14,32                                      ; Slide top of VSID over
+                       rlwinm  r5,r27,0,27,31                          ; Isolate the size
+                       eqv             r16,r16,r16                                     ; Get all foxes here
+                       rlwimi  r15,r23,16,20,24                        ; Stick in EA[36:40] to make AVPN       
+                       mr              r2,r10                                          ; Save the flag part of the mapping
+                       or              r11,r11,r23                                     ; Stick in bottom of adjusted EA for full 64-bit value  
+                       rldicr  r27,r27,0,45                            ; Clean up the hash table base
+                       or              r15,r15,r14                                     ; Stick in bottom of AVPN for full 64-bit value 
+                       rlwinm  r0,r11,0,4,19                           ; Clear out everything but the page
+                       subfic  r5,r5,46                                        ; Get number of leading zeros
+                       xor             r19,r0,r15                                      ; Calculate hash
+                       ori             r15,r15,1                                       ; Turn on valid bit in AVPN to make top of PTE
+                       srd             r16,r16,r5                                      ; Shift over to get length of table
+                       srdi    r19,r19,5                                       ; Convert page offset to hash table offset
+                       rldicr  r16,r16,0,56                            ; Clean up lower bits in hash table size                        
+                       rldicr  r10,r10,0,51                            ; Clear out flags
+                       sldi    r24,r24,12                                      ; Change ppnum to physical address
+                       sub             r11,r11,r10                                     ; Get the offset from the base mapping
+                       and             r19,r19,r16                                     ; Wrap into hash table
+                       add             r24,r24,r11                                     ; Get actual physical address of this page
+                       srdi    r20,r19,5                                       ; Convert PTEG offset to PCA offset
+                       rldimi  r24,r2,0,52                                     ; Insert the keys, WIMG, RC, etc.
+                       subfic  r20,r20,-4                                      ; Get negative offset to PCA
+                       ori             r24,r24,lo16(mpR)                       ; Force on the reference bit
+                       add             r20,r20,r27                                     ; Point to the PCA slot         
+                       add             r19,r19,r27                                     ; Point to the PTEG
+                       
+;
+;                      We now have a valid PTE pair in R15/R24.  R15 is PTE upper and R24 is PTE lower.
+;                      R19 contains the offset of the PTEG in the hash table. R20 has offset into the PCA.
+;              
+;                      We need to check PTE pointer (mpPte) again after we lock the PTEG.  It is possible 
+;                      that some other processor beat us and stuck in a PTE or that 
+;                      all we had was a simple segment exception and the PTE was there the whole time.
+;                      If we find one a pointer, we are done.
+;
+                       
+                       mr              r7,r20                                          ; Copy the PCA pointer
+                       bl              mapLockPteg                                     ; Lock the PTEG
+       
+                       lwz             r12,mpPte(r31)                          ; Get the offset to the PTE
+                       mr              r17,r6                                          ; Remember the PCA image
+                       mr              r18,r6                                          ; Prime post-selection PCA image
+                       andi.   r0,r12,mpHValid                         ; See if we have a PTE now
+                       li              r21,8                                           ; Get the number of slots
+               
+                       bne--   cr7,hpfNoPte64                          ; Skip this for a block mapping...
+
+                       bne--   hpfBailOut                                      ; Someone already did this for us...
+
+;
+;                      The mapSelSlot function selects a PTEG slot to use. As input, it uses R3 as a 
+;                      pointer to the PCA.  When it returns, R3 contains 0 if an unoccupied slot was
+;                      selected, 1 if it stole a non-block PTE, or 2 if it stole a block mapped PTE.
+;                      R4 returns the slot index.
+;
+;                      REMEMBER: CR7 indicates that we are building a block mapping.
+;
+
+hpfNoPte64:    subic.  r21,r21,1                                       ; See if we have tried all slots
+                       mr              r6,r17                                          ; Restore original state of PCA
+                       rlwimi  r6,r18,0,8,15                           ; Insert the updated steal slot
+                       blt-    hpfBailOut                                      ; Holy Cow, all slots are locked...
+                       
+                       bl              mapSelSlot                                      ; Go select a slot
+
+                       cmplwi  cr5,r3,1                                        ; Did we steal a slot?                  
+                       mr              r18,r6                                          ; Remember the PCA image after selection
+                       insrdi  r19,r4,3,57                                     ; Insert slot index into PTEG address bits 57:59, forming the PTE address
+                       lwz             r10,hwSteals(r2)                        ; Get the steal count
+                       blt++   cr5,hpfInser64                          ; Nope, no steal...
+
+                       ld              r6,0(r19)                                       ; Get the old PTE
+                       ld              r7,8(r19)                                       ; Get the real part of the stealee
+                       rldicr  r6,r6,0,62                                      ; Clear the valid bit
+                       bgt             cr5,hpfNipBMx                           ; Do not try to lock a non-existant physent for a block mapping...
+                       srdi    r3,r7,12                                        ; Change page address to a page address
+                       bl              mapFindPhyTry                           ; Go find and try to lock physent (note: if R3 is 0, there is no physent for this page)
+                       cmplwi  cr1,r3,0                                        ; Check if this is in RAM
+                       bne--   hpfNoPte64                                      ; Could not get it, try for another...
+                       
+                       crmove  cr5_gt,cr1_eq                           ; If we did not find a physent, pretend that this is a block map
+                       
+hpfNipBMx:     std             r6,0(r19)                                       ; Set the invalid PTE
+                       li              r9,tlbieLock                            ; Get the TLBIE lock
+
+                       srdi    r11,r6,5                                        ; Shift VSID over for back hash
+                       mfsprg  r4,0                                            ; Get the per_proc
+                       xor             r11,r11,r19                                     ; Hash backwards to get low bits of VPN
+                       sync                                                            ; Make sure the invalid is stored
+                       
+                       sldi    r12,r6,16                                       ; Move AVPN to EA position
+                       sldi    r11,r11,5                                       ; Move this to the page position
+                       
+hpfTLBIE64:    lwarx   r0,0,r9                                         ; Get the TLBIE lock 
+                       mr.             r0,r0                                           ; Is it locked? 
+                       li              r0,1                                            ; Get our lock word
+                       bne--   hpfTLBIE65                                      ; It is locked, go wait...
+                       
+                       stwcx.  r0,0,r9                                         ; Try to get it
+                       rldimi  r12,r11,0,41                            ; Stick the low part of the page number into the AVPN
+                       rldicl  r8,r6,52,50                                     ; Isolate the address space ID
+                       bne--   hpfTLBIE64                                      ; We was beat...
+                       addi    r10,r10,1                                       ; Bump the steal count
+                       
+                       rldicl  r11,r12,0,16                            ; Clear cause the book says so
+                       li              r0,0                                            ; Lock clear value 
+
+                       tlbie   r11                                                     ; Invalidate it everywhere 
+
+                       mr              r7,r8                                           ; Get a copy of the space ID
+                       eieio                                                           ; Make sure that the tlbie happens first
+                       rldimi  r7,r7,14,36                                     ; Copy address space to make hash value
+                       tlbsync                                                         ; Wait for everyone to catch up
+                       rldimi  r7,r7,28,22                                     ; Add in a 3rd copy of the hash up top
+                       srdi    r2,r6,26                                        ; Shift original segment down to bottom
+                       
+                       ptesync                                                         ; Make sure of it all
+                       xor             r7,r7,r2                                        ; Compute original segment
+                       stw             r0,tlbieLock(0)                         ; Clear the tlbie lock
+
+                       stw             r10,hwSteals(r4)                        ; Save the steal count
+                       bgt             cr5,hpfInser64                          ; We just stole a block mapping...
+                       
+                       rldimi  r12,r7,28,0                                     ; Insert decoded segment
+                       rldicl  r4,r12,0,13                                     ; Trim to max supported address
+                       
+                       ld              r12,8(r19)                                      ; Get the RC of the just invalidated PTE                        
+
+                       la              r11,ppLink+4(r3)                        ; Point to the master RC copy
+                       ld              r7,ppLink(r3)                           ; Grab the pointer to the first mapping
+                       rlwinm  r2,r12,27,ppRb-32,ppCb-32       ; Position the new RC
+
+hpfMrgRC64:    lwarx   r0,0,r11                                        ; Get the master RC
+                       li              r12,ppLFAmask                           ; Get mask to clean up alias pointer
+                       or              r0,r0,r2                                        ; Merge in the new RC
+                       rotrdi  r12,r12,ppLFArrot                       ; Rotate clean up mask to get 0xF0000000000000000F
+                       stwcx.  r0,0,r11                                        ; Try to stick it back
+                       bne--   hpfMrgRC64                                      ; Try again if we collided...
+       
+hpfFPnchx:     andc.   r7,r7,r12                                       ; Clean and test mapping address
+                       beq--   hpfLostPhys                                     ; We could not find our mapping.  Kick the bucket...
+                       
+                       lhz             r10,mpSpace(r7)                         ; Get the space
+                       ld              r9,mpVAddr(r7)                          ; And the vaddr
+                       cmplw   cr1,r10,r8                                      ; Is this one of ours?
+                       xor             r9,r4,r9                                        ; Compare virtual address
+                       cmpldi  r9,0x1000                                       ; See if we really match
+                       crand   cr0_eq,cr1_eq,cr0_lt            ; See if both space and vaddr match
+                       beq++   hpfFPnch2x                                      ; Yes, found ours...
+                       
+                       ld              r7,mpAlias(r7)                          ; Chain on to the next
+                       b               hpfFPnchx                                       ; Check it out...
+
+                       .align  5
+
+hpfTLBIE65:    li              r7,lgKillResv                           ; Point to the reservatio kill area
+                       stwcx.  r7,0,r7                                         ; Kill reservation              
+                       
+hpfTLBIE63: lwz                r0,0(r9)                                        ; Get the TLBIE lock
+                       mr.             r0,r0                                           ; Is it locked?
+                       beq++   hpfTLBIE64                                      ; Yup, wait for it...
+                       b               hpfTLBIE63                                      ; Nope, try again..
+
+
+
+hpfFPnch2x:    sub             r0,r19,r27                                      ; Get offset to PTEG
+                       stw             r0,mpPte(r7)                            ; Invalidate the quick pointer (keep pointing at PTEG though)
+                       bl              mapPhysUnlock                           ; Unlock the physent now
+                       
+
+hpfInser64:    std             r24,8(r19)                                      ; Stuff in the real part of the PTE
+                       eieio                                                           ; Make sure this gets there first
+                       std             r15,0(r19)                                      ; Stuff the virtual part of the PTE and make it valid
+                       mr              r17,r18                                         ; Get the PCA image to set
+                       b               hpfFinish                                       ; Go join the common exit code...
+
+hpfLostPhys:
+                       lis             r0,hi16(Choke)                          ; System abend - we must find the stolen mapping or we are dead
+                       ori             r0,r0,lo16(Choke)                       ; System abend
+                       sc
+                       
+;
+;                      This is the common code we execute when we are finished setting up the PTE.
+;
+       
+                       .align  5
+                       
+hpfFinish:     sub             r4,r19,r27                                      ; Get offset of PTE
+                       ori             r4,r4,lo16(mpHValid)            ; Add valid bit to PTE offset
+                       bne             cr7,hpfBailOut                          ; Do not set the PTE pointer for a block map
+                       stw             r4,mpPte(r31)                           ; Remember our PTE
+                       
+hpfBailOut:    eieio                                                           ; Make sure all updates come first
+                       stw             r17,0(r20)                                      ; Unlock and set the final PCA
+                       
+;
+;                      This is where we go if we have started processing the fault, but find that someone
+;                      else has taken care of it.
+;
+
+hpfIgnore:     lwz             r2,mpFlags(r31)                         ; Get the mapping flags
+                       rlwinm  r2,r2,0,mpFIPb+1,mpFIPb-1       ; Clear the "fault in progress" flag
+                       sth             r2,mpFlags+2(r31)                       ; Set it
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+
+                       li              r11,T_IN_VAIN                           ; Say that it was handled
+                       b               EXT(PFSExit)                            ; Leave...
+
+;
+;                      This is where we go when we  find that someone else
+;                      is in the process of handling the fault.
+;
+
+hpfAbandon:    li              r3,lgKillResv                           ; Kill off any reservation
+                       stwcx.  r3,0,r3                                         ; Do it
+                       
+                       la              r3,pmapSXlk(r28)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+
+                       li              r11,T_IN_VAIN                           ; Say that it was handled
+                       b               EXT(PFSExit)                            ; Leave...
+                       
+;
+;                      Guest shadow assist -- page fault handler
+;
+;                      Here we handle a fault in a guest pmap that has the guest shadow mapping
+;                      assist active. We locate the VMM pmap extension block, which contains an
+;                      index over the discontiguous multi-page shadow hash table. The index
+;                      corresponding to our vaddr is selected, and the selected group within
+;                      that page is searched for a valid and active entry that contains
+;                      our vaddr and space id. The search is pipelined, so that we may fetch
+;                      the next slot while examining the current slot for a hit. The final
+;                      search iteration is unrolled so that we don't fetch beyond the end of
+;                      our group, which could have dire consequences depending upon where the
+;                      physical hash page is located.
+;
+;                      The VMM pmap extension block occupies a page. Begining at offset 0, we
+;                      have the pmap_vmm_ext proper. Aligned at the first 128-byte boundary
+;                      after the pmap_vmm_ext is the hash table physical address index, a 
+;                      linear list of 64-bit physical addresses of the pages that comprise
+;                      the hash table.
+;
+;                      In the event that we succesfully locate a guest mapping, we re-join
+;                      the page fault path at hpfGVfound with the mapping's address in r31;
+;                      otherwise, we re-join at hpfNotFound. In either case, we re-join holding
+;                      a share of the pmap search lock for the host pmap with the host pmap's
+;                      address in r28, the guest pmap's space id in r21, and the guest pmap's
+;                      flags in r12.
+;
+
+                       .align  5
+hpfGVxlate:
+                       bt              pf64Bitb,hpfGV64                        ; Take 64-bit path for 64-bit machine
+                       
+                       lwz             r11,pmapVmmExtPhys+4(r28)       ; r11 <- VMM pmap extension block paddr
+                       lwz             r12,pmapFlags(r28)                      ; r12 <- guest pmap's flags
+                       lwz             r21,pmapSpace(r28)                      ; r21 <- guest space ID number
+                       lwz             r28,vmxHostPmapPhys+4(r11)      ; r28 <- host pmap's paddr
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       rlwinm  r10,r30,0,0xFFFFF000            ; r10 <- page-aligned guest vaddr
+                       lwz             r6,vxsGpf(r11)                          ; Get guest fault count
+                       
+                       srwi    r3,r10,12                                       ; Form shadow hash:
+                       xor             r3,r3,r21                                       ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r4,r3,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r4                                      ; r31 <- hash page index entry
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r3,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+
+                       la              r3,pmapSXlk(r28)                        ; Point to the host pmap's search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne-    hpfBadLock                                      ; Nope...
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       addi    r6,r6,1                                         ; Increment guest fault count
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       stw             r6,vxsGpf(r11)                          ; Update guest fault count
+                       b               hpfGVlp32
+
+                       .align  5
+hpfGVlp32:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       andi.   r6,r6,mpgFree+mpgDormant        ; Isolate guest free and dormant flags
+                       xor             r7,r7,r21                                       ; Compare space ID
+                       or              r0,r6,r7                                        ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r10                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             hpfGVfound                                      ; Join common patch on hit (r31 points to mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    hpfGVlp32                                       ; Iterate
+
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r3,r3,mpgFree+mpgDormant        ; Isolate guest free and dormant flag
+                       xor             r4,r4,r21                                       ; Compare space ID
+                       or              r0,r3,r4                                        ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r10                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             hpfGVfound                                      ; Join common patch on hit (r31 points to mapping)
+                       
+                       b               hpfGVmiss
+
+                       .align  5
+hpfGV64:
+                       ld              r11,pmapVmmExtPhys(r28)         ; r11 <- VMM pmap extension block paddr
+                       lwz             r12,pmapFlags(r28)                      ; r12 <- guest pmap's flags
+                       lwz             r21,pmapSpace(r28)                      ; r21 <- guest space ID number
+                       ld              r28,vmxHostPmapPhys(r11)        ; r28 <- host pmap's paddr
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       rlwinm  r10,r30,0,0xFFFFF000            ; Form 64-bit guest vaddr
+                       rldimi  r10,r29,32,0                            ;  cleaning up low-order 12 bits                        
+                       lwz             r6,vxsGpf(r11)                          ; Get guest fault count
+
+                       srwi    r3,r10,12                                       ; Form shadow hash:
+                       xor             r3,r3,r21                                       ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r4,r3,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r4                                      ; r31 <- hash page index entry
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r3,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+                                                                                               
+                       la              r3,pmapSXlk(r28)                        ; Point to the host pmap's search lock
+                       bl              sxlkShared                                      ; Go get a shared lock on the mapping lists
+                       mr.             r3,r3                                           ; Did we get the lock?
+                       bne--   hpfBadLock                                      ; Nope...
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       addi    r6,r6,1                                         ; Increment guest fault count
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       stw             r6,vxsGpf(r11)                          ; Update guest fault count
+                       b               hpfGVlp64
+                       
+                       .align  5
+hpfGVlp64:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       andi.   r6,r6,mpgFree+mpgDormant        ; Isolate guest free and dormant flag
+                       xor             r7,r7,r21                                       ; Compare space ID
+                       or              r0,r6,r7                                        ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r10                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             hpfGVfound                                      ; Join common path on hit (r31 points to mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    hpfGVlp64                                       ; Iterate
+
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r3,r3,mpgFree+mpgDormant        ; Isolate guest free and dormant flag
+                       xor             r4,r4,r21                                       ; Compare space ID
+                       or              r0,r3,r4                                        ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r10                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             hpfGVfound                                      ; Join common path on hit (r31 points to mapping)
+
+hpfGVmiss:
+                       lwz             r6,vxsGpfMiss(r11)                      ; Guest guest fault miss count
+                       addi    r6,r6,1                                         ; Increment miss count
+                       stw             r6,vxsGpfMiss(r11)                      ; Update guest fault miss count
+                       b               hpfNotFound
+                       
+/*
+ *                     hw_set_user_space(pmap) 
+ *                     hw_set_user_space_dis(pmap) 
+ *
+ *                     Indicate whether memory space needs to be switched.
+ *                     We really need to turn off interrupts here, because we need to be non-preemptable
+ *
+ *                     hw_set_user_space_dis is used when interruptions are already disabled. Mind the
+ *                     register usage here.   The VMM switch code in vmachmon.s that calls this
+ *                     know what registers are in use.  Check that if these change.
+ */
+
+
+       
+                       .align  5
+                       .globl  EXT(hw_set_user_space)
+
+LEXT(hw_set_user_space)
+
+                       lis             r8,hi16(MASK(MSR_VEC))          ; Get the vector enable
+                       mfmsr   r10                                                     ; Get the current MSR 
+                       ori             r8,r8,lo16(MASK(MSR_FP))        ; Add in FP
+                       ori             r9,r8,lo16(MASK(MSR_EE))        ; Add in the EE
+                       andc    r10,r10,r8                                      ; Turn off VEC, FP for good
+                       andc    r9,r10,r9                                       ; Turn off EE also
+                       mtmsr   r9                                                      ; Disable them 
+                       isync                                                           ; Make sure FP and vec are off
+                       mfsprg  r6,1                                            ; Get the current activation
+                       lwz             r6,ACT_PER_PROC(r6)                     ; Get the per_proc block
+                       lwz             r2,ppUserPmapVirt(r6)           ; Get our virtual pmap address
+                       mfsprg  r4,2                                            ; The the feature flags
+                       lwz             r7,pmapvr(r3)                           ; Get the v to r translation
+                       lwz             r8,pmapvr+4(r3)                         ; Get the v to r translation
+                       mtcrf   0x80,r4                                         ; Get the Altivec flag
+                       xor             r4,r3,r8                                        ; Get bottom of the real address of bmap anchor
+                       cmplw   cr1,r3,r2                                       ; Same address space as before?
+                       stw             r7,ppUserPmap(r6)                       ; Show our real pmap address
+                       crorc   cr1_eq,cr1_eq,pfAltivecb        ; See if same address space or not altivec machine
+                       stw             r4,ppUserPmap+4(r6)                     ; Show our real pmap address
+                       stw             r3,ppUserPmapVirt(r6)           ; Show our virtual pmap address
+                       mtmsr   r10                                                     ; Restore interruptions 
+                       beqlr-- cr1                                                     ; Leave if the same address space or not Altivec
+
+                       dssall                                                          ; Need to kill all data streams if adrsp changed
+                       sync
+                       blr                                                                     ; Return... 
+       
+                       .align  5
+                       .globl  EXT(hw_set_user_space_dis)
+
+LEXT(hw_set_user_space_dis)
+
+                       lwz             r7,pmapvr(r3)                           ; Get the v to r translation
+                       mfsprg  r4,2                                            ; The the feature flags
+                       lwz             r8,pmapvr+4(r3)                         ; Get the v to r translation
+                       mfsprg  r6,1                                            ; Get the current activation
+                       lwz             r6,ACT_PER_PROC(r6)                     ; Get the per_proc block
+                       lwz             r2,ppUserPmapVirt(r6)           ; Get our virtual pmap address
+                       mtcrf   0x80,r4                                         ; Get the Altivec flag
+                       xor             r4,r3,r8                                        ; Get bottom of the real address of bmap anchor
+                       cmplw   cr1,r3,r2                                       ; Same address space as before?
+                       stw             r7,ppUserPmap(r6)                       ; Show our real pmap address
+                       crorc   cr1_eq,cr1_eq,pfAltivecb        ; See if same address space or not altivec machine
+                       stw             r4,ppUserPmap+4(r6)                     ; Show our real pmap address
+                       stw             r3,ppUserPmapVirt(r6)           ; Show our virtual pmap address
+                       beqlr-- cr1                                                     ; Leave if the same
+
+                       dssall                                                          ; Need to kill all data streams if adrsp changed
+                       sync
+                       blr                                                                     ; Return...
+       
+/*                     int mapalc1(struct mappingblok *mb) - Finds, allocates, and zeros a free 1-bit mapping entry
+ *
+ *                     Lock must already be held on mapping block list
  *                     returns 0 if all slots filled.
  *                     returns n if a slot is found and it is not the last
- *                     returns -n if a slot os found and it is the last
+ *                     returns -n if a slot is found and it is the last
  *                     when n and -n are returned, the corresponding bit is cleared
+ *                     the mapping is zeroed out before return
+ *
+ */
+
+                       .align  5
+                       .globl  EXT(mapalc1)
+
+LEXT(mapalc1)
+                       lwz             r4,mbfree(r3)                           ; Get the 1st mask 
+                       lis             r0,0x8000                                       ; Get the mask to clear the first free bit
+                       lwz             r5,mbfree+4(r3)                         ; Get the 2nd mask 
+                       mr              r12,r3                                          ; Save the block ptr
+                       cntlzw  r3,r4                                           ; Get first 1-bit in 1st word
+                       srw.    r9,r0,r3                                        ; Get bit corresponding to first free one
+                       cntlzw  r10,r5                                          ; Get first free field in second word
+                       andc    r4,r4,r9                                        ; Turn 1-bit off in 1st word
+                       bne             mapalc1f                                        ; Found one in 1st word
+                       
+                       srw.    r9,r0,r10                                       ; Get bit corresponding to first free one in 2nd word
+            li         r3,0                                            ; assume failure return
+                       andc    r5,r5,r9                                        ; Turn it off
+                       beqlr--                                                         ; There are no 1 bits left...
+            addi       r3,r10,32                                       ; set the correct number
+            
+mapalc1f:
+            or.                r0,r4,r5                                        ; any more bits set?
+            stw                r4,mbfree(r12)                          ; update bitmasks
+            stw                r5,mbfree+4(r12)
+            
+            slwi       r6,r3,6                                         ; get (n * mpBasicSize), ie offset of mapping in block
+            addi       r7,r6,32
+            dcbz       r6,r12                                          ; clear the 64-byte mapping
+            dcbz       r7,r12
+            
+            bnelr++                                                            ; return if another bit remains set
+            
+            neg                r3,r3                                           ; indicate we just returned the last bit
+            blr
+
+
+/*                     int mapalc2(struct mappingblok *mb) - Finds, allocates, and zero's a free 2-bit mapping entry
  *
+ *                     Lock must already be held on mapping block list
+ *                     returns 0 if all slots filled.
+ *                     returns n if a slot is found and it is not the last
+ *                     returns -n if a slot is found and it is the last
+ *                     when n and -n are returned, the corresponding bits are cleared
+ *                     We find runs of 2 consecutive 1 bits by cntlzw(n & (n<<1)).
+ *                     the mapping is zero'd out before return
  */
 
                        .align  5
-                       .globl  EXT(mapalc)
+                       .globl  EXT(mapalc2)
+LEXT(mapalc2)
+                       lwz             r4,mbfree(r3)                           ; Get the first mask 
+                       lis             r0,0x8000                                       ; Get the mask to clear the first free bit
+                       lwz             r5,mbfree+4(r3)                         ; Get the second mask 
+                       mr              r12,r3                                          ; Save the block ptr
+            slwi       r6,r4,1                                         ; shift first word over
+            and                r6,r4,r6                                        ; lite start of double bit runs in 1st word
+            slwi       r7,r5,1                                         ; shift 2nd word over
+                       cntlzw  r3,r6                                           ; Get first free 2-bit run in 1st word
+            and                r7,r5,r7                                        ; lite start of double bit runs in 2nd word
+                       srw.    r9,r0,r3                                        ; Get bit corresponding to first run in 1st word
+                       cntlzw  r10,r7                                          ; Get first free field in second word
+            srwi       r11,r9,1                                        ; shift over for 2nd bit in 1st word
+                       andc    r4,r4,r9                                        ; Turn off 1st bit in 1st word
+            andc       r4,r4,r11                                       ; turn off 2nd bit in 1st word
+                       bne             mapalc2a                                        ; Found two consecutive free bits in 1st word
+                       
+                       srw.    r9,r0,r10                                       ; Get bit corresponding to first free one in second word
+            li         r3,0                                            ; assume failure
+            srwi       r11,r9,1                                        ; get mask for 2nd bit
+                       andc    r5,r5,r9                                        ; Turn off 1st bit in 2nd word
+            andc       r5,r5,r11                                       ; turn off 2nd bit in 2nd word
+                       beq--   mapalc2c                                        ; There are no runs of 2 bits in 2nd word either
+            addi       r3,r10,32                                       ; set the correct number
+            
+mapalc2a:
+            or.                r0,r4,r5                                        ; any more bits set?
+            stw                r4,mbfree(r12)                          ; update bitmasks
+            stw                r5,mbfree+4(r12)
+            slwi       r6,r3,6                                         ; get (n * mpBasicSize), ie offset of mapping in block
+            addi       r7,r6,32
+            addi       r8,r6,64
+            addi       r9,r6,96
+            dcbz       r6,r12                                          ; zero out the 128-byte mapping
+            dcbz       r7,r12                                          ; we use the slow 32-byte dcbz even on 64-bit machines
+            dcbz       r8,r12                                          ; because the mapping may not be 128-byte aligned
+            dcbz       r9,r12
+            
+            bnelr++                                                            ; return if another bit remains set
+            
+            neg                r3,r3                                           ; indicate we just returned the last bit
+            blr
+            
+mapalc2c:
+            rlwinm     r7,r5,1,31,31                           ; move bit 0 of 2nd word to bit 31
+            and.       r0,r4,r7                                        ; is the 2-bit field that spans the 2 words free?
+            beqlr                                                              ; no, we failed
+            rlwinm     r4,r4,0,0,30                            ; yes, turn off bit 31 of 1st word
+            rlwinm     r5,r5,0,1,31                            ; turn off bit 0 of 2nd word
+            li         r3,31                                           ; get index of this field
+            b          mapalc2a
+                       
+
+;
+;                      This routine initialzes the hash table and PCA.
+;                      It is done here because we may need to be 64-bit to do it.
+;
+
+                       .align  5
+                       .globl  EXT(hw_hash_init)
+
+LEXT(hw_hash_init)
+
+                       mfsprg  r10,2                                           ; Get feature flags 
+                       lis             r12,hi16(EXT(hash_table_size))          ; Get hash table size address
+                       mtcrf   0x02,r10                                        ; move pf64Bit to cr6
+                       lis             r11,hi16(EXT(hash_table_base))          ; Get hash table base address
+                       lis             r4,0xFF01                                       ; Set all slots free and start steal at end
+                       ori             r12,r12,lo16(EXT(hash_table_size))      ; Get hash table size address
+                       ori             r11,r11,lo16(EXT(hash_table_base))      ; Get hash table base address
+
+                       lwz             r12,0(r12)                                      ; Get hash table size
+                       li              r3,0                                            ; Get start
+                       bt++    pf64Bitb,hhiSF                          ; skip if 64-bit (only they take the hint)
+
+                       lwz             r11,4(r11)                                      ; Get hash table base
+                       
+hhiNext32:     cmplw   r3,r12                                          ; Have we reached the end?
+                       bge-    hhiCPCA32                                       ; Yes...                        
+                       dcbz    r3,r11                                          ; Clear the line
+                       addi    r3,r3,32                                        ; Next one...
+                       b               hhiNext32                                       ; Go on...
+
+hhiCPCA32:     rlwinm  r12,r12,28,4,29                         ; Get number of slots * 4
+                       li              r3,-4                                           ; Displacement to first PCA entry
+                       neg             r12,r12                                         ; Get negative end of PCA       
+                       
+hhiNPCA32:     stwx    r4,r3,r11                                       ; Initialize the PCA entry
+                       subi    r3,r3,4                                         ; Next slot
+                       cmpw    r3,r12                                          ; Have we finished?
+                       bge+    hhiNPCA32                                       ; Not yet...
+                       blr                                                                     ; Leave...
+
+hhiSF:         mfmsr   r9                                                      ; Save the MSR
+                       li              r8,1                                            ; Get a 1
+                       mr              r0,r9                                           ; Get a copy of the MSR
+                       ld              r11,0(r11)                                      ; Get hash table base
+                       rldimi  r0,r8,63,MSR_SF_BIT                     ; Set SF bit (bit 0)
+                       mtmsrd  r0                                                      ; Turn on SF
+                       isync
+                       
+                       
+hhiNext64:     cmpld   r3,r12                                          ; Have we reached the end?
+                       bge--   hhiCPCA64                                       ; Yes...                        
+                       dcbz128 r3,r11                                          ; Clear the line
+                       addi    r3,r3,128                                       ; Next one...
+                       b               hhiNext64                                       ; Go on...
+
+hhiCPCA64:     rlwinm  r12,r12,27,5,29                         ; Get number of slots * 4
+                       li              r3,-4                                           ; Displacement to first PCA entry
+                       neg             r12,r12                                         ; Get negative end of PCA       
+               
+hhiNPCA64:     stwx    r4,r3,r11                                       ; Initialize the PCA entry
+                       subi    r3,r3,4                                         ; Next slot
+                       cmpd    r3,r12                                          ; Have we finished?
+                       bge++   hhiNPCA64                                       ; Not yet...
+
+                       mtmsrd  r9                                                      ; Turn off SF if it was off
+                       isync
+                       blr                                                                     ; Leave...
+                       
+                       
+;
+;                      This routine sets up the hardware to start translation.
+;                      Note that we do NOT start translation.
+;
+
+                       .align  5
+                       .globl  EXT(hw_setup_trans)
+
+LEXT(hw_setup_trans)
+
+                       mfsprg  r11,0                                           ; Get the per_proc block
+                       mfsprg  r12,2                                           ; Get feature flags 
+                       li              r0,0                                            ; Get a 0
+                       li              r2,1                                            ; And a 1
+                       mtcrf   0x02,r12                                        ; Move pf64Bit to cr6
+                       stw             r0,validSegs(r11)                       ; Make sure we think all SR/STEs are invalid
+                       stw             r0,validSegs+4(r11)                     ; Make sure we think all SR/STEs are invalid, part deux
+                       sth             r2,ppInvSeg(r11)                        ; Force a reload of the SRs
+                       sth             r0,ppCurSeg(r11)                        ; Set that we are starting out in kernel
+                       
+                       bt++    pf64Bitb,hstSF                          ; skip if 64-bit (only they take the hint)
+
+                       li              r9,0                                            ; Clear out a register
+                       sync
+                       isync
+                       mtdbatu 0,r9                                            ; Invalidate maps
+                       mtdbatl 0,r9                                            ; Invalidate maps
+                       mtdbatu 1,r9                                            ; Invalidate maps
+                       mtdbatl 1,r9                                            ; Invalidate maps
+                       mtdbatu 2,r9                                            ; Invalidate maps
+                       mtdbatl 2,r9                                            ; Invalidate maps
+                       mtdbatu 3,r9                                            ; Invalidate maps
+                       mtdbatl 3,r9                                            ; Invalidate maps
+
+                       mtibatu 0,r9                                            ; Invalidate maps
+                       mtibatl 0,r9                                            ; Invalidate maps
+                       mtibatu 1,r9                                            ; Invalidate maps
+                       mtibatl 1,r9                                            ; Invalidate maps
+                       mtibatu 2,r9                                            ; Invalidate maps
+                       mtibatl 2,r9                                            ; Invalidate maps
+                       mtibatu 3,r9                                            ; Invalidate maps
+                       mtibatl 3,r9                                            ; Invalidate maps
+
+                       lis             r11,hi16(EXT(hash_table_base))          ; Get hash table base address
+                       lis             r12,hi16(EXT(hash_table_size))          ; Get hash table size address
+                       ori             r11,r11,lo16(EXT(hash_table_base))      ; Get hash table base address
+                       ori             r12,r12,lo16(EXT(hash_table_size))      ; Get hash table size address
+                       lwz             r11,4(r11)                                      ; Get hash table base
+                       lwz             r12,0(r12)                                      ; Get hash table size
+                       subi    r12,r12,1                                       ; Back off by 1
+                       rlwimi  r11,r12,16,23,31                        ; Stick the size into the sdr1 image
+                       
+                       mtsdr1  r11                                                     ; Ok, we now have the hash table set up
+                       sync
+                       
+                       li              r12,invalSpace                          ; Get the invalid segment value
+                       li              r10,0                                           ; Start low
+                       
+hstsetsr:      mtsrin  r12,r10                                         ; Set the SR
+                       addis   r10,r10,0x1000                          ; Bump the segment
+                       mr.             r10,r10                                         ; Are we finished?
+                       bne+    hstsetsr                                        ; Nope...       
+                       sync
+                       blr                                                                     ; Return...
+
+;
+;                      64-bit version
+;
+
+hstSF:         lis             r11,hi16(EXT(hash_table_base))          ; Get hash table base address
+                       lis             r12,hi16(EXT(hash_table_size))          ; Get hash table size address
+                       ori             r11,r11,lo16(EXT(hash_table_base))      ; Get hash table base address
+                       ori             r12,r12,lo16(EXT(hash_table_size))      ; Get hash table size address
+                       ld              r11,0(r11)                                      ; Get hash table base
+                       lwz             r12,0(r12)                                      ; Get hash table size
+                       cntlzw  r10,r12                                         ; Get the number of bits
+                       subfic  r10,r10,13                                      ; Get the extra bits we need
+                       or              r11,r11,r10                                     ; Add the size field to SDR1
+                       
+                       mtsdr1  r11                                                     ; Ok, we now have the hash table set up
+                       sync
+
+                       li              r0,0                                            ; Set an SLB slot index of 0
+                       slbia                                                           ; Trash all SLB entries (except for entry 0 that is)
+                       slbmfee r7,r0                                           ; Get the entry that is in SLB index 0
+                       rldicr  r7,r7,0,35                                      ; Clear the valid bit and the rest
+                       slbie   r7                                                      ; Invalidate it
+
+                       blr                                                                     ; Return...
+
+
+;
+;                      This routine turns on translation for the first time on a processor
+;
+
+                       .align  5
+                       .globl  EXT(hw_start_trans)
+
+LEXT(hw_start_trans)
+
+                       
+                       mfmsr   r10                                                     ; Get the msr
+                       ori             r10,r10,lo16(MASK(MSR_IR) | MASK(MSR_DR))       ; Turn on translation
+
+                       mtmsr   r10                                                     ; Everything falls apart here
+                       isync
+                       
+                       blr                                                                     ; Back to it.
+
+
+
+;
+;                      This routine validates a segment register.
+;                              hw_map_seg(pmap_t pmap, addr64_t seg, addr64_t va)
+;
+;                              r3 = virtual pmap
+;                              r4 = segment[0:31]
+;                              r5 = segment[32:63]
+;                              r6 = va[0:31]
+;                              r7 = va[32:63]
+;
+;                      Note that we transform the addr64_t (long long) parameters into single 64-bit values.
+;                      Note that there is no reason to apply the key modifier here because this is only
+;                      used for kernel accesses.
+;
+
+                       .align  5
+                       .globl  EXT(hw_map_seg)
+
+LEXT(hw_map_seg)
+
+                       lwz             r0,pmapSpace(r3)                        ; Get the space, we will need it soon
+                       lwz             r9,pmapFlags(r3)                        ; Get the flags for the keys now
+                       mfsprg  r10,2                                           ; Get feature flags 
+
+;
+;                      Note: the following code would problably be easier to follow if I split it,
+;                      but I just wanted to see if I could write this to work on both 32- and 64-bit
+;                      machines combined.
+;
+                       
+;
+;                      Here we enter with va[0:31] in r6[0:31] (or r6[32:63] on 64-bit machines)
+;                      and va[32:63] in r7[0:31] (or r7[32:63] on 64-bit machines)
+
+                       rlwinm  r4,r4,0,1,0                                     ; Copy seg[0:31] into r4[0;31] - no-op for 32-bit
+                       rlwinm  r7,r7,18,14,17                          ; Slide va[32:35] east to just west of space ID
+                       mtcrf   0x02,r10                                        ; Move pf64Bit and pfNoMSRirb to cr5 and 6
+                       srwi    r8,r6,14                                        ; Slide va[0:17] east to just west of the rest
+                       rlwimi  r7,r6,18,0,13                           ; Slide va[18:31] east to just west of slid va[32:25]
+                       rlwimi  r0,r0,14,4,17                           ; Dup address space ID above itself
+                       rlwinm  r8,r8,0,1,0                                     ; Dup low part into high (does nothing on 32-bit machines)
+                       rlwinm  r2,r0,28,0,31                           ; Rotate rotate low nybble to top of low half
+                       rlwimi  r2,r2,0,1,0                                     ; Replicate bottom 32 into top 32
+                       rlwimi  r8,r7,0,0,31                            ; Join va[0:17] with va[18:35] (just like mr on 32-bit machines)                        
+
+                       rlwimi  r2,r0,0,4,31                            ; We should now have 4 copies of the space
+                                                                                               ; concatenated together.   There is garbage
+                                                                                               ; at the top for 64-bit but we will clean
+                                                                                               ; that out later.
+                       rlwimi  r4,r5,0,0,31                            ; Copy seg[32:63] into r4[32:63] - just like mr for 32-bit
+
+                       
+;
+;                      Here we exit with va[0:35] shifted into r8[14:51], zeros elsewhere, or
+;                      va[18:35] shifted into r8[0:17], zeros elsewhere on 32-bit machines
+;                      
+                                                                                               
+;
+;                      What we have now is:
+;
+;                                       0        0        1        2        3        4        4        5      6
+;                                       0        8        6        4        2        0        8        6      3        - for 64-bit machines
+;                                      +--------+--------+--------+--------+--------+--------+--------+--------+
+;                      r2 =    |xxxx0000|AAAAAAAA|AAAAAABB|BBBBBBBB|BBBBCCCC|CCCCCCCC|CCDDDDDD|DDDDDDDD|       - hash value
+;                                      +--------+--------+--------+--------+--------+--------+--------+--------+
+;                                                                                                               0        0        1        2      3    - for 32-bit machines
+;                                                                                                               0        8        6        4      1
+;
+;                                       0        0        1        2        3        4        4        5      6
+;                                       0        8        6        4        2        0        8        6      3        - for 64-bit machines
+;                                      +--------+--------+--------+--------+--------+--------+--------+--------+
+;                      r8 =    |00000000|000000SS|SSSSSSSS|SSSSSSSS|SSSSSSSS|SSSSSSSS|SS000000|00000000|       - shifted and cleaned EA
+;                                      +--------+--------+--------+--------+--------+--------+--------+--------+
+;                                                                                                               0        0        1        2      3    - for 32-bit machines
+;                                                                                                               0        8        6        4      1
+;
+;                                       0        0        1        2        3        4        4        5      6
+;                                       0        8        6        4        2        0        8        6      3        - for 64-bit machines
+;                                      +--------+--------+--------+--------+--------+--------+--------+--------+
+;                      r4 =    |SSSSSSSS|SSSSSSSS|SSSSSSSS|SSSSSSSS|SSSS0000|00000000|00000000|00000000|       - Segment
+;                                      +--------+--------+--------+--------+--------+--------+--------+--------+
+;                                                                                                               0        0        1        2      3    - for 32-bit machines
+;                                                                                                               0        8        6        4      1
+
+
+                       xor             r8,r8,r2                                        ; Calculate VSID
+                       
+                       bf--    pf64Bitb,hms32bit                       ; Skip out if 32-bit...
+                       mfsprg  r12,0                                           ; Get the per_proc
+                       li              r0,1                                            ; Prepare to set bit 0 (also to clear EE)
+                       mfmsr   r6                                                      ; Get current MSR
+                       li              r2,MASK(MSR_IR)|MASK(MSR_DR)    ; Get the translation bits
+                       mtmsrd  r0,1                                            ; Set only the EE bit to 0
+                       rlwinm  r6,r6,0,MSR_EE_BIT,MSR_EE_BIT   ; See if EE bit is on
+                       mfmsr   r11                                                     ; Get the MSR right now, after disabling EE
+                       andc    r2,r11,r2                                       ; Turn off translation now
+                       rldimi  r2,r0,63,0                                      ; Get bit 64-bit turned on
+                       or              r11,r11,r6                                      ; Turn on the EE bit if it was on
+                       mtmsrd  r2                                                      ; Make sure translation and EE are off and 64-bit is on
+                       isync                                                           ; Hang out a bit
+                                               
+                       ld              r6,validSegs(r12)                       ; Get the valid SLB entry flags
+                       sldi    r9,r9,9                                         ; Position the key and noex bit
+                       
+                       rldimi  r5,r8,12,0                                      ; Form the VSID/key
+                       
+                       not             r3,r6                                           ; Make valids be 0s
+                       
+                       cntlzd  r7,r3                                           ; Find a free SLB       
+                       cmplwi  r7,63                                           ; Did we find a free SLB entry?         
+                       
+                       slbie   r4                                                      ; Since this ESID may still be in an SLBE, kill it
+
+                       oris    r4,r4,0x0800                            ; Turn on the valid bit in ESID
+                       addi    r7,r7,1                                         ; Make sure we skip slb 0
+                       blt++   hmsFreeSeg                                      ; Yes, go load it...
+
+;
+;                      No free SLB entries, select one that is in use and invalidate it
+;
+                       lwz             r2,ppSegSteal(r12)                      ; Get the next slot to steal
+                       addi    r7,r2,pmapSegCacheUse+1         ; Select stealee from non-cached slots only
+                       addi    r2,r2,1                                         ; Set next slot to steal
+                       slbmfee r3,r7                                           ; Get the entry that is in the selected spot
+                       subi    r8,r2,64-(pmapSegCacheUse+1)    ; Force steal to wrap
+                       rldicr  r3,r3,0,35                                      ; Clear the valid bit and the rest
+                       srawi   r8,r8,31                                        ; Get -1 if steal index still in range
+                       slbie   r3                                                      ; Invalidate the in-use SLB entry
+                       and             r2,r2,r8                                        ; Reset steal index when it should wrap
+                       isync                                                           ; 
+                       
+                       stw             r2,ppSegSteal(r12)                      ; Set the next slot to steal
+;
+;                      We are now ready to stick the SLB entry in the SLB and mark it in use
+;
+
+hmsFreeSeg:    subi    r2,r7,1                                         ; Adjust for skipped slb 0
+                       rldimi  r4,r7,0,58                                      ; Copy in the SLB entry selector
+                       srd             r0,r0,r2                                        ; Set bit mask for allocation
+                       rldicl  r5,r5,0,15                                      ; Clean out the unsupported bits
+                       or              r6,r6,r0                                        ; Turn on the allocation flag
+                       
+                       slbmte  r5,r4                                           ; Make that SLB entry
+
+                       std             r6,validSegs(r12)                       ; Mark as valid
+                       mtmsrd  r11                                                     ; Restore the MSR
+                       isync
+                       blr                                                                     ; Back to it...
+
+                       .align  5
+
+hms32bit:
+                       mfsprg  r12,1                                           ; Get the current activation
+                       lwz             r12,ACT_PER_PROC(r12)           ; Get the per_proc block
+                       rlwinm  r8,r8,0,8,31                            ; Clean up the VSID
+                       rlwinm  r2,r4,4,28,31                           ; Isolate the segment we are setting
+                       lis             r0,0x8000                                       ; Set bit 0
+                       rlwimi  r8,r9,28,1,3                            ; Insert the keys and N bit                     
+                       srw             r0,r0,r2                                        ; Get bit corresponding to SR
+                       addi    r7,r12,validSegs                        ; Point to the valid segment flags directly
+               
+                       mtsrin  r8,r4                                           ; Set the actual SR     
+                       isync                                                           ; Need to make sure this is done
+               
+hmsrupt:       lwarx   r6,0,r7                                         ; Get and reserve the valid segment flags
+                       or              r6,r6,r0                                        ; Show that SR is valid
+                       stwcx.  r6,0,r7                                         ; Set the valid SR flags
+                       bne--   hmsrupt                                         ; Had an interrupt, need to get flags again...
+
+                       blr                                                                     ; Back to it...
+
+
+;
+;                      This routine invalidates a segment register.
+;
+
+                       .align  5
+                       .globl  EXT(hw_blow_seg)
+
+LEXT(hw_blow_seg)
+
+                       mfsprg  r10,2                                           ; Get feature flags 
+                       mtcrf   0x02,r10                                        ; move pf64Bit and pfNoMSRirb to cr5 and 6
+               
+                       rlwinm  r9,r4,0,0,3                                     ; Save low segment address and make sure it is clean
+                       
+                       bf--    pf64Bitb,hbs32bit                       ; Skip out if 32-bit...
+                       
+                       li              r0,1                                            ; Prepare to set bit 0 (also to clear EE)
+                       mfmsr   r6                                                      ; Get current MSR
+                       li              r2,MASK(MSR_IR)|MASK(MSR_DR)    ; Get the translation bits
+                       mtmsrd  r0,1                                            ; Set only the EE bit to 0
+                       rlwinm  r6,r6,0,MSR_EE_BIT,MSR_EE_BIT   ; See if EE bit is on
+                       mfmsr   r11                                                     ; Get the MSR right now, after disabling EE
+                       andc    r2,r11,r2                                       ; Turn off translation now
+                       rldimi  r2,r0,63,0                                      ; Get bit 64-bit turned on
+                       or              r11,r11,r6                                      ; Turn on the EE bit if it was on
+                       mtmsrd  r2                                                      ; Make sure translation and EE are off and 64-bit is on
+                       isync                                                           ; Hang out a bit
+
+                       rldimi  r9,r3,32,0                                      ; Insert the top part of the ESID
+                       
+                       slbie   r9                                                      ; Invalidate the associated SLB entry
+                       
+                       mtmsrd  r11                                                     ; Restore the MSR
+                       isync
+                       blr                                                                     ; Back to it.
+
+                       .align  5
+
+hbs32bit:
+                       mfsprg  r12,1                                           ; Get the current activation
+                       lwz             r12,ACT_PER_PROC(r12)           ; Get the per_proc block
+                       addi    r7,r12,validSegs                        ; Point to the valid segment flags directly
+                       lwarx   r4,0,r7                                         ; Get and reserve the valid segment flags
+                       rlwinm  r6,r9,4,28,31                           ; Convert segment to number
+                       lis             r2,0x8000                                       ; Set up a mask
+                       srw             r2,r2,r6                                        ; Make a mask
+                       and.    r0,r4,r2                                        ; See if this is even valid
+                       li              r5,invalSpace                           ; Set the invalid address space VSID
+                       beqlr                                                           ; Leave if already invalid...
+                       
+                       mtsrin  r5,r9                                           ; Slam the segment register
+                       isync                                                           ; Need to make sure this is done
+               
+hbsrupt:       andc    r4,r4,r2                                        ; Clear the valid bit for this segment
+                       stwcx.  r4,0,r7                                         ; Set the valid SR flags
+                       beqlr++                                                         ; Stored ok, no interrupt, time to leave...
+                       
+                       lwarx   r4,0,r7                                         ; Get and reserve the valid segment flags again
+                       b               hbsrupt                                         ; Try again...
+
+;
+;                      This routine invadates the entire pmap segment cache
+;
+;                      Translation is on, interrupts may or may not be enabled.
+;
+
+                       .align  5
+                       .globl  EXT(invalidateSegs)
+
+LEXT(invalidateSegs)
+
+                       la              r10,pmapCCtl(r3)                        ; Point to the segment cache control
+                       eqv             r2,r2,r2                                        ; Get all foxes
+                       
+isInv:         lwarx   r4,0,r10                                        ; Get the segment cache control value
+                       rlwimi  r4,r2,0,0,15                            ; Slam in all invalid bits
+                       rlwinm. r0,r4,0,pmapCCtlLckb,pmapCCtlLckb       ; Is it already locked?
+                       bne--   isInv0                                          ; Yes, try again...
+                       
+                       stwcx.  r4,0,r10                                        ; Try to invalidate it
+                       bne--   isInv                                           ; Someone else just stuffed it...
+                       blr                                                                     ; Leave...
+                       
+
+isInv0:                li              r4,lgKillResv                           ; Get reservation kill zone
+                       stwcx.  r4,0,r4                                         ; Kill reservation
+
+isInv1:                lwz             r4,pmapCCtl(r3)                         ; Get the segment cache control
+                       rlwinm. r0,r4,0,pmapCCtlLckb,pmapCCtlLckb       ; Is it already locked?
+                       bne--   isInv                                           ; Nope...
+                       b               isInv1                                          ; Still locked do it again...
+                       
+;
+;                      This routine switches segment registers between kernel and user.
+;                      We have some assumptions and rules:
+;                              We are in the exception vectors
+;                              pf64Bitb is set up
+;                              R3 contains the MSR we going to
+;                              We can not use R4, R13, R20, R21, R25, R26, R29
+;                              R13 is the savearea
+;                              R29 has the per_proc
+;
+;                      We return R3 as 0 if we did not switch between kernel and user
+;                      We also maintain and apply the user state key modifier used by VMM support;     
+;                      If we go to the kernel it is set to 0, otherwise it follows the bit 
+;                      in spcFlags.
+;
+
+                       .align  5
+                       .globl  EXT(switchSegs)
+
+LEXT(switchSegs)
+
+                       lwz             r22,ppInvSeg(r29)                       ; Get the ppInvSeg (force invalidate) and ppCurSeg (user or kernel segments indicator)
+                       lwz             r9,spcFlags(r29)                        ; Pick up the special user state flags
+                       rlwinm  r2,r3,MSR_PR_BIT+1,31,31        ; Isolate the problem mode bit
+                       rlwinm  r3,r3,MSR_RI_BIT+1,31,31        ; Isolate the recoverable interrupt bit
+                       lis             r8,hi16(EXT(kernel_pmap_phys))  ; Assume kernel
+                       or              r2,r2,r3                                        ; This will 1 if we will be using user segments
+                       li              r3,0                                            ; Get a selection mask
+                       cmplw   r2,r22                                          ; This will be EQ if same state and not ppInvSeg
+                       ori             r8,r8,lo16(EXT(kernel_pmap_phys))       ; Assume kernel (bottom of address)
+                       sub             r3,r3,r2                                        ; Form select mask - 0 if kernel, -1 if user
+                       la              r19,ppUserPmap(r29)                     ; Point to the current user pmap
+
+;                      The following line is an exercise of a generally unreadable but recompile-friendly programing practice
+                       rlwinm  r30,r9,userProtKeybit+1+(63-sgcVSKeyUsr),sgcVSKeyUsr-32,sgcVSKeyUsr-32  ; Isolate the user state protection key 
+
+                       andc    r8,r8,r3                                        ; Zero kernel pmap ptr if user, untouched otherwise
+                       and             r19,r19,r3                                      ; Zero user pmap ptr if kernel, untouched otherwise
+                       and             r30,r30,r3                                      ; Clear key modifier if kernel, leave otherwise
+                       or              r8,r8,r19                                       ; Get the pointer to the pmap we are using
+
+                       beqlr                                                           ; We are staying in the same mode, do not touch segs...
+
+                       lwz             r28,0(r8)                                       ; Get top half of pmap address
+                       lwz             r10,4(r8)                                       ; Get bottom half
+
+                       stw             r2,ppInvSeg(r29)                        ; Clear request for invalidate and save ppCurSeg
+                       rlwinm  r28,r28,0,1,0                           ; Copy top to top
+                       stw             r30,ppMapFlags(r29)                     ; Set the key modifier
+                       rlwimi  r28,r10,0,0,31                          ; Insert bottom
+                       
+                       la              r10,pmapCCtl(r28)                       ; Point to the segment cache control
+                       la              r9,pmapSegCache(r28)            ; Point to the segment cache
+
+ssgLock:       lwarx   r15,0,r10                                       ; Get and reserve the segment cache control
+                       rlwinm. r0,r15,0,pmapCCtlLckb,pmapCCtlLckb      ; Someone have the lock?
+                       ori             r16,r15,lo16(pmapCCtlLck)       ; Set lock bit
+                       bne--   ssgLock0                                        ; Yup, this is in use...
+
+                       stwcx.  r16,0,r10                                       ; Try to set the lock
+                       bne--   ssgLock                                         ; Did we get contention?
+                       
+                       not             r11,r15                                         ; Invert the invalids to valids
+                       li              r17,0                                           ; Set a mask for the SRs we are loading
+                       isync                                                           ; Make sure we are all caught up
+
+                       bf--    pf64Bitb,ssg32Enter                     ; If 32-bit, jump into it...
+               
+                       li              r0,0                                            ; Clear
+                       slbia                                                           ; Trash all SLB entries (except for entry 0 that is)
+                       li              r17,1                                           ; Get SLB index to load (skip slb 0)
+                       oris    r0,r0,0x8000                            ; Get set for a mask
+                       b               ssg64Enter                                      ; Start on a cache line...
+
+                       .align  5
+
+ssgLock0:      li              r15,lgKillResv                          ; Killing field
+                       stwcx.  r15,0,r15                                       ; Kill reservation
+
+ssgLock1:      lwz             r15,pmapCCtl(r28)                       ; Get the segment cache controls
+                       rlwinm. r15,r15,0,pmapCCtlLckb,pmapCCtlLckb     ; Someone have the lock?
+                       beq++   ssgLock                                         ; Yup, this is in use...
+                       b               ssgLock1                                        ; Nope, try again...
+;
+;                      This is the 32-bit address space switch code.
+;                      We take a reservation on the segment cache and walk through.
+;                      For each entry, we load the specified entries and remember which
+;                      we did with a mask.  Then, we figure out which segments should be
+;                      invalid and then see which actually are.  Then we load those with the
+;                      defined invalid VSID. 
+;                      Afterwards, we unlock the segment cache.
+;
+
+                       .align  5
+
+ssg32Enter:    cntlzw  r12,r11                                         ; Find the next slot in use
+                       cmplwi  r12,pmapSegCacheUse                     ; See if we are done
+                       slwi    r14,r12,4                                       ; Index to the cache slot
+                       lis             r0,0x8000                                       ; Get set for a mask
+                       add             r14,r14,r9                                      ; Point to the entry
+               
+                       bge-    ssg32Done                                       ; All done...
+               
+                       lwz             r5,sgcESID+4(r14)                       ; Get the ESID part
+                       srw             r2,r0,r12                                       ; Form a mask for the one we are loading
+                       lwz             r7,sgcVSID+4(r14)                       ; And get the VSID bottom
+
+                       andc    r11,r11,r2                                      ; Clear the bit
+                       lwz             r6,sgcVSID(r14)                         ; And get the VSID top
+
+                       rlwinm  r2,r5,4,28,31                           ; Change the segment number to a number
+
+                       xor             r7,r7,r30                                       ; Modify the key before we actually set it
+                       srw             r0,r0,r2                                        ; Get a mask for the SR we are loading
+                       rlwinm  r8,r7,19,1,3                            ; Insert the keys and N bit                     
+                       or              r17,r17,r0                                      ; Remember the segment
+                       rlwimi  r8,r7,20,12,31                          ; Insert 4:23 the VSID
+                       rlwimi  r8,r6,20,8,11                           ; Get the last nybble of the SR contents                        
+
+                       mtsrin  r8,r5                                           ; Load the segment
+                       b               ssg32Enter                                      ; Go enter the next...
+                       
+                       .align  5
+                       
+ssg32Done:     lwz             r16,validSegs(r29)                      ; Get the valid SRs flags
+                       stw             r15,pmapCCtl(r28)                       ; Unlock the segment cache controls
+
+                       lis             r0,0x8000                                       ; Get set for a mask
+                       li              r2,invalSpace                           ; Set the invalid address space VSID
+
+                       nop                                                                     ; Align loop
+                       nop                                                                     ; Align loop
+                       andc    r16,r16,r17                                     ; Get list of SRs that were valid before but not now
+                       nop                                                                     ; Align loop
+
+ssg32Inval:    cntlzw  r18,r16                                         ; Get the first one to invalidate
+                       cmplwi  r18,16                                          ; Have we finished?
+                       srw             r22,r0,r18                                      ; Get the mask bit
+                       rlwinm  r23,r18,28,0,3                          ; Get the segment register we need
+                       andc    r16,r16,r22                                     ; Get rid of the guy we just did
+                       bge             ssg32Really                                     ; Yes, we are really done now...
+
+                       mtsrin  r2,r23                                          ; Invalidate the SR
+                       b               ssg32Inval                                      ; Do the next...
+                       
+                       .align  5
+
+ssg32Really:
+                       stw             r17,validSegs(r29)                      ; Set the valid SR flags
+                       li              r3,1                                            ; Set kernel/user transition
+                       blr
+
+;
+;                      This is the 64-bit address space switch code.
+;                      First we blow away all of the SLB entries.
+;                      Walk through,
+;                      loading the SLB.  Afterwards, we release the cache lock
+;
+;                      Note that because we have to treat SLBE 0 specially, we do not ever use it...
+;                      Its a performance thing...
+;
+
+                       .align  5
+
+ssg64Enter:    cntlzw  r12,r11                                         ; Find the next slot in use
+                       cmplwi  r12,pmapSegCacheUse                     ; See if we are done
+                       slwi    r14,r12,4                                       ; Index to the cache slot
+                       srw             r16,r0,r12                                      ; Form a mask for the one we are loading
+                       add             r14,r14,r9                                      ; Point to the entry
+                       andc    r11,r11,r16                                     ; Clear the bit
+                       bge--   ssg64Done                                       ; All done...
+
+                       ld              r5,sgcESID(r14)                         ; Get the ESID part
+                       ld              r6,sgcVSID(r14)                         ; And get the VSID part
+                       oris    r5,r5,0x0800                            ; Turn on the valid bit
+                       or              r5,r5,r17                                       ; Insert the SLB slot
+                       xor             r6,r6,r30                                       ; Modify the key before we actually set it
+                       addi    r17,r17,1                                       ; Bump to the next slot
+                       slbmte  r6,r5                                           ; Make that SLB entry
+                       b               ssg64Enter                                      ; Go enter the next...
+                       
+                       .align  5
+                       
+ssg64Done:     stw             r15,pmapCCtl(r28)                       ; Unlock the segment cache controls
+
+                       eqv             r16,r16,r16                                     ; Load up with all foxes
+                       subfic  r17,r17,64                                      ; Get the number of 1 bits we need
+
+                       sld             r16,r16,r17                                     ; Get a mask for the used SLB entries
+                       li              r3,1                                            ; Set kernel/user transition
+                       std             r16,validSegs(r29)                      ; Set the valid SR flags
+                       blr
+
+;
+;                      mapSetUp - this function sets initial state for all mapping functions.
+;                      We turn off all translations (physical), disable interruptions, and 
+;                      enter 64-bit mode if applicable.
+;
+;                      We also return the original MSR in r11, the feature flags in R12,
+;                      and CR6 set up so we can do easy branches for 64-bit
+;                      hw_clear_maps assumes r10, r9 will not be trashed.
+;
+
+                       .align  5
+                       .globl  EXT(mapSetUp)
+
+LEXT(mapSetUp)
+
+                       lis             r0,hi16(MASK(MSR_VEC))          ; Get the vector mask
+                       mfsprg  r12,2                                           ; Get feature flags 
+                       ori             r0,r0,lo16(MASK(MSR_FP))        ; Get the FP as well
+                       mtcrf   0x04,r12                                        ; move pf64Bit and pfNoMSRirb to cr5 and 6
+                       mfmsr   r11                                                     ; Save the MSR 
+                       mtcrf   0x02,r12                                        ; move pf64Bit and pfNoMSRirb to cr5 and 6
+                       andc    r11,r11,r0                                      ; Clear VEC and FP for good
+                       ori             r0,r0,lo16(MASK(MSR_EE)|MASK(MSR_DR)|MASK(MSR_IR))      ; Get rid of EE, IR, and DR
+                       li              r2,1                                            ; Prepare for 64 bit
+                       andc    r0,r11,r0                                       ; Clear the rest
+                       bt              pfNoMSRirb,msuNoMSR                     ; No MSR...
+                       bt++    pf64Bitb,msuSF                          ; skip if 64-bit (only they take the hint)
+
+                       mtmsr   r0                                                      ; Translation and all off
+                       isync                                                           ; Toss prefetch
+                       blr                                                                     ; Return...
+
+                       .align  5
+
+msuSF:         rldimi  r0,r2,63,MSR_SF_BIT                     ; set SF bit (bit 0)
+                       mtmsrd  r0                                                      ; set 64-bit mode, turn off EE, DR, and IR
+                       isync                                                           ; synchronize
+                       blr                                                                     ; Return...
+
+                       .align  5
+
+msuNoMSR:      mr              r2,r3                                           ; Save R3 across call
+                       mr              r3,r0                                           ; Get the new MSR value
+                       li              r0,loadMSR                                      ; Get the MSR setter SC
+                       sc                                                                      ; Set it
+                       mr              r3,r2                                           ; Restore R3
+                       blr                                                                     ; Go back all set up...
+                       
+
+;
+;                      Guest shadow assist -- remove all guest mappings
+;
+;                      Remove all mappings for a guest pmap from the shadow hash table.
+;
+;                      Parameters:
+;                              r3 : address of pmap, 32-bit kernel virtual address
+;
+;                      Non-volatile register usage:
+;                              r24 : host pmap's physical address
+;                              r25 : VMM extension block's physical address
+;                              r26 : physent address
+;                              r27 : guest pmap's space ID number
+;                              r28 : current hash table page index
+;                              r29 : guest pmap's physical address
+;                              r30 : saved msr image
+;                              r31 : current mapping
+;
+                       .align  5
+                       .globl  EXT(hw_rem_all_gv)
+                       
+LEXT(hw_rem_all_gv)
+
+#define graStackSize ((31-24+1)*4)+4
+                       stwu    r1,-(FM_ALIGN(graStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(graStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+                       stw             r24,FM_ARG0+0x1C(r1)            ; Save non-volatile r24
+                                                                                               
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+
+                       bt++    pf64Bitb,gra64Salt                      ; Test for 64-bit machine
+                       lwz             r25,pmapVmmExtPhys+4(r3)        ; r25 <- VMM pmap extension block paddr
+                       lwz             r9,pmapvr+4(r3)                         ; Get 32-bit virt<->real conversion salt
+                       lwz             r24,vmxHostPmapPhys+4(r11)      ; r24 <- host pmap's paddr
+                       b               graStart                                        ; Get to it                     
+gra64Salt:     ld              r25,pmapVmmExtPhys(r3)          ; r25 <- VMM pmap extension block paddr
+                       ld              r9,pmapvr(r3)                           ; Get 64-bit virt<->real conversion salt
+                       ld              r24,vmxHostPmapPhys(r11)        ; r24 <- host pmap's paddr
+graStart:      bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, enter 64-bit mode
+                       xor             r29,r3,r9                                       ; Convert pmap_t virt->real
+                       mr              r30,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r24)                        ; r3 <- host pmap's search lock
+                       bl              sxlkExclusive                           ; Get lock exclusive
+                       
+                       lwz             r3,vxsGra(r25)                          ; Get remove all count
+                       addi    r3,r3,1                                         ; Increment remove all count
+                       stw             r3,vxsGra(r25)                          ; Update remove all count
+
+                       li              r28,0                                           ; r28 <- first hash page table index to search
+                       lwz             r27,pmapSpace(r29)                      ; r27 <- guest pmap's space ID number
+graPgLoop:     
+                       la              r31,VMX_HPIDX_OFFSET(r25)       ; Get base of hash page physical index
+                       rlwinm  r11,r28,GV_PGIDX_SZ_LG2,GV_HPAGE_MASK
+                                                                                               ; Convert page index into page physical index offset
+                       add             r31,r31,r11                                     ; Calculate page physical index entry address
+                       bt++    pf64Bitb,gra64Page                      ; Separate handling for 64-bit
+                       lwz             r31,4(r31)                                      ; r31 <- first slot in hash table page to examine
+                       b               graLoop                                         ; Examine all slots in this page
+gra64Page:     ld              r31,0(r31)                                      ; r31 <- first slot in hash table page to examine
+                       b               graLoop                                         ; Examine all slots in this page
+
+                       .align  5
+graLoop:       lwz             r3,mpFlags(r31)                         ; Get mapping's flags
+                       lhz             r4,mpSpace(r31)                         ; Get mapping's space ID number
+                       rlwinm  r6,r3,0,mpgFree                         ; Isolate guest free mapping flag
+                       xor             r4,r4,r27                                       ; Compare space ID number
+                       or.             r0,r6,r4                                        ; cr0_eq <- !free && space id match
+                       bne             graMiss                                         ; Not one of ours, skip it
+                       
+                       lwz             r11,vxsGraHits(r25)                     ; Get remove hit count
+                       addi    r11,r11,1                                       ; Increment remove hit count
+                       stw             r11,vxsGraHits(r25)                     ; Update remove hit count
+
+                       rlwinm. r0,r3,0,mpgDormant                      ; Is this entry dormant?
+                       bne             graRemPhys                                      ; Yes, nothing to disconnect
+                       
+                       lwz             r11,vxsGraActive(r25)           ; Get remove active count
+                       addi    r11,r11,1                                       ; Increment remove hit count
+                       stw             r11,vxsGraActive(r25)           ; Update remove hit count
+
+                       bt++    pf64Bitb,graDscon64                     ; Handle 64-bit disconnect separately
+                       bl              mapInvPte32                                     ; Disconnect PTE, invalidate, gather ref and change
+                                                                                               ; r31 <- mapping's physical address
+                                                                                               ; r3  -> PTE slot physical address
+                                                                                               ; r4  -> High-order 32 bits of PTE
+                                                                                               ; r5  -> Low-order  32 bits of PTE
+                                                                                               ; r6  -> PCA
+                                                                                               ; r7  -> PCA physical address
+                       rlwinm  r2,r3,29,29,31                          ; Get PTE's slot number in the PTEG (8-byte PTEs)
+                       b               graFreePTE                                      ; Join 64-bit path to release the PTE                   
+graDscon64:    bl              mapInvPte64                                     ; Disconnect PTE, invalidate, gather ref and change
+                       rlwinm  r2,r3,28,29,31                          ; Get PTE's slot number in the PTEG (16-byte PTEs)
+graFreePTE: mr.                r3,r3                                           ; Was there a valid PTE?
+                       beq-    graRemPhys                                      ; No valid PTE, we're almost done
+                       lis             r0,0x8000                                       ; Prepare free bit for this slot
+                       srw             r0,r0,r2                                        ; Position free bit
+                       or              r6,r6,r0                                        ; Set it in our PCA image
+                       lwz             r8,mpPte(r31)                           ; Get PTE pointer
+                       rlwinm  r8,r8,0,~mpHValid                       ; Make the pointer invalid
+                       stw             r8,mpPte(r31)                           ; Save invalidated PTE pointer
+                       eieio                                                           ; Synchronize all previous updates (mapInvPtexx doesn't)
+                       stw             r6,0(r7)                                        ; Update PCA and unlock the PTEG
+                       
+graRemPhys:
+                       lwz             r3,mpPAddr(r31)                         ; r3 <- physical 4K-page number
+                       bl              mapFindLockPN                           ; Find 'n' lock this page's physent
+                       mr.             r26,r3                                          ; Got lock on our physent?
+                       beq--   graBadPLock                                     ; No, time to bail out
+
+                       crset   cr1_eq                                          ; cr1_eq <- previous link is the anchor
+                       bt++    pf64Bitb,graRemove64            ; Use 64-bit version on 64-bit machine
+                       la              r11,ppLink+4(r26)                       ; Point to chain anchor
+                       lwz             r9,ppLink+4(r26)                        ; Get chain anchor
+                       rlwinm. r9,r9,0,~ppFlags                        ; Remove flags, yielding 32-bit physical chain pointer
+
+graRemLoop:    beq-    graRemoveMiss                           ; End of chain, this is not good
+                       cmplw   r9,r31                                          ; Is this the mapping to remove?
+                       lwz             r8,mpAlias+4(r9)                        ; Get forward chain pointer
+                       bne             graRemNext                                      ; No, chain onward
+                       bt              cr1_eq,graRemRetry                      ; Mapping to remove is chained from anchor
+                       stw             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               graRemoved                                      ; Exit loop
+graRemRetry:
+                       lwarx   r0,0,r11                                        ; Get previous link
+                       rlwimi  r0,r8,0,~ppFlags                        ; Insert new forward pointer whilst preserving flags
+                       stwcx.  r0,0,r11                                        ; Update previous link
+                       bne-    graRemRetry                                     ; Lost reservation, retry
+                       b               graRemoved                                      ; Good work, let's get outta here
+                       
+graRemNext:    la              r11,mpAlias+4(r9)                       ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               graRemLoop                                      ; Carry on
+
+graRemove64:
+                       li              r7,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r7,r7,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       la              r11,ppLink(r26)                         ; Point to chain anchor
+                       ld              r9,ppLink(r26)                          ; Get chain anchor
+                       andc.   r9,r9,r7                                        ; Remove flags, yielding 64-bit physical chain pointer
+graRem64Lp:    beq--   graRemoveMiss                           ; End of chain, this is not good
+                       cmpld   r9,r31                                          ; Is this the mapping to remove?
+                       ld              r8,mpAlias(r9)                          ; Get forward chain pinter
+                       bne             graRem64Nxt                                     ; Not mapping to remove, chain on, dude
+                       bt              cr1_eq,graRem64Rt                       ; Mapping to remove is chained from anchor
+                       std             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               graRemoved                                      ; Exit loop
+graRem64Rt:    ldarx   r0,0,r11                                        ; Get previous link
+                       and             r0,r0,r7                                        ; Get flags
+                       or              r0,r0,r8                                        ; Insert new forward pointer
+                       stdcx.  r0,0,r11                                        ; Slam it back in
+                       bne--   graRem64Rt                                      ; Lost reservation, retry
+                       b               graRemoved                                      ; Good work, let's go home
+               
+graRem64Nxt:
+                       la              r11,mpAlias(r9)                         ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               graRem64Lp                                      ; Carry on
+
+graRemoved:
+                       mr              r3,r26                                          ; r3 <- physent's address
+                       bl              mapPhysUnlock                           ; Unlock the physent (and its chain of mappings)
+                       
+                       lwz             r3,mpFlags(r31)                         ; Get mapping's flags
+                       rlwinm  r3,r3,0,~mpgFlags                       ; Clear all guest flags
+                       ori             r3,r3,mpgFree                           ; Mark mapping free
+                       stw             r3,mpFlags(r31)                         ; Update flags
+                       
+graMiss:       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping
+                       rlwinm. r0,r31,0,GV_PAGE_MASK           ; End of hash table page?
+                       bne             graLoop                                         ; No, examine next slot
+                       addi    r28,r28,1                                       ; Increment hash table page index
+                       cmplwi  r28,GV_HPAGES                           ; End of hash table?
+                       bne             graPgLoop                                       ; Examine next hash table page
+                       
+                       la              r3,pmapSXlk(r24)                        ; r3 <- host pmap's search lock
+                       bl              sxlkUnlock                                      ; Release host pmap's search lock
+                       
+                       bt++    pf64Bitb,graRtn64                       ; Handle 64-bit separately
+                       mtmsr   r30                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       b               graPopFrame                                     ; Nothing to do now but pop a frame and return
+graRtn64:      mtmsrd  r30                                                     ; Restore 'rupts, translation, 32-bit mode
+graPopFrame:           
+                       lwz             r0,(FM_ALIGN(graStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r24,FM_ARG0+0x1C(r1)            ; Restore non-volatile r24
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+graBadPLock:
+graRemoveMiss:
+                       lis             r0,hi16(Choke)                          ; Dmitri, you know how we've always talked about the
+                       ori             r0,r0,lo16(Choke)                       ;  possibility of something going wrong with the bomb?
+                       li              r3,failMapping                          ; The BOMB, Dmitri.
+                       sc                                                                      ; The hydrogen bomb.
+
+
+;
+;                      Guest shadow assist -- remove local guest mappings
+;
+;                      Remove local mappings for a guest pmap from the shadow hash table.
+;
+;                      Parameters:
+;                              r3 : address of guest pmap, 32-bit kernel virtual address
+;
+;                      Non-volatile register usage:
+;                              r20 : current active map word's physical address
+;                              r21 : current hash table page address
+;                              r22 : updated active map word in process
+;                              r23 : active map word in process
+;                              r24 : host pmap's physical address
+;                              r25 : VMM extension block's physical address
+;                              r26 : physent address
+;                              r27 : guest pmap's space ID number
+;                              r28 : current active map index
+;                              r29 : guest pmap's physical address
+;                              r30 : saved msr image
+;                              r31 : current mapping
+;
+                       .align  5
+                       .globl  EXT(hw_rem_local_gv)
+                       
+LEXT(hw_rem_local_gv)
+
+#define grlStackSize ((31-20+1)*4)+4
+                       stwu    r1,-(FM_ALIGN(grlStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(grlStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+                       stw             r24,FM_ARG0+0x1C(r1)            ; Save non-volatile r24
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save non-volatile r23
+                       stw             r22,FM_ARG0+0x24(r1)            ; Save non-volatile r22
+                       stw             r21,FM_ARG0+0x28(r1)            ; Save non-volatile r21
+                       stw             r20,FM_ARG0+0x2C(r1)            ; Save non-volatile r20
+                                                                                               
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+
+                       bt++    pf64Bitb,grl64Salt                      ; Test for 64-bit machine
+                       lwz             r25,pmapVmmExtPhys+4(r3)        ; r25 <- VMM pmap extension block paddr
+                       lwz             r9,pmapvr+4(r3)                         ; Get 32-bit virt<->real conversion salt
+                       lwz             r24,vmxHostPmapPhys+4(r11)      ; r24 <- host pmap's paddr
+                       b               grlStart                                        ; Get to it                     
+grl64Salt:     ld              r25,pmapVmmExtPhys(r3)          ; r25 <- VMM pmap extension block paddr
+                       ld              r9,pmapvr(r3)                           ; Get 64-bit virt<->real conversion salt
+                       ld              r24,vmxHostPmapPhys(r11)        ; r24 <- host pmap's paddr
+
+grlStart:      bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, enter 64-bit mode
+                       xor             r29,r3,r9                                       ; Convert pmap_t virt->real
+                       mr              r30,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r24)                        ; r3 <- host pmap's search lock
+                       bl              sxlkExclusive                           ; Get lock exclusive
+
+                       li              r28,0                                           ; r28 <- index of first active map word to search
+                       lwz             r27,pmapSpace(r29)                      ; r27 <- guest pmap's space ID number
+                       b               grlMap1st                                       ; Examine first map word
+
+                       .align  5
+grlNextMap:    stw             r22,0(r21)                                      ; Save updated map word
+                       addi    r28,r28,1                                       ; Increment map word index
+                       cmplwi  r28,GV_MAP_WORDS                        ; See if we're done
+                       beq             grlDone                                         ; Yup, let's get outta here
+
+grlMap1st:     la              r20,VMX_ACTMAP_OFFSET(r25)      ; Get base of active map word array
+                       rlwinm  r11,r28,GV_MAPWD_SZ_LG2,GV_MAP_MASK
+                                                                                               ; Convert map index into map index offset
+                       add             r20,r20,r11                                     ; Calculate map array element address
+                       lwz             r22,0(r20)                                      ; Get active map word at index
+                       mr.             r23,r22                                         ; Any active mappings indicated?
+                       beq             grlNextMap                                      ; Nope, check next word
+                       
+                       la              r21,VMX_HPIDX_OFFSET(r25)       ; Get base of hash page physical index
+                       rlwinm  r11,r28,GV_MAP_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Extract page index from map word index and convert
+                                                                                               ;  into page physical index offset
+                       add             r21,r21,r11                                     ; Calculate page physical index entry address
+                       bt++    pf64Bitb,grl64Page                      ; Separate handling for 64-bit
+                       lwz             r21,4(r21)                                      ; Get selected hash table page's address
+                       b               grlLoop                                         ; Examine all slots in this page
+grl64Page:     ld              r21,0(r21)                                      ; Get selected hash table page's address
+                       b               grlLoop                                         ; Examine all slots in this page
+                       
+                       .align  5
+grlLoop:       cntlzw  r11,r23                                         ; Get next active bit lit in map word
+                       cmplwi  r11,32                                          ; Any active mappings left in this word?
+                       lis             r12,0x8000                                      ; Prepare mask to reset bit
+                       srw             r12,r12,r11                                     ; Position mask bit
+                       andc    r23,r23,r12                                     ; Reset lit bit
+                       beq             grlNextMap                                      ; No bits lit, examine next map word                                            
+
+                       slwi    r31,r11,GV_SLOT_SZ_LG2          ; Get slot offset in slot band from lit bit number
+                       rlwinm  r31,r28,GV_BAND_SHIFT,GV_BAND_MASK
+                                                                                               ; Extract slot band number from index and insert
+                       add             r31,r31,r21                                     ; Add hash page address yielding mapping slot address
+
+                       lwz             r3,mpFlags(r31)                         ; Get mapping's flags
+                       lhz             r4,mpSpace(r31)                         ; Get mapping's space ID number
+                       rlwinm  r5,r3,0,mpgGlobal                       ; Extract global bit
+                       xor             r4,r4,r27                                       ; Compare space ID number
+                       or.             r4,r4,r5                                        ; (space id miss || global)
+                       bne             grlLoop                                         ; Not one of ours, skip it
+                       andc    r22,r22,r12                                     ; Reset active bit corresponding to this mapping
+                       ori             r3,r3,mpgDormant                        ; Mark entry dormant
+                       stw             r3,mpFlags(r31)                         ; Update mapping's flags
+
+                       bt++    pf64Bitb,grlDscon64                     ; Handle 64-bit disconnect separately
+                       bl              mapInvPte32                                     ; Disconnect PTE, invalidate, gather ref and change
+                                                                                               ; r31 <- mapping's physical address
+                                                                                               ; r3  -> PTE slot physical address
+                                                                                               ; r4  -> High-order 32 bits of PTE
+                                                                                               ; r5  -> Low-order  32 bits of PTE
+                                                                                               ; r6  -> PCA
+                                                                                               ; r7  -> PCA physical address
+                       rlwinm  r2,r3,29,29,31                          ; Get PTE's slot number in the PTEG (8-byte PTEs)
+                       b               grlFreePTE                                      ; Join 64-bit path to release the PTE                   
+grlDscon64:    bl              mapInvPte64                                     ; Disconnect PTE, invalidate, gather ref and change
+                       rlwinm  r2,r3,28,29,31                          ; Get PTE's slot number in the PTEG (16-byte PTEs)
+grlFreePTE: mr.                r3,r3                                           ; Was there a valid PTE?
+                       beq-    grlLoop                                         ; No valid PTE, we're done with this mapping
+                       lis             r0,0x8000                                       ; Prepare free bit for this slot
+                       srw             r0,r0,r2                                        ; Position free bit
+                       or              r6,r6,r0                                        ; Set it in our PCA image
+                       lwz             r8,mpPte(r31)                           ; Get PTE pointer
+                       rlwinm  r8,r8,0,~mpHValid                       ; Make the pointer invalid
+                       stw             r8,mpPte(r31)                           ; Save invalidated PTE pointer
+                       eieio                                                           ; Synchronize all previous updates (mapInvPtexx doesn't)
+                       stw             r6,0(r7)                                        ; Update PCA and unlock the PTEG
+                       b               grlLoop                                         ; On to next active mapping in this map word
+                                               
+grlDone:       la              r3,pmapSXlk(r24)                        ; r3 <- host pmap's search lock
+                       bl              sxlkUnlock                                      ; Release host pmap's search lock
+                       
+                       bt++    pf64Bitb,grlRtn64                       ; Handle 64-bit separately
+                       mtmsr   r30                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       b               grlPopFrame                                     ; Nothing to do now but pop a frame and return
+grlRtn64:      mtmsrd  r30                                                     ; Restore 'rupts, translation, 32-bit mode
+grlPopFrame:           
+                       lwz             r0,(FM_ALIGN(grlStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r24,FM_ARG0+0x1C(r1)            ; Restore non-volatile r24
+                       lwz             r23,FM_ARG0+0x20(r1)            ; Restore non-volatile r23
+                       lwz             r22,FM_ARG0+0x24(r1)            ; Restore non-volatile r22
+                       lwz             r21,FM_ARG0+0x28(r1)            ; Restore non-volatile r21
+                       lwz             r20,FM_ARG0+0x2C(r1)            ; Restore non-volatile r20
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+
+;
+;                      Guest shadow assist -- resume a guest mapping
+;
+;                      Locates the specified dormant mapping, and if it exists validates it and makes it
+;                      active.
+;
+;                      Parameters:
+;                              r3 : address of host pmap, 32-bit kernel virtual address
+;                              r4 : address of guest pmap, 32-bit kernel virtual address
+;                              r5 : host virtual address, high-order 32 bits
+;                              r6 : host virtual address,  low-order 32 bits
+;                              r7 : guest virtual address, high-order 32 bits
+;                              r8 : guest virtual address,  low-order 32 bits
+;                              r9 : guest mapping protection code
+;
+;                      Non-volatile register usage:
+;                              r23 : VMM extension block's physical address
+;                              r24 : physent physical address
+;                              r25 : caller's msr image from mapSetUp
+;                              r26 : guest mapping protection code
+;                              r27 : host pmap physical address
+;                              r28 : guest pmap physical address
+;                              r29 : host virtual address
+;                              r30 : guest virtual address
+;                              r31 : gva->phys mapping's physical address
+;
+                       .align  5
+                       .globl  EXT(hw_res_map_gv)
+                       
+LEXT(hw_res_map_gv)
+
+#define grsStackSize ((31-23+1)*4)+4
+
+                       stwu    r1,-(FM_ALIGN(grsStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(grsStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+                       stw             r24,FM_ARG0+0x1C(r1)            ; Save non-volatile r24
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save non-volatile r23
+
+                       rlwinm  r29,r6,0,0xFFFFF000                     ; Clean up low-order 32 bits of host vaddr
+                       rlwinm  r30,r8,0,0xFFFFF000                     ; Clean up low-order 32 bits of guest vaddr
+                       mr              r26,r9                                          ; Copy guest mapping protection code
+
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+                       lwz             r9,pmapSpace(r4)                        ; r9 <- guest space ID number
+                       bt++    pf64Bitb,grs64Salt                      ; Handle 64-bit machine separately
+                       lwz             r23,pmapVmmExtPhys+4(r3)        ; r23 <- VMM pmap extension block paddr
+                       lwz             r27,pmapvr+4(r3)                        ; Get 32-bit virt<->real host pmap conversion salt
+                       lwz             r28,pmapvr+4(r4)                        ; Get 32-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+                       b               grsStart                                        ; Get to it                     
+
+grs64Salt:     rldimi  r29,r5,32,0                                     ; Insert high-order 32 bits of 64-bit host vaddr                        
+                       rldimi  r30,r7,32,0                                     ; Insert high-order 32 bits of 64-bit guest vaddr                       
+                       ld              r23,pmapVmmExtPhys(r3)          ; r23 <- VMM pmap extension block paddr
+                       ld              r27,pmapvr(r3)                          ; Get 64-bit virt<->real host pmap conversion salt
+                       ld              r28,pmapvr(r4)                          ; Get 64-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+
+grsStart:      xor             r27,r3,r27                                      ; Convert host pmap_t virt->real
+                       xor             r28,r4,r28                                      ; Convert guest pmap_t virt->real
+                       bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, maybe enter 64-bit mode
+                       mr              r25,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exclusive
+
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,grs64Search            ; Test for 64-bit machine
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       b               grs32SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+grs32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             grsSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    grs32SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             grsSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       b               grsSrchMiss                                     ; No joy in our hash group
+                       
+grs64Search:                   
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       b               grs64SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+grs64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             grsSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    grs64SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && space match && virtual addr match
+                       bne             grsSrchMiss                                     ; No joy in our hash group
+                       
+grsSrchHit:
+                       rlwinm. r0,r6,0,mpgDormant                      ; Is the mapping dormant?
+                       bne             grsFindHost                                     ; Yes, nothing to disconnect
+
+                       bt++    pf64Bitb,grsDscon64                     ; Handle 64-bit disconnect separately
+                       bl              mapInvPte32                                     ; Disconnect PTE, invalidate, gather ref and change
+                                                                                               ; r31 <- mapping's physical address
+                                                                                               ; r3  -> PTE slot physical address
+                                                                                               ; r4  -> High-order 32 bits of PTE
+                                                                                               ; r5  -> Low-order  32 bits of PTE
+                                                                                               ; r6  -> PCA
+                                                                                               ; r7  -> PCA physical address
+                       rlwinm  r2,r3,29,29,31                          ; Get PTE's slot number in the PTEG (8-byte PTEs)
+                       b               grsFreePTE                                      ; Join 64-bit path to release the PTE                   
+grsDscon64:    bl              mapInvPte64                                     ; Disconnect PTE, invalidate, gather ref and change
+                       rlwinm  r2,r3,28,29,31                          ; Get PTE's slot number in the PTEG (16-byte PTEs)
+grsFreePTE: mr.                r3,r3                                           ; Was there a valid PTE?
+                       beq-    grsFindHost                                     ; No valid PTE, we're almost done
+                       lis             r0,0x8000                                       ; Prepare free bit for this slot
+                       srw             r0,r0,r2                                        ; Position free bit
+                       or              r6,r6,r0                                        ; Set it in our PCA image
+                       lwz             r8,mpPte(r31)                           ; Get PTE pointer
+                       rlwinm  r8,r8,0,~mpHValid                       ; Make the pointer invalid
+                       stw             r8,mpPte(r31)                           ; Save invalidated PTE pointer
+                       eieio                                                           ; Synchronize all previous updates (mapInvPtexx didn't)
+                       stw             r6,0(r7)                                        ; Update PCA and unlock the PTEG
+
+grsFindHost:
+
+// We now have a dormant guest mapping that matches our space id and virtual address. Our next
+// step is to locate the host mapping that completes the guest mapping's connection to a physical
+// frame. The guest and host mappings must connect to the same physical frame, so they must both
+// be chained on the same physent. We search the physent chain for a host mapping matching our
+// host's space id and the host virtual address. If we succeed, we know that the entire chain
+// of mappings (guest virtual->host virtual->physical) is valid, so the dormant mapping can be
+// resumed. If we fail to find the specified host virtual->physical mapping, it is because the
+// host virtual or physical address has changed since the guest mapping was suspended, so it
+// is no longer valid and cannot be resumed -- we therefore delete the guest mappping and tell
+// our caller that it will have to take its long path, translating the host virtual address
+// through the host's skiplist and installing a new guest mapping.
+
+                       lwz             r3,mpPAddr(r31)                         ; r3 <- physical 4K-page number
+                       bl              mapFindLockPN                           ; Find 'n' lock this page's physent
+                       mr.             r24,r3                                          ; Got lock on our physent?
+                       beq--   grsBadPLock                                     ; No, time to bail out
+                       
+                       bt++    pf64Bitb,grsPFnd64                      ; 64-bit version of physent chain search
+                       
+                       lwz             r9,ppLink+4(r24)                        ; Get first mapping on physent
+                       lwz             r6,pmapSpace(r27)                       ; Get host pmap's space id number
+                       rlwinm  r9,r9,0,~ppFlags                        ; Be-gone, unsightly flags
+grsPELoop:     mr.             r12,r9                                          ; Got a mapping to look at?
+                       beq-    grsPEMiss                                       ; Nope, we've missed hva->phys mapping
+                       lwz             r7,mpFlags(r12)                         ; Get mapping's flags
+                       lhz             r4,mpSpace(r12)                         ; Get mapping's space id number
+                       lwz             r5,mpVAddr+4(r12)                       ; Get mapping's virtual address
+                       lwz             r9,mpAlias+4(r12)                       ; Next mapping in physent alias chain
+                       
+                       rlwinm  r0,r7,0,mpType                          ; Isolate mapping's type
+                       rlwinm  r5,r5,0,~mpHWFlags                      ; Bye-bye unsightly flags
+                       xori    r0,r0,mpNormal                          ; Normal mapping?
+                       xor             r4,r4,r6                                        ; Compare w/ host space id number
+                       xor             r5,r5,r29                                       ; Compare w/ host virtual address
+                       or              r0,r0,r4                                        ; r0 <- (wrong type || !space id)
+                       or.             r0,r0,r5                                        ; cr0_eq <- (right type && space id hit && hva hit)
+                       beq             grsPEHit                                        ; Hit
+                       b               grsPELoop                                       ; Iterate
+                       
+grsPFnd64:     li              r0,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       ld              r9,ppLink(r24)                          ; Get first mapping on physent
+                       lwz             r6,pmapSpace(r27)                       ; Get pmap's space id number
+                       andc    r9,r9,r0                                        ; Cleanup mapping pointer
+grsPELp64:     mr.             r12,r9                                          ; Got a mapping to look at?
+                       beq--   grsPEMiss                                       ; Nope, we've missed hva->phys mapping
+                       lwz             r7,mpFlags(r12)                         ; Get mapping's flags
+                       lhz             r4,mpSpace(r12)                         ; Get mapping's space id number
+                       ld              r5,mpVAddr(r12)                         ; Get mapping's virtual address
+                       ld              r9,mpAlias(r12)                         ; Next mapping physent alias chain
+                       rlwinm  r0,r7,0,mpType                          ; Isolate mapping's type
+                       rldicr  r5,r5,0,mpHWFlagsb-1            ; Bye-bye unsightly flags
+                       xori    r0,r0,mpNormal                          ; Normal mapping?
+                       xor             r4,r4,r6                                        ; Compare w/ host space id number
+                       xor             r5,r5,r29                                       ; Compare w/ host virtual address
+                       or              r0,r0,r4                                        ; r0 <- (wrong type || !space id)
+                       or.             r0,r0,r5                                        ; cr0_eq <- (right type && space id hit && hva hit)
+                       beq             grsPEHit                                        ; Hit
+                       b               grsPELp64                                       ; Iterate
+                       
+grsPEHit:      lwz             r0,mpVAddr+4(r31)                       ; Get va byte containing protection bits
+                       rlwimi  r0,r26,0,mpPP                           ; Insert new protection bits
+                       stw             r0,mpVAddr+4(r31)                       ; Write 'em back
+
+                       eieio                                                           ; Ensure previous mapping updates are visible
+                       lwz             r0,mpFlags(r31)                         ; Get flags
+                       rlwinm  r0,r0,0,~mpgDormant                     ; Turn off dormant flag
+                       stw             r0,mpFlags(r31)                         ; Set updated flags, entry is now valid
+                       
+                       li              r31,mapRtOK                                     ; Indicate success
+                       b               grsRelPhy                                       ; Exit through physent lock release
+
+grsPEMiss:     crset   cr1_eq                                          ; cr1_eq <- previous link is the anchor
+                       bt++    pf64Bitb,grsRemove64            ; Use 64-bit version on 64-bit machine
+                       la              r11,ppLink+4(r24)                       ; Point to chain anchor
+                       lwz             r9,ppLink+4(r24)                        ; Get chain anchor
+                       rlwinm. r9,r9,0,~ppFlags                        ; Remove flags, yielding 32-bit physical chain pointer
+grsRemLoop:    beq-    grsPEMissMiss                           ; End of chain, this is not good
+                       cmplw   r9,r31                                          ; Is this the mapping to remove?
+                       lwz             r8,mpAlias+4(r9)                        ; Get forward chain pointer
+                       bne             grsRemNext                                      ; No, chain onward
+                       bt              cr1_eq,grsRemRetry                      ; Mapping to remove is chained from anchor
+                       stw             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               grsDelete                                       ; Finish deleting mapping
+grsRemRetry:
+                       lwarx   r0,0,r11                                        ; Get previous link
+                       rlwimi  r0,r8,0,~ppFlags                        ; Insert new forward pointer whilst preserving flags
+                       stwcx.  r0,0,r11                                        ; Update previous link
+                       bne-    grsRemRetry                                     ; Lost reservation, retry
+                       b               grsDelete                                       ; Finish deleting mapping
+                       
+                       .align  5
+grsRemNext:    la              r11,mpAlias+4(r9)                       ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               grsRemLoop                                      ; Carry on
+
+grsRemove64:
+                       li              r7,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r7,r7,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       la              r11,ppLink(r24)                         ; Point to chain anchor
+                       ld              r9,ppLink(r24)                          ; Get chain anchor
+                       andc.   r9,r9,r7                                        ; Remove flags, yielding 64-bit physical chain pointer
+grsRem64Lp:    beq--   grsPEMissMiss                           ; End of chain, this is not good
+                       cmpld   r9,r31                                          ; Is this the mapping to remove?
+                       ld              r8,mpAlias(r9)                          ; Get forward chain pinter
+                       bne             grsRem64Nxt                                     ; Not mapping to remove, chain on, dude
+                       bt              cr1_eq,grsRem64Rt                       ; Mapping to remove is chained from anchor
+                       std             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               grsDelete                                       ; Finish deleting mapping
+grsRem64Rt:    ldarx   r0,0,r11                                        ; Get previous link
+                       and             r0,r0,r7                                        ; Get flags
+                       or              r0,r0,r8                                        ; Insert new forward pointer
+                       stdcx.  r0,0,r11                                        ; Slam it back in
+                       bne--   grsRem64Rt                                      ; Lost reservation, retry
+                       b               grsDelete                                       ; Finish deleting mapping
+
+                       .align  5               
+grsRem64Nxt:
+                       la              r11,mpAlias(r9)                         ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               grsRem64Lp                                      ; Carry on
+                       
+grsDelete:
+                       lwz             r3,mpFlags(r31)                         ; Get mapping's flags
+                       rlwinm  r3,r3,0,~mpgFlags                       ; Clear all guest flags
+                       ori             r3,r3,mpgFree                           ; Mark mapping free
+                       stw             r3,mpFlags(r31)                         ; Update flags
+
+                       li              r31,mapRtNotFnd                         ; Didn't succeed
+
+grsRelPhy:     mr              r3,r24                                          ; r3 <- physent addr
+                       bl              mapPhysUnlock                           ; Unlock physent chain
+                       
+grsRelPmap:    la              r3,pmapSXlk(r27)                        ; r3 <- host pmap search lock phys addr
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+                       
+grsRtn:                mr              r3,r31                                          ; r3 <- result code
+                       bt++    pf64Bitb,grsRtn64                       ; Handle 64-bit separately
+                       mtmsr   r25                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       b               grsPopFrame                                     ; Nothing to do now but pop a frame and return
+grsRtn64:      mtmsrd  r25                                                     ; Restore 'rupts, translation, 32-bit mode
+grsPopFrame:           
+                       lwz             r0,(FM_ALIGN(grsStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r24,FM_ARG0+0x1C(r1)            ; Restore non-volatile r24
+                       lwz             r23,FM_ARG0+0x20(r1)            ; Restore non-volatile r23
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+                       .align  5
+grsSrchMiss:
+                       li              r31,mapRtNotFnd                         ; Could not locate requested mapping
+                       b               grsRelPmap                                      ; Exit through host pmap search lock release
+
+grsBadPLock:
+grsPEMissMiss:
+                       lis             r0,hi16(Choke)                          ; Dmitri, you know how we've always talked about the
+                       ori             r0,r0,lo16(Choke)                       ;  possibility of something going wrong with the bomb?
+                       li              r3,failMapping                          ; The BOMB, Dmitri.
+                       sc                                                                      ; The hydrogen bomb.
+
+
+;
+;                      Guest shadow assist -- add a guest mapping
+;
+;                      Adds a guest mapping.
+;
+;                      Parameters:
+;                              r3 : address of host pmap, 32-bit kernel virtual address
+;                              r4 : address of guest pmap, 32-bit kernel virtual address
+;                              r5 : guest virtual address, high-order 32 bits
+;                              r6 : guest virtual address,  low-order 32 bits (with mpHWFlags)
+;                              r7 : new mapping's flags
+;                              r8 : physical address, 32-bit page number
+;
+;                      Non-volatile register usage:
+;                              r22 : hash group's physical address
+;                              r23 : VMM extension block's physical address
+;                              r24 : mapping's flags
+;                              r25 : caller's msr image from mapSetUp
+;                              r26 : physent physical address
+;                              r27 : host pmap physical address
+;                              r28 : guest pmap physical address
+;                              r29 : physical address, 32-bit 4k-page number
+;                              r30 : guest virtual address
+;                              r31 : gva->phys mapping's physical address
+;
+                       
+                       .align  5
+                       .globl  EXT(hw_add_map_gv)
+                       
+                       
+LEXT(hw_add_map_gv)
+
+#define gadStackSize ((31-22+1)*4)+4
+
+                       stwu    r1,-(FM_ALIGN(gadStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(gadStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+                       stw             r24,FM_ARG0+0x1C(r1)            ; Save non-volatile r24
+                       stw             r23,FM_ARG0+0x20(r1)            ; Save non-volatile r23
+                       stw             r22,FM_ARG0+0x24(r1)            ; Save non-volatile r22
+
+                       rlwinm  r30,r5,0,1,0                            ; Get high-order 32 bits of guest vaddr
+                       rlwimi  r30,r6,0,0,31                           ; Get  low-order 32 bits of guest vaddr
+                       mr              r24,r7                                          ; Copy guest mapping's flags
+                       mr              r29,r8                                          ; Copy target frame's physical address
+
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+                       lwz             r9,pmapSpace(r4)                        ; r9 <- guest space ID number
+                       bt++    pf64Bitb,gad64Salt                      ; Test for 64-bit machine
+                       lwz             r23,pmapVmmExtPhys+4(r3)        ; r23 <- VMM pmap extension block paddr
+                       lwz             r27,pmapvr+4(r3)                        ; Get 32-bit virt<->real host pmap conversion salt
+                       lwz             r28,pmapvr+4(r4)                        ; Get 32-bit virt<->real guest pmap conversion salt
+                       la              r22,VMX_HPIDX_OFFSET(r11)       ; r22 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r22,r22,r10                                     ; r22 <- hash page index entry
+                       lwz             r22,4(r22)                                      ; r22 <- hash page paddr
+                       rlwimi  r22,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r22 <- hash group paddr
+                       b               gadStart                                        ; Get to it                     
+
+gad64Salt:     ld              r23,pmapVmmExtPhys(r3)          ; r23 <- VMM pmap extension block paddr
+                       ld              r27,pmapvr(r3)                          ; Get 64-bit virt<->real host pmap conversion salt
+                       ld              r28,pmapvr(r4)                          ; Get 64-bit virt<->real guest pmap conversion salt
+                       la              r22,VMX_HPIDX_OFFSET(r11)       ; r22 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r22,r22,r10                                     ; r22 <- hash page index entry
+                       ld              r22,0(r22)                                      ; r22 <- hash page paddr
+                       insrdi  r22,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r22 <- hash group paddr
+
+gadStart:      xor             r27,r3,r27                                      ; Convert host pmap_t virt->real
+                       xor             r28,r4,r28                                      ; Convert guest pmap_t virt->real
+                       bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, maybe enter 64-bit mode
+                       mr              r25,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exlusive
+
+                       mr              r31,r22                                         ; Prepare to search this group
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,gad64Search            ; Test for 64-bit machine
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       clrrwi  r12,r30,12                                      ; r12 <- virtual address we're searching for
+                       b               gad32SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gad32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && space match)
+                       xor             r8,r8,r12                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             gadRelPmap                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gad32SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && && space match)
+                       xor             r5,r5,r12                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- free && space match && virtual addr match
+                       beq             gadRelPmap                                      ; Join common path on hit (r31 points to guest mapping)
+                       b               gadScan                                         ; No joy in our hash group
+                       
+gad64Search:                   
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       clrrdi  r12,r30,12                                      ; r12 <- virtual address we're searching for
+                       b               gad64SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gad64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && space match)
+                       xor             r8,r8,r12                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && space match && virtual addr match
+                       beq             gadRelPmap                                      ; Hit, let upper-level redrive sort it out
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gad64SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       rlwinm  r11,r6,0,mpgFree                        ; Isolate guest free flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && && space match)
+                       xor             r5,r5,r12                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && space match && virtual addr match
+                       bne             gadScan                                         ; No joy in our hash group
+                       b               gadRelPmap                                      ; Hit, let upper-level redrive sort it out
+                       
+gadScan:       lbz             r12,mpgCursor(r22)                      ; Get group's cursor
+                       rlwinm  r12,r12,GV_SLOT_SZ_LG2,(GV_SLOT_MASK << GV_SLOT_SZ_LG2)
+                                                                                               ; Prepare to address slot at cursor
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       or              r2,r22,r12                                      ; r2 <- 1st mapping to search
+                       lwz             r3,mpFlags(r2)                          ; r3 <- 1st mapping slot's flags
+                       li              r11,0                                           ; No dormant entries found yet
+                       b               gadScanLoop                                     ; Let the search begin!
+                       
+                       .align  5
+gadScanLoop:
+                       addi    r12,r12,GV_SLOT_SZ                      ; Calculate next slot number to search
+                       rlwinm  r12,r12,0,(GV_SLOT_MASK << GV_SLOT_SZ_LG2)
+                                                                                               ; Trim off any carry, wrapping into slot number range
+                       mr              r31,r2                                          ; r31 <- current mapping's address
+                       or              r2,r22,r12                                      ; r2 <- next mapping to search
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags(r2)                          ; r3 <- next mapping slot's flags
+                       rlwinm. r0,r6,0,mpgFree                         ; Test free flag
+                       bne             gadFillMap                                      ; Join common path on hit (r31 points to free mapping)
+                       rlwinm  r0,r6,0,mpgDormant                      ; Dormant entry?
+                       xori    r0,r0,mpgDormant                        ; Invert dormant flag
+                       or.             r0,r0,r11                                       ; Skip all but the first dormant entry we see
+                       bne             gadNotDorm                                      ; Not dormant or we've already seen one
+                       mr              r11,r31                                         ; We'll use this dormant entry if we don't find a free one first
+gadNotDorm:    bdnz    gadScanLoop                                     ; Iterate
+
+                       mr              r31,r2                                          ; r31 <- final mapping's address
+                       rlwinm. r0,r6,0,mpgFree                         ; Test free flag in final mapping
+                       bne             gadFillMap                                      ; Join common path on hit (r31 points to dormant mapping)
+                       rlwinm  r0,r6,0,mpgDormant                      ; Dormant entry?
+                       xori    r0,r0,mpgDormant                        ; Invert dormant flag
+                       or.             r0,r0,r11                                       ; Skip all but the first dormant entry we see
+                       bne             gadCkDormant                            ; Not dormant or we've already seen one
+                       mr              r11,r31                                         ; We'll use this dormant entry if we don't find a free one first
+
+gadCkDormant:
+                       mr.             r31,r11                                         ; Get dormant mapping, if any, and test
+                       bne             gadUpCursor                                     ; Go update the cursor, we'll take the dormant entry
+                       
+gadSteal:
+                       lbz             r12,mpgCursor(r22)                      ; Get group's cursor
+                       rlwinm  r12,r12,GV_SLOT_SZ_LG2,(GV_SLOT_MASK << GV_SLOT_SZ_LG2)
+                                                                                               ; Prepare to address slot at cursor
+                       or              r31,r22,r12                                     ; r31 <- address of mapping to steal
+
+                       bt++    pf64Bitb,gadDscon64                     ; Handle 64-bit disconnect separately
+                       bl              mapInvPte32                                     ; Disconnect PTE, invalidate, gather ref and change
+                                                                                               ; r31 <- mapping's physical address
+                                                                                               ; r3  -> PTE slot physical address
+                                                                                               ; r4  -> High-order 32 bits of PTE
+                                                                                               ; r5  -> Low-order  32 bits of PTE
+                                                                                               ; r6  -> PCA
+                                                                                               ; r7  -> PCA physical address
+                       rlwinm  r2,r3,29,29,31                          ; Get PTE's slot number in the PTEG (8-byte PTEs)
+                       b               gadFreePTE                                      ; Join 64-bit path to release the PTE                   
+gadDscon64:    bl              mapInvPte64                                     ; Disconnect PTE, invalidate, gather ref and change
+                       rlwinm  r2,r3,28,29,31                          ; Get PTE's slot number in the PTEG (16-byte PTEs)
+gadFreePTE: mr.                r3,r3                                           ; Was there a valid PTE?
+                       beq-    gadUpCursor                                     ; No valid PTE, we're almost done
+                       lis             r0,0x8000                                       ; Prepare free bit for this slot
+                       srw             r0,r0,r2                                        ; Position free bit
+                       or              r6,r6,r0                                        ; Set it in our PCA image
+                       lwz             r8,mpPte(r31)                           ; Get PTE pointer
+                       rlwinm  r8,r8,0,~mpHValid                       ; Make the pointer invalid
+                       stw             r8,mpPte(r31)                           ; Save invalidated PTE pointer
+                       eieio                                                           ; Synchronize all previous updates (mapInvPtexx didn't)
+                       stw             r6,0(r7)                                        ; Update PCA and unlock the PTEG
+
+gadUpCursor:
+                       rlwinm  r12,r31,(32-GV_SLOT_SZ_LG2),GV_SLOT_MASK
+                                                                                               ; Recover slot number from stolen mapping's address
+                       addi    r12,r12,1                                       ; Increment slot number
+                       rlwinm  r12,r12,0,GV_SLOT_MASK          ; Clip to slot number range
+                       stb             r12,mpgCursor(r22)                      ; Update group's cursor
+
+                       lwz             r3,mpPAddr(r31)                         ; r3 <- physical 4K-page number
+                       bl              mapFindLockPN                           ; Find 'n' lock this page's physent
+                       mr.             r26,r3                                          ; Got lock on our physent?
+                       beq--   gadBadPLock                                     ; No, time to bail out
+
+                       crset   cr1_eq                                          ; cr1_eq <- previous link is the anchor
+                       bt++    pf64Bitb,gadRemove64            ; Use 64-bit version on 64-bit machine
+                       la              r11,ppLink+4(r26)                       ; Point to chain anchor
+                       lwz             r9,ppLink+4(r26)                        ; Get chain anchor
+                       rlwinm. r9,r9,0,~ppFlags                        ; Remove flags, yielding 32-bit physical chain pointer
+gadRemLoop:    beq-    gadPEMissMiss                           ; End of chain, this is not good
+                       cmplw   r9,r31                                          ; Is this the mapping to remove?
+                       lwz             r8,mpAlias+4(r9)                        ; Get forward chain pointer
+                       bne             gadRemNext                                      ; No, chain onward
+                       bt              cr1_eq,gadRemRetry                      ; Mapping to remove is chained from anchor
+                       stw             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               gadDelDone                                      ; Finish deleting mapping
+gadRemRetry:
+                       lwarx   r0,0,r11                                        ; Get previous link
+                       rlwimi  r0,r8,0,~ppFlags                        ; Insert new forward pointer whilst preserving flags
+                       stwcx.  r0,0,r11                                        ; Update previous link
+                       bne-    gadRemRetry                                     ; Lost reservation, retry
+                       b               gadDelDone                                      ; Finish deleting mapping
+                       
+gadRemNext:    la              r11,mpAlias+4(r9)                       ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               gadRemLoop                                      ; Carry on
+
+gadRemove64:
+                       li              r7,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r7,r7,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       la              r11,ppLink(r26)                         ; Point to chain anchor
+                       ld              r9,ppLink(r26)                          ; Get chain anchor
+                       andc.   r9,r9,r7                                        ; Remove flags, yielding 64-bit physical chain pointer
+gadRem64Lp:    beq--   gadPEMissMiss                           ; End of chain, this is not good
+                       cmpld   r9,r31                                          ; Is this the mapping to remove?
+                       ld              r8,mpAlias(r9)                          ; Get forward chain pinter
+                       bne             gadRem64Nxt                                     ; Not mapping to remove, chain on, dude
+                       bt              cr1_eq,gadRem64Rt                       ; Mapping to remove is chained from anchor
+                       std             r8,0(r11)                                       ; Unchain gpv->phys mapping
+                       b               gadDelDone                                      ; Finish deleting mapping
+gadRem64Rt:    ldarx   r0,0,r11                                        ; Get previous link
+                       and             r0,r0,r7                                        ; Get flags
+                       or              r0,r0,r8                                        ; Insert new forward pointer
+                       stdcx.  r0,0,r11                                        ; Slam it back in
+                       bne--   gadRem64Rt                                      ; Lost reservation, retry
+                       b               gadDelDone                                      ; Finish deleting mapping
+
+                       .align  5               
+gadRem64Nxt:
+                       la              r11,mpAlias(r9)                         ; Point to (soon to be) previous link
+                       crclr   cr1_eq                                          ; ~cr1_eq <- Previous link is not the anchor
+                       mr.             r9,r8                                           ; Does next entry exist?
+                       b               gadRem64Lp                                      ; Carry on
+                       
+gadDelDone:
+                       mr              r3,r26                                          ; Get physent address
+                       bl              mapPhysUnlock                           ; Unlock physent chain
+
+gadFillMap:
+                       lwz             r12,pmapSpace(r28)                      ; Get guest space id number
+                       li              r2,0                                            ; Get a zero
+                       stw             r24,mpFlags(r31)                        ; Set mapping's flags
+                       sth             r12,mpSpace(r31)                        ; Set mapping's space id number
+                       stw             r2,mpPte(r31)                           ; Set mapping's pte pointer invalid
+                       stw             r29,mpPAddr(r31)                        ; Set mapping's physical address
+                       bt++    pf64Bitb,gadVA64                        ; Use 64-bit version on 64-bit machine
+                       stw             r30,mpVAddr+4(r31)                      ; Set mapping's virtual address (w/flags)
+                       b               gadChain                                        ; Continue with chaining mapping to physent
+gadVA64:       std             r30,mpVAddr(r31)                        ; Set mapping's virtual address (w/flags)
+                       
+gadChain:      mr              r3,r29                                          ; r3 <- physical frame address
+                       bl              mapFindLockPN                           ; Find 'n' lock this page's physent
+                       mr.             r26,r3                                          ; Got lock on our physent?
+                       beq--   gadBadPLock                                     ; No, time to bail out
+
+                       bt++    pf64Bitb,gadChain64                     ; Use 64-bit version on 64-bit machine
+                       lwz             r12,ppLink+4(r26)                       ; Get forward chain
+                       rlwinm  r11,r12,0,~ppFlags                      ; Get physent's forward pointer sans flags
+                       rlwimi  r12,r31,0,~ppFlags                      ; Insert new mapping, preserve physent flags
+                       stw             r11,mpAlias+4(r31)                      ; New mapping will head chain
+                       stw             r12,ppLink+4(r26)                       ; Point physent to new mapping
+                       b               gadFinish                                       ; All over now...
+
+gadChain64:    li              r7,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r7,r7,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       ld              r12,ppLink(r26)                         ; Get forward chain
+                       andc    r11,r12,r7                                      ; Get physent's forward chain pointer sans flags
+                       and             r12,r12,r7                                      ; Isolate pointer's flags
+                       or              r12,r12,r31                                     ; Insert new mapping's address forming pointer
+                       std             r11,mpAlias(r31)                        ; New mapping will head chain
+                       std             r12,ppLink(r26)                         ; Point physent to new mapping
+
+gadFinish:     eieio                                                           ; Ensure new mapping is completely visible
+                       
+gadRelPhy:     mr              r3,r26                                          ; r3 <- physent addr
+                       bl              mapPhysUnlock                           ; Unlock physent chain
+                       
+gadRelPmap:    la              r3,pmapSXlk(r27)                        ; r3 <- host pmap search lock phys addr
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+                       
+                       bt++    pf64Bitb,gadRtn64                       ; Handle 64-bit separately
+                       mtmsr   r25                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       b               gadPopFrame                                     ; Nothing to do now but pop a frame and return
+gadRtn64:      mtmsrd  r25                                                     ; Restore 'rupts, translation, 32-bit mode
+gadPopFrame:           
+                       lwz             r0,(FM_ALIGN(gadStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r24,FM_ARG0+0x1C(r1)            ; Restore non-volatile r24
+                       lwz             r23,FM_ARG0+0x20(r1)            ; Restore non-volatile r23
+                       lwz             r22,FM_ARG0+0x24(r1)            ; Restore non-volatile r22
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+gadPEMissMiss:
+gadBadPLock:
+                       lis             r0,hi16(Choke)                          ; Dmitri, you know how we've always talked about the
+                       ori             r0,r0,lo16(Choke)                       ;  possibility of something going wrong with the bomb?
+                       li              r3,failMapping                          ; The BOMB, Dmitri.
+                       sc                                                                      ; The hydrogen bomb.
+
+
+;
+;                      Guest shadow assist -- supend a guest mapping
+;
+;                      Suspends a guest mapping.
+;
+;                      Parameters:
+;                              r3 : address of host pmap, 32-bit kernel virtual address
+;                              r4 : address of guest pmap, 32-bit kernel virtual address
+;                              r5 : guest virtual address, high-order 32 bits
+;                              r6 : guest virtual address,  low-order 32 bits
+;
+;                      Non-volatile register usage:
+;                              r26 : VMM extension block's physical address
+;                              r27 : host pmap physical address
+;                              r28 : guest pmap physical address
+;                              r29 : caller's msr image from mapSetUp
+;                              r30 : guest virtual address
+;                              r31 : gva->phys mapping's physical address
+;
+
+                       .align  5
+                       .globl  EXT(hw_susp_map_gv)
+
+LEXT(hw_susp_map_gv)
+
+#define gsuStackSize ((31-26+1)*4)+4
+
+                       stwu    r1,-(FM_ALIGN(gsuStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(gsuStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+
+                       rlwinm  r30,r6,0,0xFFFFF000                     ; Clean up low-order 32 bits of guest vaddr
+
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+                       lwz             r9,pmapSpace(r4)                        ; r9 <- guest space ID number
+                       bt++    pf64Bitb,gsu64Salt                      ; Test for 64-bit machine
+
+                       lwz             r26,pmapVmmExtPhys+4(r3)        ; r26 <- VMM pmap extension block paddr
+                       lwz             r27,pmapvr+4(r3)                        ; Get 32-bit virt<->real host pmap conversion salt
+                       lwz             r28,pmapvr+4(r4)                        ; Get 32-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+                       b               gsuStart                                        ; Get to it                     
+gsu64Salt:     rldimi  r30,r5,32,0                                     ; Insert high-order 32 bits of 64-bit guest vaddr
+                       ld              r26,pmapVmmExtPhys(r3)          ; r26 <- VMM pmap extension block paddr
+                       ld              r27,pmapvr(r3)                          ; Get 64-bit virt<->real host pmap conversion salt
+                       ld              r28,pmapvr(r4)                          ; Get 64-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+
+gsuStart:      xor             r27,r3,r27                                      ; Convert host pmap_t virt->real
+                       xor             r28,r4,r28                                      ; Convert guest pmap_t virt->real
+                       bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, maybe enter 64-bit mode
+                       mr              r29,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exclusive
+
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,gsu64Search            ; Test for 64-bit machine
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       b               gsu32SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gsu32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gsuSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gsu32SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gsuSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       b               gsuSrchMiss                                     ; No joy in our hash group
+                       
+gsu64Search:                   
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       b               gsu64SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gsu64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gsuSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gsu64SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       bne             gsuSrchMiss                                     ; No joy in our hash group
+                       
+gsuSrchHit:
+                       bt++    pf64Bitb,gsuDscon64                     ; Handle 64-bit disconnect separately
+                       bl              mapInvPte32                                     ; Disconnect PTE, invalidate, gather ref and change
+                                                                                               ; r31 <- mapping's physical address
+                                                                                               ; r3  -> PTE slot physical address
+                                                                                               ; r4  -> High-order 32 bits of PTE
+                                                                                               ; r5  -> Low-order  32 bits of PTE
+                                                                                               ; r6  -> PCA
+                                                                                               ; r7  -> PCA physical address
+                       rlwinm  r2,r3,29,29,31                          ; Get PTE's slot number in the PTEG (8-byte PTEs)
+                       b               gsuFreePTE                                      ; Join 64-bit path to release the PTE                   
+gsuDscon64:    bl              mapInvPte64                                     ; Disconnect PTE, invalidate, gather ref and change
+                       rlwinm  r2,r3,28,29,31                          ; Get PTE's slot number in the PTEG (16-byte PTEs)
+gsuFreePTE: mr.                r3,r3                                           ; Was there a valid PTE?
+                       beq-    gsuNoPTE                                        ; No valid PTE, we're almost done
+                       lis             r0,0x8000                                       ; Prepare free bit for this slot
+                       srw             r0,r0,r2                                        ; Position free bit
+                       or              r6,r6,r0                                        ; Set it in our PCA image
+                       lwz             r8,mpPte(r31)                           ; Get PTE pointer
+                       rlwinm  r8,r8,0,~mpHValid                       ; Make the pointer invalid
+                       stw             r8,mpPte(r31)                           ; Save invalidated PTE pointer
+                       eieio                                                           ; Synchronize all previous updates (mapInvPtexx didn't)
+                       stw             r6,0(r7)                                        ; Update PCA and unlock the PTEG
+                       
+gsuNoPTE:      lwz             r3,mpFlags(r31)                         ; Get mapping's flags
+                       ori             r3,r3,mpgDormant                        ; Mark entry dormant
+                       stw             r3,mpFlags(r31)                         ; Save updated flags
+                       eieio                                                           ; Ensure update is visible when we unlock
+
+gsuSrchMiss:
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap search lock phys addr
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+                       
+                       bt++    pf64Bitb,gsuRtn64                       ; Handle 64-bit separately
+                       mtmsr   r29                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       b               gsuPopFrame                                     ; Nothing to do now but pop a frame and return
+gsuRtn64:      mtmsrd  r29                                                     ; Restore 'rupts, translation, 32-bit mode
+gsuPopFrame:           
+                       lwz             r0,(FM_ALIGN(gsuStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+;
+;                      Guest shadow assist -- test guest mapping reference and change bits
+;
+;                      Locates the specified guest mapping, and if it exists gathers its reference
+;                      and change bit, optionallyÊresetting them.
+;
+;                      Parameters:
+;                              r3 : address of host pmap, 32-bit kernel virtual address
+;                              r4 : address of guest pmap, 32-bit kernel virtual address
+;                              r5 : guest virtual address, high-order 32 bits
+;                              r6 : guest virtual address,  low-order 32 bits
+;                              r7 : reset boolean
+;
+;                      Non-volatile register usage:
+;                              r24 : VMM extension block's physical address
+;                              r25 : return code (w/reference and change bits)
+;                              r26 : reset boolean
+;                              r27 : host pmap physical address
+;                              r28 : guest pmap physical address
+;                              r29 : caller's msr image from mapSetUp
+;                              r30 : guest virtual address
+;                              r31 : gva->phys mapping's physical address
+;
+
+                       .align  5
+                       .globl  EXT(hw_test_rc_gv)
+
+LEXT(hw_test_rc_gv)
+
+#define gtdStackSize ((31-24+1)*4)+4
+
+                       stwu    r1,-(FM_ALIGN(gtdStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(gtdStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+                       stw             r24,FM_ARG0+0x1C(r1)            ; Save non-volatile r24
+
+                       rlwinm  r30,r6,0,0xFFFFF000                     ; Clean up low-order 20 bits of guest vaddr
+
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+                       lwz             r9,pmapSpace(r4)                        ; r9 <- guest space ID number
+
+                       bt++    pf64Bitb,gtd64Salt                      ; Test for 64-bit machine
+
+                       lwz             r24,pmapVmmExtPhys+4(r3)        ; r24 <- VMM pmap extension block paddr
+                       lwz             r27,pmapvr+4(r3)                        ; Get 32-bit virt<->real host pmap conversion salt
+                       lwz             r28,pmapvr+4(r4)                        ; Get 32-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+                       b               gtdStart                                        ; Get to it                     
+
+gtd64Salt:     rldimi  r30,r5,32,0                                     ; Insert high-order 32 bits of 64-bit guest vaddr
+                       ld              r24,pmapVmmExtPhys(r3)          ; r24 <- VMM pmap extension block paddr
+                       ld              r27,pmapvr(r3)                          ; Get 64-bit virt<->real host pmap conversion salt
+                       ld              r28,pmapvr(r4)                          ; Get 64-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+
+gtdStart:      xor             r27,r3,r27                                      ; Convert host pmap_t virt->real
+                       xor             r28,r4,r28                                      ; Convert guest pmap_t virt->real
+                       mr              r26,r7                                          ; Save reset boolean
+                       bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, maybe enter 64-bit mode
+                       mr              r29,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exclusive
+
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,gtd64Search            ; Test for 64-bit machine
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       b               gtd32SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gtd32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gtdSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gtd32SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gtdSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       b               gtdSrchMiss                                     ; No joy in our hash group
+                       
+gtd64Search:                   
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       b               gtd64SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gtd64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gtdSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gtd64SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       bne             gtdSrchMiss                                     ; No joy in our hash group
+                       
+gtdSrchHit:
+                       bt++    pf64Bitb,gtdDo64                        ; Split for 64 bit
+                       
+                       bl              mapInvPte32                                     ; Invalidate and lock PTEG, also merge into physent
+                                               
+                       cmplwi  cr1,r26,0                                       ; Do we want to clear RC?
+                       lwz             r12,mpVAddr+4(r31)                      ; Get the bottom of the mapping vaddr field
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+                       li              r0,lo16(mpR|mpC)                        ; Get bits to clear
 
-LEXT(mapalc)
+                       and             r25,r5,r0                                       ; Copy RC bits into result
+                       beq++   cr1,gtdNoClr32                          ; Nope...
                        
-                       lwz             r4,mbfree(r3)                           ; Get the first mask 
-                       lis             r0,0x8000                                       ; Get the mask to clear the first free bit
-                       lwz             r5,mbfree+4(r3)                         ; Get the second mask 
-                       mr              r12,r3                                          ; Save the return
-                       cntlzw  r8,r4                                           ; Get first free field
-                       lwz             r6,mbfree+8(r3)                         ; Get the third mask 
-                       srw.    r9,r0,r8                                        ; Get bit corresponding to first free one
-                       lwz             r7,mbfree+12(r3)                        ; Get the fourth mask 
-                       cntlzw  r10,r5                                          ; Get first free field in second word
-                       andc    r4,r4,r9                                        ; Turn it off
-                       bne             malcfnd0                                        ; Found one...
+                       andc    r12,r12,r0                                      ; Clear mapping copy of RC
+                       andc    r5,r5,r0                                        ; Clear PTE copy of RC
+                       sth             r12,mpVAddr+6(r31)                      ; Set the new RC in mapping                     
+
+gtdNoClr32:    beq--   gtdNoOld32                                      ; No previously valid PTE...
                        
-                       srw.    r9,r0,r10                                       ; Get bit corresponding to first free one in second word
-                       cntlzw  r11,r6                                          ; Get first free field in third word
-                       andc    r5,r5,r9                                        ; Turn it off
-                       bne             malcfnd1                                        ; Found one...
+                       sth             r5,6(r3)                                        ; Store updated RC in PTE
+                       eieio                                                           ; Make sure we do not reorder
+                       stw             r4,0(r3)                                        ; Revalidate the PTE
+
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock PCA
+
+gtdNoOld32:    la              r3,pmapSXlk(r27)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       b               gtdR32                                          ; Join common...
+
+                       .align  5                       
                        
-                       srw.    r9,r0,r11                                       ; Get bit corresponding to first free one in third word
-                       cntlzw  r10,r7                                          ; Get first free field in fourth word
-                       andc    r6,r6,r9                                        ; Turn it off
-                       bne             malcfnd2                                        ; Found one...
                        
-                       srw.    r9,r0,r10                                       ; Get bit corresponding to first free one in second word
-                       li              r3,0                                            ; Assume abject failure
-                       andc    r7,r7,r9                                        ; Turn it off
-                       beqlr                                                           ; There are none any left...
+gtdDo64:       bl              mapInvPte64                                     ; Invalidate and lock PTEG, also merge into physent
+                                               
+                       cmplwi  cr1,r26,0                                       ; Do we want to clear RC?
+                       lwz             r12,mpVAddr+4(r31)                      ; Get the bottom of the mapping vaddr field
+                       mr.             r3,r3                                           ; Was there a previously valid PTE?
+                       li              r0,lo16(mpR|mpC)                        ; Get bits to clear
+
+                       and             r25,r5,r0                                       ; Copy RC bits into result
+                       beq++   cr1,gtdNoClr64                          ; Nope...
                        
-                       addi    r3,r10,96                                       ; Set the correct bit number
-                       stw             r7,mbfree+12(r12)                       ; Actually allocate the slot
+                       andc    r12,r12,r0                                      ; Clear mapping copy of RC
+                       andc    r5,r5,r0                                        ; Clear PTE copy of RC
+                       sth             r12,mpVAddr+6(r31)                      ; Set the new RC                        
+
+gtdNoClr64:    beq--   gtdNoOld64                                      ; Nope, no pevious pte...
                        
-mapafin:       or              r4,r4,r5                                        ; Merge the first two allocation maps
-                       or              r6,r6,r7                                        ; Then the last two
-                       or.             r4,r4,r6                                        ; Merge both halves
-                       bnelr+                                                          ; Return if some left for next time...
+                       sth             r5,14(r3)                                       ; Store updated RC
+                       eieio                                                           ; Make sure we do not reorder
+                       std             r4,0(r3)                                        ; Revalidate the PTE
+
+                       eieio                                                           ; Make sure all updates come first
+                       stw             r6,0(r7)                                        ; Unlock PCA
+
+gtdNoOld64:    la              r3,pmapSXlk(r27)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       b               gtdR64                                          ; Join common...
+
+gtdSrchMiss:
+                       la              r3,pmapSXlk(r27)                        ; Point to the pmap search lock
+                       bl              sxlkUnlock                                      ; Unlock the search list
+                       li              r25,mapRtNotFnd                         ; Get ready to return not found
+                       bt++    pf64Bitb,gtdR64                         ; Test for 64-bit machine
                        
-                       neg             r3,r3                                           ; Indicate we just allocated the last one
-                       blr                                                                     ; Leave...
+gtdR32:                mtmsr   r29                                                     ; Restore caller's msr image
+                       isync
+                       b               gtdEpilog
+                       
+gtdR64:                mtmsrd  r29                                                     ; Restore caller's msr image
+
+gtdEpilog:     lwz             r0,(FM_ALIGN(gtdStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       mr              r3,r25                                          ; Get return code
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r24,FM_ARG0+0x1C(r1)            ; Restore non-volatile r24
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+;
+;                      Guest shadow assist -- convert guest to host virtual address
+;
+;                      Locates the specified guest mapping, and if it exists locates the
+;                      first mapping belonging to its host on the physical chain and returns
+;                      its virtual address.
+;
+;                      Note that if there are multiple mappings belonging to this host
+;                      chained to the physent to which the guest mapping is chained, then
+;                      host virtual aliases exist for this physical address. If host aliases
+;                      exist, then we select the first on the physent chain, making it 
+;                      unpredictable which of the two or more possible host virtual addresses
+;                      will be returned.
+;
+;                      Parameters:
+;                              r3 : address of guest pmap, 32-bit kernel virtual address
+;                              r4 : guest virtual address, high-order 32 bits
+;                              r5 : guest virtual address,  low-order 32 bits
+;
+;                      Non-volatile register usage:
+;                              r24 : physent physical address
+;                              r25 : VMM extension block's physical address
+;                              r26 : host virtual address
+;                              r27 : host pmap physical address
+;                              r28 : guest pmap physical address
+;                              r29 : caller's msr image from mapSetUp
+;                              r30 : guest virtual address
+;                              r31 : gva->phys mapping's physical address
+;
+
+                       .align  5
+                       .globl  EXT(hw_gva_to_hva)
+
+LEXT(hw_gva_to_hva)
+
+#define gthStackSize ((31-24+1)*4)+4
+
+                       stwu    r1,-(FM_ALIGN(gtdStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(gtdStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+                       stw             r24,FM_ARG0+0x1C(r1)            ; Save non-volatile r24
+
+                       rlwinm  r30,r5,0,0xFFFFF000                     ; Clean up low-order 32 bits of guest vaddr
+
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+                       lwz             r9,pmapSpace(r3)                        ; r9 <- guest space ID number
+
+                       bt++    pf64Bitb,gth64Salt                      ; Test for 64-bit machine
+
+                       lwz             r25,pmapVmmExtPhys+4(r3)        ; r25 <- VMM pmap extension block paddr
+                       lwz             r28,pmapvr+4(r3)                        ; Get 32-bit virt<->real guest pmap conversion salt
+                       lwz             r27,vmxHostPmapPhys+4(r11)      ; Get host pmap physical address
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+                       b               gthStart                                        ; Get to it                     
+
+gth64Salt:     rldimi  r30,r4,32,0                                     ; Insert high-order 32 bits of 64-bit guest vaddr
+                       ld              r25,pmapVmmExtPhys(r3)          ; r24 <- VMM pmap extension block paddr
+                       ld              r28,pmapvr(r3)                          ; Get 64-bit virt<->real guest pmap conversion salt
+                       ld              r27,vmxHostPmapPhys(r11)        ; Get host pmap physical address
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+
+gthStart:      xor             r28,r3,r28                                      ; Convert guest pmap_t virt->real
+                       bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, maybe enter 64-bit mode
+                       mr              r29,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exclusive
+
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,gth64Search            ; Test for 64-bit machine
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       b               gth32SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gth32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gthSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gth32SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gthSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       b               gthSrchMiss                                     ; No joy in our hash group
+                       
+gth64Search:                   
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       b               gth64SrchLp                                     ; Let the search begin!
                        
-malcfnd0:      stw             r4,mbfree(r12)                          ; Actually allocate the slot
-                       mr              r3,r8                                           ; Set the correct bit number
-                       b               mapafin                                         ; Exit now...
+                       .align  5
+gth64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gthSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gth64SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       bne             gthSrchMiss                                     ; No joy in our hash group
+                       
+gthSrchHit:    lwz             r3,mpPAddr(r31)                         ; r3 <- physical 4K-page number
+                       bl              mapFindLockPN                           ; Find 'n' lock this page's physent
+                       mr.             r24,r3                                          ; Got lock on our physent?
+                       beq--   gthBadPLock                                     ; No, time to bail out
+                       
+                       bt++    pf64Bitb,gthPFnd64                      ; 64-bit version of physent chain search
+                       
+                       lwz             r9,ppLink+4(r24)                        ; Get first mapping on physent
+                       lwz             r6,pmapSpace(r27)                       ; Get host pmap's space id number
+                       rlwinm  r9,r9,0,~ppFlags                        ; Be-gone, unsightly flags
+gthPELoop:     mr.             r12,r9                                          ; Got a mapping to look at?
+                       beq-    gthPEMiss                                       ; Nope, we've missed hva->phys mapping
+                       lwz             r7,mpFlags(r12)                         ; Get mapping's flags
+                       lhz             r4,mpSpace(r12)                         ; Get mapping's space id number
+                       lwz             r26,mpVAddr+4(r12)                      ; Get mapping's virtual address
+                       lwz             r9,mpAlias+4(r12)                       ; Next mapping in physent alias chain
+                       
+                       rlwinm  r0,r7,0,mpType                          ; Isolate mapping's type
+                       rlwinm  r26,r26,0,~mpHWFlags            ; Bye-bye unsightly flags
+                       xori    r0,r0,mpNormal                          ; Normal mapping?
+                       xor             r4,r4,r6                                        ; Compare w/ host space id number
+                       or.             r0,r0,r4                                        ; cr0_eq <- (normal && space id hit)
+                       beq             gthPEHit                                        ; Hit
+                       b               gthPELoop                                       ; Iterate
+                       
+gthPFnd64:     li              r0,ppLFAmask                            ; Get mask to clean up mapping pointer
+                       rotrdi  r0,r0,ppLFArrot                         ; Rotate clean up mask to get 0xF0000000000000000F
+                       ld              r9,ppLink(r24)                          ; Get first mapping on physent
+                       lwz             r6,pmapSpace(r27)                       ; Get host pmap's space id number
+                       andc    r9,r9,r0                                        ; Cleanup mapping pointer
+gthPELp64:     mr.             r12,r9                                          ; Got a mapping to look at?
+                       beq--   gthPEMiss                                       ; Nope, we've missed hva->phys mapping
+                       lwz             r7,mpFlags(r12)                         ; Get mapping's flags
+                       lhz             r4,mpSpace(r12)                         ; Get mapping's space id number
+                       ld              r26,mpVAddr(r12)                        ; Get mapping's virtual address
+                       ld              r9,mpAlias(r12)                         ; Next mapping physent alias chain
+                       rlwinm  r0,r7,0,mpType                          ; Isolate mapping's type
+                       rldicr  r26,r26,0,mpHWFlagsb-1          ; Bye-bye unsightly flags
+                       xori    r0,r0,mpNormal                          ; Normal mapping?
+                       xor             r4,r4,r6                                        ; Compare w/ host space id number
+                       or.             r0,r0,r4                                        ; cr0_eq <- (normal && space id hit)
+                       beq             gthPEHit                                        ; Hit
+                       b               gthPELp64                                       ; Iterate
+
+                       .align  5                       
+gthPEMiss:     mr              r3,r24                                          ; Get physent's address
+                       bl              mapPhysUnlock                           ; Unlock physent chain
+gthSrchMiss:
+                       la              r3,pmapSXlk(r27)                        ; Get host pmap search lock address
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+                       li              r3,-1                                           ; Return 64-bit -1
+                       li              r4,-1
+                       bt++    pf64Bitb,gthEpi64                       ; Take 64-bit exit
+                       b               gthEpi32                                        ; Take 32-bit exit
+
+                       .align  5
+gthPEHit:      mr              r3,r24                                          ; Get physent's address
+                       bl              mapPhysUnlock                           ; Unlock physent chain
+                       la              r3,pmapSXlk(r27)                        ; Get host pmap search lock address
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+
+                       bt++    pf64Bitb,gthR64                         ; Test for 64-bit machine
                        
-malcfnd1:      stw             r5,mbfree+4(r12)                        ; Actually allocate the slot
-                       addi    r3,r10,32                                       ; Set the correct bit number
-                       b               mapafin                                         ; Exit now...
+gthR32:                li              r3,0                                            ; High-order 32 bits host virtual address
+                       mr              r4,r26                                          ; Low-order  32 bits host virtual address
+gthEpi32:      mtmsr   r29                                                     ; Restore caller's msr image
+                       isync
+                       b               gthEpilog
+
+                       .align  5                       
+gthR64:                srdi    r3,r26,32                                       ; High-order 32 bits host virtual address
+                       clrldi  r4,r26,32                                       ; Low-order  32 bits host virtual address
+gthEpi64:      mtmsrd  r29                                                     ; Restore caller's msr image
+
+gthEpilog:     lwz             r0,(FM_ALIGN(gthStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r24,FM_ARG0+0x1C(r1)            ; Restore non-volatile r24
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+gthBadPLock:
+                       lis             r0,hi16(Choke)                          ; Dmitri, you know how we've always talked about the
+                       ori             r0,r0,lo16(Choke)                       ;  possibility of something going wrong with the bomb?
+                       li              r3,failMapping                          ; The BOMB, Dmitri.
+                       sc                                                                      ; The hydrogen bomb.
+
+
+;
+;                      Guest shadow assist -- find a guest mapping
+;
+;                      Locates the specified guest mapping, and if it exists returns a copy
+;                      of it.
+;
+;                      Parameters:
+;                              r3 : address of guest pmap, 32-bit kernel virtual address
+;                              r4 : guest virtual address, high-order 32 bits
+;                              r5 : guest virtual address,  low-order 32 bits
+;                              r6 : 32 byte copy area, 32-bit kernel virtual address
+;
+;                      Non-volatile register usage:
+;                              r25 : VMM extension block's physical address
+;                              r26 : copy area virtual address
+;                              r27 : host pmap physical address
+;                              r28 : guest pmap physical address
+;                              r29 : caller's msr image from mapSetUp
+;                              r30 : guest virtual address
+;                              r31 : gva->phys mapping's physical address
+;
+
+                       .align  5
+                       .globl  EXT(hw_find_map_gv)
+
+LEXT(hw_find_map_gv)
+
+#define gfmStackSize ((31-25+1)*4)+4
+
+                       stwu    r1,-(FM_ALIGN(gfmStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(gfmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+
+                       rlwinm  r30,r5,0,0xFFFFF000                     ; Clean up low-order 32 bits of guest vaddr
+                       mr              r26,r6                                          ; Copy copy buffer vaddr
+
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+                       lwz             r9,pmapSpace(r3)                        ; r9 <- guest space ID number
+
+                       bt++    pf64Bitb,gfm64Salt                      ; Test for 64-bit machine
+
+                       lwz             r25,pmapVmmExtPhys+4(r3)        ; r25 <- VMM pmap extension block paddr
+                       lwz             r28,pmapvr+4(r3)                        ; Get 32-bit virt<->real guest pmap conversion salt
+                       lwz             r27,vmxHostPmapPhys+4(r11)      ; Get host pmap physical address
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+                       b               gfmStart                                        ; Get to it                     
+
+gfm64Salt:     rldimi  r30,r4,32,0                                     ; Insert high-order 32 bits of 64-bit guest vaddr
+                       ld              r25,pmapVmmExtPhys(r3)          ; r24 <- VMM pmap extension block paddr
+                       ld              r28,pmapvr(r3)                          ; Get 64-bit virt<->real guest pmap conversion salt
+                       ld              r27,vmxHostPmapPhys(r11)        ; Get host pmap physical address
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+
+gfmStart:      xor             r28,r3,r28                                      ; Convert guest pmap_t virt->real
+                       bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, maybe enter 64-bit mode
+                       mr              r29,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exclusive
+
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,gfm64Search            ; Test for 64-bit machine
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       b               gfm32SrchLp                                     ; Let the search begin!
                        
-malcfnd2:      stw             r6,mbfree+8(r12)                        ; Actually allocate the slot
-                       addi    r3,r11,64                                       ; Set the correct bit number
-                       b               mapafin                                         ; Exit now...
+                       .align  5
+gfm32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gfmSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gfm32SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gfmSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       b               gfmSrchMiss                                     ; No joy in our hash group
+                       
+gfm64Search:                   
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       b               gfm64SrchLp                                     ; Let the search begin!
                        
+                       .align  5
+gfm64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gfmSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gfm64SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free and dormant flags
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- !(!free && !dormant && space match)
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       bne             gfmSrchMiss                                     ; No joy in our hash group
+                       
+gfmSrchHit:    lwz             r5,0(r31)                                       ; Fetch 32 bytes of mapping from physical
+                       lwz             r6,4(r31)                                       ;  +4
+                       lwz             r7,8(r31)                                       ;  +8
+                       lwz             r8,12(r31)                                      ;  +12
+                       lwz             r9,16(r31)                                      ;  +16
+                       lwz             r10,20(r31)                                     ;  +20
+                       lwz             r11,24(r31)                                     ;  +24
+                       lwz             r12,28(r31)                                     ;  +28
+                       
+                       li              r31,mapRtOK                                     ; Return found mapping
+
+                       la              r3,pmapSXlk(r27)                        ; Get host pmap search lock address
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+
+                       bt++    pf64Bitb,gfmEpi64                       ; Test for 64-bit machine
+                       
+gfmEpi32:      mtmsr   r29                                                     ; Restore caller's msr image
+                       isync                                                           ; A small wrench
+                       b               gfmEpilog                                       ;  and a larger bubble
+
+                       .align  5                       
+gfmEpi64:      mtmsrd  r29                                                     ; Restore caller's msr image
+
+gfmEpilog:     mr.             r3,r31                                          ; Copy/test mapping address
+                       beq             gfmNotFound                                     ; Skip copy if no mapping found
+                       
+                       stw             r5,0(r26)                                       ; Store 32 bytes of mapping into virtual
+                       stw             r6,4(r26)                                       ;  +4
+                       stw             r7,8(r26)                                       ;  +8
+                       stw             r8,12(r26)                                      ;  +12
+                       stw             r9,16(r26)                                      ;  +16
+                       stw             r10,20(r26)                                     ;  +20
+                       stw             r11,24(r26)                                     ;  +24
+                       stw             r12,28(r26)                                     ;  +28
+                       
+gfmNotFound:
+                       lwz             r0,(FM_ALIGN(gfmStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
+
+                       .align  5                       
+gfmSrchMiss:
+                       li              r31,mapRtNotFnd                         ; Indicate mapping not found
+                       la              r3,pmapSXlk(r27)                        ; Get host pmap search lock address
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+                       bt++    pf64Bitb,gfmEpi64                       ; Take 64-bit exit
+                       b               gfmEpi32                                        ; Take 32-bit exit
 
-/*
- * Log out all memory usage
- */
+
+;
+;                      Guest shadow assist -- change guest page protection
+;
+;                      Locates the specified dormant mapping, and if it is active, changes its
+;                      protection.
+;
+;                      Parameters:
+;                              r3 : address of guest pmap, 32-bit kernel virtual address
+;                              r4 : guest virtual address, high-order 32 bits
+;                              r5 : guest virtual address,  low-order 32 bits
+;                              r6 : guest mapping protection code
+;
+;                      Non-volatile register usage:
+;                              r25 : caller's msr image from mapSetUp
+;                              r26 : guest mapping protection code
+;                              r27 : host pmap physical address
+;                              r28 : guest pmap physical address
+;                              r29 : VMM extension block's physical address
+;                              r30 : guest virtual address
+;                              r31 : gva->phys mapping's physical address
+;
+                       .align  5
+                       .globl  EXT(hw_protect_gv)
+                       
+LEXT(hw_protect_gv)
+
+#define gcpStackSize ((31-24+1)*4)+4
+
+                       stwu    r1,-(FM_ALIGN(gcpStackSize)+FM_SIZE)(r1)
+                                                                                               ; Mint a new stack frame
+                       mflr    r0                                                      ; Get caller's return address
+                       mfsprg  r11,2                                           ; Get feature flags
+                       mtcrf   0x02,r11                                        ; Insert feature flags into cr6
+                       stw             r0,(FM_ALIGN(gcpStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Save caller's return address
+                       stw             r31,FM_ARG0+0x00(r1)            ; Save non-volatile r31
+                       stw             r30,FM_ARG0+0x04(r1)            ; Save non-volatile r30
+                       stw             r29,FM_ARG0+0x08(r1)            ; Save non-volatile r29
+                       stw             r28,FM_ARG0+0x0C(r1)            ; Save non-volatile r28
+                       stw             r27,FM_ARG0+0x10(r1)            ; Save non-volatile r27
+                       stw             r26,FM_ARG0+0x14(r1)            ; Save non-volatile r26
+                       stw             r25,FM_ARG0+0x18(r1)            ; Save non-volatile r25
+
+                       rlwinm  r30,r5,0,0xFFFFF000                     ; Clean up low-order 32 bits of guest vaddr
+                       mr              r26,r6                                          ; Copy guest mapping protection code
+
+                       lwz             r11,pmapVmmExt(r3)                      ; r11 <- VMM pmap extension block vaddr
+                       lwz             r9,pmapSpace(r3)                        ; r9 <- guest space ID number
+                       bt++    pf64Bitb,gcp64Salt                      ; Handle 64-bit machine separately
+                       lwz             r29,pmapVmmExtPhys+4(r3)        ; r29 <- VMM pmap extension block paddr
+                       lwz             r27,vmxHostPmapPhys+4(r11)      ; r27 <- host pmap paddr
+                       lwz             r28,pmapvr+4(r3)                        ; Get 32-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       lwz             r31,4(r31)                                      ; r31 <- hash page paddr
+                       rlwimi  r31,r11,GV_HGRP_SHIFT,GV_HGRP_MASK
+                                                                                               ; r31 <- hash group paddr
+                       b               gcpStart                                        ; Get to it                     
+
+gcp64Salt:     rldimi  r30,r4,32,0                                     ; Insert high-order 32 bits of 64-bit guest vaddr                       
+                       ld              r29,pmapVmmExtPhys(r3)          ; r29 <- VMM pmap extension block paddr
+                       ld              r27,vmxHostPmapPhys(r11)        ; r27 <- host pmap paddr
+                       ld              r28,pmapvr(r3)                          ; Get 64-bit virt<->real guest pmap conversion salt
+                       la              r31,VMX_HPIDX_OFFSET(r11)       ; r31 <- base of hash page physical index
+                       srwi    r11,r30,12                                      ; Form shadow hash:
+                       xor             r11,r11,r9                                      ;       spaceID ^ (vaddr >> 12) 
+                       rlwinm  r10,r11,GV_HPAGE_SHIFT,GV_HPAGE_MASK
+                                                                                               ; Form index offset from hash page number
+                       add             r31,r31,r10                                     ; r31 <- hash page index entry
+                       ld              r31,0(r31)                                      ; r31 <- hash page paddr
+                       insrdi  r31,r11,GV_GRPS_PPG_LG2,64-(GV_HGRP_SHIFT+GV_GRPS_PPG_LG2)
+                                                                                               ; r31 <- hash group paddr
+
+gcpStart:      xor             r28,r4,r28                                      ; Convert guest pmap_t virt->real
+                       bl              EXT(mapSetUp)                           ; Disable 'rupts, translation, maybe enter 64-bit mode
+                       mr              r25,r11                                         ; Save caller's msr image
+
+                       la              r3,pmapSXlk(r27)                        ; r3 <- host pmap's search lock address
+                       bl              sxlkExclusive                           ; Get lock exclusive
+
+                       li              r0,(GV_SLOTS - 1)                       ; Prepare to iterate over mapping slots
+                       mtctr   r0                                                      ;  in this group
+                       bt++    pf64Bitb,gcp64Search            ; Test for 64-bit machine
+
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       lwz             r5,mpVAddr+4(r31)                       ; r5 <- 1st mapping slot's virtual address
+                       b               gcp32SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gcp32SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrwi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       lwz             r5,mpVAddr+4+GV_SLOT_SZ(r31); r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- free || dormant || !space match
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gcpSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gcp32SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrwi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- free || dormant || !space match
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gcpSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       b               gcpSrchMiss                                     ; No joy in our hash group
+                       
+gcp64Search:                   
+                       lwz             r3,mpFlags(r31)                         ; r3 <- 1st mapping slot's flags
+                       lhz             r4,mpSpace(r31)                         ; r4 <- 1st mapping slot's space ID 
+                       ld              r5,mpVAddr(r31)                         ; r5 <- 1st mapping slot's virtual address
+                       b               gcp64SrchLp                                     ; Let the search begin!
+                       
+                       .align  5
+gcp64SrchLp:
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       lwz             r3,mpFlags+GV_SLOT_SZ(r31)      ; r3 <- next mapping slot's flags
+                       mr              r7,r4                                           ; r7 <- current mapping slot's space ID
+                       lhz             r4,mpSpace+GV_SLOT_SZ(r31)      ; r4 <- next mapping slot's space ID
+                       clrrdi  r8,r5,12                                        ; r8 <- current mapping slot's virtual addr w/o flags
+                       ld              r5,mpVAddr+GV_SLOT_SZ(r31)      ; r5 <- next mapping slot's virtual addr
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free flag
+                       xor             r7,r7,r9                                        ; Compare space ID
+                       or              r0,r11,r7                                       ; r0 <- free || dormant || !space match
+                       xor             r8,r8,r30                                       ; Compare virtual address
+                       or.             r0,r0,r8                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       beq             gcpSrchHit                                      ; Join common path on hit (r31 points to guest mapping)
+                       
+                       addi    r31,r31,GV_SLOT_SZ                      ; r31 <- next mapping slot              
+                       bdnz    gcp64SrchLp                                     ; Iterate
+
+                       mr              r6,r3                                           ; r6 <- current mapping slot's flags
+                       clrrdi  r5,r5,12                                        ; Remove flags from virtual address                     
+                       andi.   r11,r6,mpgFree+mpgDormant       ; Isolate guest free flag
+                       xor             r4,r4,r9                                        ; Compare space ID
+                       or              r0,r11,r4                                       ; r0 <- free || dormant || !space match
+                       xor             r5,r5,r30                                       ; Compare virtual address
+                       or.             r0,r0,r5                                        ; cr0_eq <- !free && !dormant && space match && virtual addr match
+                       bne             gcpSrchMiss                                     ; No joy in our hash group
+                       
+gcpSrchHit:
+                       bt++    pf64Bitb,gcpDscon64                     ; Handle 64-bit disconnect separately
+                       bl              mapInvPte32                                     ; Disconnect PTE, invalidate, gather ref and change
+                                                                                               ; r31 <- mapping's physical address
+                                                                                               ; r3  -> PTE slot physical address
+                                                                                               ; r4  -> High-order 32 bits of PTE
+                                                                                               ; r5  -> Low-order  32 bits of PTE
+                                                                                               ; r6  -> PCA
+                                                                                               ; r7  -> PCA physical address
+                       rlwinm  r2,r3,29,29,31                          ; Get PTE's slot number in the PTEG (8-byte PTEs)
+                       b               gcpFreePTE                                      ; Join 64-bit path to release the PTE                   
+gcpDscon64:    bl              mapInvPte64                                     ; Disconnect PTE, invalidate, gather ref and change
+                       rlwinm  r2,r3,28,29,31                          ; Get PTE's slot number in the PTEG (16-byte PTEs)
+gcpFreePTE: mr.                r3,r3                                           ; Was there a valid PTE?
+                       beq-    gcpSetKey                                       ; No valid PTE, we're almost done
+                       lis             r0,0x8000                                       ; Prepare free bit for this slot
+                       srw             r0,r0,r2                                        ; Position free bit
+                       or              r6,r6,r0                                        ; Set it in our PCA image
+                       lwz             r8,mpPte(r31)                           ; Get PTE pointer
+                       rlwinm  r8,r8,0,~mpHValid                       ; Make the pointer invalid
+                       stw             r8,mpPte(r31)                           ; Save invalidated PTE pointer
+                       eieio                                                           ; Synchronize all previous updates (mapInvPtexx didn't)
+                       stw             r6,0(r7)                                        ; Update PCA and unlock the PTEG
+                       
+gcpSetKey:     lwz             r0,mpVAddr+4(r31)                       ; Get va word containing protection bits
+                       rlwimi  r0,r26,0,mpPP                           ; Insert new protection bits
+                       stw             r0,mpVAddr+4(r31)                       ; Write 'em back
+                       eieio                                                           ; Ensure previous mapping updates are visible
+                       li              r31,mapRtOK                                     ; I'm a success
+
+gcpRelPmap:    la              r3,pmapSXlk(r27)                        ; r3 <- host pmap search lock phys addr
+                       bl              sxlkUnlock                                      ; Release host pmap search lock
+                       
+                       mr              r3,r31                                          ; r3 <- result code
+                       bt++    pf64Bitb,gcpRtn64                       ; Handle 64-bit separately
+                       mtmsr   r25                                                     ; Restore 'rupts, translation
+                       isync                                                           ; Throw a small wrench into the pipeline
+                       b               gcpPopFrame                                     ; Nothing to do now but pop a frame and return
+gcpRtn64:      mtmsrd  r25                                                     ; Restore 'rupts, translation, 32-bit mode
+gcpPopFrame:           
+                       lwz             r0,(FM_ALIGN(gcpStackSize)+FM_SIZE+FM_LR_SAVE)(r1)
+                                                                                               ; Get caller's return address
+                       lwz             r31,FM_ARG0+0x00(r1)            ; Restore non-volatile r31
+                       lwz             r30,FM_ARG0+0x04(r1)            ; Restore non-volatile r30
+                       lwz             r29,FM_ARG0+0x08(r1)            ; Restore non-volatile r29
+                       lwz             r28,FM_ARG0+0x0C(r1)            ; Restore non-volatile r28
+                       mtlr    r0                                                      ; Prepare return address
+                       lwz             r27,FM_ARG0+0x10(r1)            ; Restore non-volatile r27
+                       lwz             r26,FM_ARG0+0x14(r1)            ; Restore non-volatile r26
+                       lwz             r25,FM_ARG0+0x18(r1)            ; Restore non-volatile r25
+                       lwz             r1,0(r1)                                        ; Pop stack frame
+                       blr                                                                     ; Return to caller
 
                        .align  5
-                       .globl  EXT(logmem)
+gcpSrchMiss:
+                       li              r31,mapRtNotFnd                         ; Could not locate requested mapping
+                       b               gcpRelPmap                                      ; Exit through host pmap search lock release
 
-LEXT(logmem)
 
-                       mfmsr   r2                                                      ; Get the MSR   
-                       lis             r10,hi16(EXT(DebugWork))                ; High part of area
-                       rlwinm  r2,r2,0,MSR_FP_BIT+1,MSR_FP_BIT-1       ; Force floating point off
-                       lis             r12,hi16(EXT(mem_actual))       ; High part of actual
-                       rlwinm  r2,r2,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1     ; Force vectors off
-                       andi.   r0,r2,0x7FCF                            ; Interrupts and translation off
-                       ori             r10,r10,lo16(EXT(DebugWork))    ; Get the entry
-                       mtmsr   r0                                                      ; Turn stuff off
-                       ori             r12,r12,lo16(EXT(mem_actual))   ; Get the actual
-                       li              r0,1                                            ; Get a one
+;
+;                      Find the physent based on a physical page and try to lock it (but not too hard) 
+;                      Note that this table always has an entry that with a 0 table pointer at the end 
+;                      
+;                      R3 contains ppnum on entry
+;                      R3 is 0 if no entry was found
+;                      R3 is physent if found
+;                      cr0_eq is true if lock was obtained or there was no entry to lock
+;                      cr0_eq is false of there was an entry and it was locked
+;      
+
+                       .align  5
+                       
+mapFindPhyTry: 
+                       lis             r9,hi16(EXT(pmap_mem_regions))          ; Point to the start of the region table
+                       mr              r2,r3                                           ; Save our target
+                       ori             r9,r9,lo16(EXT(pmap_mem_regions))       ; Point to the start of the region table                        
+
+mapFindPhz:    lwz             r3,mrPhysTab(r9)                        ; Get the actual table address
+                       lwz             r5,mrStart(r9)                          ; Get start of table entry
+                       lwz             r0,mrEnd(r9)                            ; Get end of table entry
+                       addi    r9,r9,mrSize                            ; Point to the next slot
+                       cmplwi  cr2,r3,0                                        ; Are we at the end of the table?
+                       cmplw   r2,r5                                           ; See if we are in this table
+                       cmplw   cr1,r2,r0                                       ; Check end also
+                       sub             r4,r2,r5                                        ; Calculate index to physical entry
+                       beq--   cr2,mapFindNo                           ; Leave if we did not find an entry...
+                       cror    cr0_lt,cr0_lt,cr1_gt            ; Set CR0_LT if it is NOT this entry
+                       slwi    r4,r4,3                                         ; Get offset to physical entry
+
+                       blt--   mapFindPhz                                      ; Did not find it...
+                       
+                       add             r3,r3,r4                                        ; Point right to the slot
        
+mapFindOv:     lwz             r2,0(r3)                                        ; Get the lock contents right now
+                       rlwinm. r0,r2,0,0,0                                     ; Is it locked?
+                       bnelr--                                                         ; Yes it is...
+                       
+                       lwarx   r2,0,r3                                         ; Get the lock
+                       rlwinm. r0,r2,0,0,0                                     ; Is it locked?
+                       oris    r0,r2,0x8000                            ; Set the lock bit
+                       bne--   mapFindKl                                       ; It is locked, go get rid of reservation and leave...
+                       stwcx.  r0,0,r3                                         ; Try to stuff it back...
+                       bne--   mapFindOv                                       ; Collision, try again...
+                       isync                                                           ; Clear any speculations
+                       blr                                                                     ; Leave...
+
+mapFindKl:     li              r2,lgKillResv                           ; Killing field
+                       stwcx.  r2,0,r2                                         ; Trash reservation...
+                       crclr   cr0_eq                                          ; Make sure we do not think we got the lock
+                       blr                                                                     ; Leave...
+
+mapFindNo:     crset   cr0_eq                                          ; Make sure that we set this
+                       li              r3,0                                            ; Show that we did not find it
+                       blr                                                                     ; Leave...                      
+;
+;                      pmapCacheLookup - This function will look up an entry in the pmap segment cache.
+;
+;                      How the pmap cache lookup works:
+;
+;                      We use a combination of three things: a mask of valid entries, a sub-tag, and the
+;                      ESID (aka the "tag").  The mask indicates which of the cache slots actually contain
+;                      an entry.  The sub-tag is a 16 entry 4 bit array that contains the low order 4 bits
+;                      of the ESID, bits 32:36 of the effective for 64-bit and 0:3 for 32-bit.  The cache
+;                      entry contains the full 36 bit ESID.
+;
+;                      The purpose of the sub-tag is to limit the number of searches necessary when looking
+;                      for an existing cache entry.  Because there are 16 slots in the cache, we could end up
+;                      searching all 16 if an match is not found.  
+;
+;                      Essentially, we will search only the slots that have a valid entry and whose sub-tag
+;                      matches. More than likely, we will eliminate almost all of the searches.
+;              
+;                      Inputs:
+;                              R3 = pmap
+;                              R4 = ESID high half
+;                              R5 = ESID low half
+;
+;                      Outputs:
+;                              R3 = pmap cache slot if found, 0 if not
+;                              R10 = pmapCCtl address
+;                              R11 = pmapCCtl image
+;                              pmapCCtl locked on exit
+;
+
+                       .align  5
+
+pmapCacheLookup:               
+                       la              r10,pmapCCtl(r3)                        ; Point to the segment cache control
+
+pmapCacheLookuq:               
+                       lwarx   r11,0,r10                                       ; Get the segment cache control value
+                       rlwinm. r0,r11,0,pmapCCtlLckb,pmapCCtlLckb      ; Is it already locked?
+                       ori             r0,r11,lo16(pmapCCtlLck)        ; Turn on the lock bit
+                       bne--   pmapCacheLookur                         ; Nope...
+                       stwcx.  r0,0,r10                                        ; Try to take the lock
+                       bne--   pmapCacheLookuq                         ; Someone else just stuffed it, try again...
+
+                       isync                                                           ; Make sure we get reservation first
+                       lwz             r9,pmapSCSubTag(r3)                     ; Get the high part of the sub-tag
+                       rlwimi  r5,r5,28,4,7                            ; Copy sub-tag just to right of itself (XX------)
+                       lwz             r10,pmapSCSubTag+4(r3)          ; And the bottom half
+                       rlwimi  r5,r5,24,8,15                           ; Copy doubled sub-tag to right of itself (XXXX----)
+                       lis             r8,0x8888                                       ; Get some eights
+                       rlwimi  r5,r5,16,16,31                          ; Copy quadrupled sub-tags to the right
+                       ori             r8,r8,0x8888                            ; Fill the rest with eights
+
+                       eqv             r10,r10,r5                                      ; Get 0xF where we hit in bottom half
+                       eqv             r9,r9,r5                                        ; Get 0xF where we hit in top half
+                       
+                       rlwinm  r2,r10,1,0,30                           ; Shift over 1
+                       rlwinm  r0,r9,1,0,30                            ; Shift over 1
+                       and             r2,r2,r10                                       ; AND the even/odd pair into the even
+                       and             r0,r0,r9                                        ; AND the even/odd pair into the even
+                       rlwinm  r10,r2,2,0,28                           ; Shift over 2
+                       rlwinm  r9,r0,2,0,28                            ; Shift over 2
+                       and             r10,r2,r10                                      ; AND the even of the ANDed pairs giving the AND of all 4 bits in 0, 4, ...
+                       and             r9,r0,r9                                        ; AND the even of the ANDed pairs giving the AND of all 4 bits in 0, 4, ...
+                       
+                       and             r10,r10,r8                                      ; Clear out extras
+                       and             r9,r9,r8                                        ; Clear out extras
+                       
+                       rlwinm  r0,r10,3,1,28                           ; Slide adjacent next to each other
+                       rlwinm  r2,r9,3,1,28                            ; Slide adjacent next to each other
+                       or              r10,r0,r10                                      ; Merge them
+                       or              r9,r2,r9                                        ; Merge them
+                       rlwinm  r0,r10,6,2,26                           ; Slide adjacent pairs next to each other
+                       rlwinm  r2,r9,6,2,26                            ; Slide adjacent pairs next to each other
+                       or              r10,r0,r10                                      ; Merge them
+                       or              r9,r2,r9                                        ; Merge them
+                       rlwimi  r10,r10,12,4,7                          ; Stick in the low-order adjacent quad
+                       rlwimi  r9,r9,12,4,7                            ; Stick in the low-order adjacent quad
+                       not             r6,r11                                          ; Turn invalid into valid
+                       rlwimi  r9,r10,24,8,15                          ; Merge in the adjacent octs giving a hit mask
+                       
+                       la              r10,pmapSegCache(r3)            ; Point at the cache slots
+                       and.    r6,r9,r6                                        ; Get mask of valid and hit
+                       li              r0,0                                            ; Clear
+                       li              r3,0                                            ; Assume not found
+                       oris    r0,r0,0x8000                            ; Start a mask
+                       beqlr++                                                         ; Leave, should usually be no hits...
+                       
+pclNextEnt:    cntlzw  r5,r6                                           ; Find an in use one
+                       cmplwi  cr1,r5,pmapSegCacheUse          ; Did we find one?
+                       rlwinm  r7,r5,4,0,27                            ; Index to the cache entry
+                       srw             r2,r0,r5                                        ; Get validity mask bit
+                       add             r7,r7,r10                                       ; Point to the cache slot
+                       andc    r6,r6,r2                                        ; Clear the validity bit we just tried
+                       bgelr-- cr1                                                     ; Leave if there are no more to check...
+                       
+                       lwz             r5,sgcESID(r7)                          ; Get the top half
+                       
+                       cmplw   r5,r4                                           ; Only need to check top because sub-tag is the entire other half
+                       
+                       bne++   pclNextEnt                                      ; Nope, try again...
+
+                       mr              r3,r7                                           ; Point to the slot
+                       blr                                                                     ; Leave....
+
+                       .align  5
+
+pmapCacheLookur:
+                       li              r11,lgKillResv                          ; The killing spot
+                       stwcx.  r11,0,r11                                       ; Kill the reservation
+                       
+pmapCacheLookus:               
+                       lwz             r11,pmapCCtl(r3)                        ; Get the segment cache control
+                       rlwinm. r0,r11,0,pmapCCtlLckb,pmapCCtlLckb      ; Is it already locked?
+                       beq++   pmapCacheLookup                         ; Nope...
+                       b               pmapCacheLookus                         ; Yup, keep waiting...
+
+
+;
+;                      mapMergeRC -- Given a physical mapping address in R31, locate its
+;           connected PTE (if any) and merge the PTE referenced and changed bits
+;                      into the mapping and physent.
+;
+
+                       .align  5
+                       
+mapMergeRC32:
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset
+                       mfsdr1  r7                                                      ; Get the pointer to the hash table
+                       lwz             r5,mpVAddr+4(r31)                       ; Grab the virtual address
+                       rlwinm  r10,r7,0,0,15                           ; Clean up the hash table base
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       srwi    r7,r0,4                                         ; Convert to PCA units
+                       rlwinm  r7,r7,0,0,29                            ; Clean up PCA offset
+                       mflr    r2                                                      ; Save the return
+                       subfic  r7,r7,-4                                        ; Convert to -4 based negative index
+                       add             r7,r10,r7                                       ; Point to the PCA directly
+                       beqlr--                                                         ; There was no PTE to start with...
+                       
+                       bl              mapLockPteg                                     ; Lock the PTEG
+
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset
+                       mtlr    r2                                                      ; Restore the LR
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       beq-    mMPUnlock                                       ; There is no PTE, someone took it so just unlock and leave...
+
+                       rlwinm  r3,r0,0,0,30                            ; Clear the valid bit
+                       add             r3,r3,r10                                       ; Point to actual PTE
+                       lwz             r5,4(r3)                                        ; Get the real part of the PTE
+                       srwi    r10,r5,12                                       ; Change physical address to a ppnum
+
+mMNmerge:      lbz             r11,mpFlags+1(r31)                      ; Get the offset to the physical entry table
+                       lwz             r0,mpVAddr+4(r31)                       ; Get the flags part of the field
+                       lis             r8,hi16(EXT(pmap_mem_regions))  ; Get the top of the region table
+                       ori             r8,r8,lo16(EXT(pmap_mem_regions))       ; Get the bottom of the region table
+                       rlwinm  r11,r11,2,24,29                         ; Mask index bits and convert to byte offset
+                       add             r11,r11,r8                                      ; Point to the bank table
+                       lwz             r2,mrPhysTab(r11)                       ; Get the physical table bank pointer
+                       lwz             r11,mrStart(r11)                        ; Get the start of bank
+                       rlwimi  r0,r5,0,mpRb-32,mpCb-32         ; Copy in the RC
+                       addi    r2,r2,4                                         ; Offset to last half of field
+                       stw             r0,mpVAddr+4(r31)                       ; Set the new RC into the field
+                       sub             r11,r10,r11                                     ; Get the index into the table
+                       rlwinm  r11,r11,3,0,28                          ; Get offset to the physent
+
+mMmrgRC:       lwarx   r10,r11,r2                                      ; Get the master RC
+                       rlwinm  r0,r5,27,ppRb-32,ppCb-32        ; Position the new RC
+                       or              r0,r0,r10                                       ; Merge in the new RC
+                       stwcx.  r0,r11,r2                                       ; Try to stick it back
+                       bne--   mMmrgRC                                         ; Try again if we collided...
+                       eieio                                                           ; Commit all updates
+
+mMPUnlock:                             
+                       stw             r6,0(r7)                                        ; Unlock PTEG
+                       blr                                                                     ; Return
+
+;
+;                      64-bit version of mapMergeRC
+;
+                       .align  5
+
+mapMergeRC64:
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset
+                       ld              r5,mpVAddr(r31)                         ; Grab the virtual address
+                       mfsdr1  r7                                                      ; Get the pointer to the hash table
+                       rldicr  r10,r7,0,45                                     ; Clean up the hash table base
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       srdi    r7,r0,5                                         ; Convert to PCA units
+                       rldicr  r7,r7,0,61                                      ; Clean up PCA
+                       subfic  r7,r7,-4                                        ; Convert to -4 based negative index
+                       mflr    r2                                                      ; Save the return
+                       add             r7,r10,r7                                       ; Point to the PCA directly
+                       beqlr--                                                         ; There was no PTE to start with...
+                       
+                       bl              mapLockPteg                                     ; Lock the PTEG
+                       
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset again
+                       mtlr    r2                                                      ; Restore the LR
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       beq--   mMPUnlock                                       ; There is no PTE, someone took it so just unlock and leave...
+
+                       rlwinm  r3,r0,0,0,30                            ; Clear the valid bit
+                       add             r3,r3,r10                                       ; Point to the actual PTE
+                       ld              r5,8(r3)                                        ; Get the real part
+                       srdi    r10,r5,12                                       ; Change physical address to a ppnum
+                       b               mMNmerge                                        ; Join the common 32-64-bit code...
+
+
+;
+;                      This routine, given a mapping, will find and lock the PTEG
+;                      If mpPte does not point to a PTE (checked before and after lock), it will unlock the
+;                      PTEG and return.  In this case we will have undefined in R4
+;                      and the low 12 bits of mpVAddr valid in R5.  R3 will contain 0.
+;
+;                      If the mapping is still valid, we will invalidate the PTE and merge
+;                      the RC bits into the physent and also save them into the mapping.
+;
+;                      We then return with R3 pointing to the PTE slot, R4 is the
+;                      top of the PTE and R5 is the bottom.  R6 contains the PCA.
+;                      R7 points to the PCA entry.
+;
+;                      Note that we should NEVER be called on a block or special mapping.
+;                      We could do many bad things.
+;
+
+                       .align  5
+
+mapInvPte32:
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset
+                       mfsdr1  r7                                                      ; Get the pointer to the hash table
+                       lwz             r5,mpVAddr+4(r31)                       ; Grab the virtual address
+                       rlwinm  r10,r7,0,0,15                           ; Clean up the hash table base
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       srwi    r7,r0,4                                         ; Convert to PCA units
+                       rlwinm  r7,r7,0,0,29                            ; Clean up PCA offset
+                       mflr    r2                                                      ; Save the return
+                       subfic  r7,r7,-4                                        ; Convert to -4 based negative index
+                       add             r7,r10,r7                                       ; Point to the PCA directly
+                       beqlr--                                                         ; There was no PTE to start with...
+                       
+                       bl              mapLockPteg                                     ; Lock the PTEG
+
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset
+                       mtlr    r2                                                      ; Restore the LR
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       beq-    mIPUnlock                                       ; There is no PTE, someone took it so just unlock and leave...
+
+                       rlwinm  r3,r0,0,0,30                            ; Clear the valid bit
+                       add             r3,r3,r10                                       ; Point to actual PTE
+                       lwz             r4,0(r3)                                        ; Get the top of the PTE
+                       
+                       li              r8,tlbieLock                            ; Get the TLBIE lock
+                       rlwinm  r0,r4,0,1,31                            ; Clear the valid bit
+                       stw             r0,0(r3)                                        ; Invalidate the PTE
+
+                       sync                                                            ; Make sure everyone sees the invalidate
+                       
+mITLBIE32:     lwarx   r0,0,r8                                         ; Get the TLBIE lock 
+                       mfsprg  r2,2                                            ; Get feature flags 
+                       mr.             r0,r0                                           ; Is it locked? 
+                       li              r0,1                                            ; Get our lock word 
+                       bne-    mITLBIE32                                       ; It is locked, go wait...
+                       
+                       stwcx.  r0,0,r8                                         ; Try to get it
+                       bne-    mITLBIE32                                       ; We was beat...
+                       
+                       rlwinm. r0,r2,0,pfSMPcapb,pfSMPcapb     ; Can this be an MP box?
+                       li              r0,0                                            ; Lock clear value 
+
+                       tlbie   r5                                                      ; Invalidate it everywhere 
+                       
+                       beq-    mINoTS32                                        ; Can not have MP on this machine...
+                       
+                       eieio                                                           ; Make sure that the tlbie happens first 
+                       tlbsync                                                         ; Wait for everyone to catch up 
+                       sync                                                            ; Make sure of it all
+                       
+mINoTS32:      stw             r0,tlbieLock(0)                         ; Clear the tlbie lock
+                       lwz             r5,4(r3)                                        ; Get the real part
+                       srwi    r10,r5,12                                       ; Change physical address to a ppnum
+
+mINmerge:      lbz             r11,mpFlags+1(r31)                      ; Get the offset to the physical entry table
+                       lwz             r0,mpVAddr+4(r31)                       ; Get the flags part of the field
+                       lis             r8,hi16(EXT(pmap_mem_regions))  ; Get the top of the region table
+                       ori             r8,r8,lo16(EXT(pmap_mem_regions))       ; Get the bottom of the region table
+                       rlwinm  r11,r11,2,24,29                         ; Mask index bits and convert to byte offset
+                       add             r11,r11,r8                                      ; Point to the bank table
+                       lwz             r2,mrPhysTab(r11)                       ; Get the physical table bank pointer
+                       lwz             r11,mrStart(r11)                        ; Get the start of bank
+                       rlwimi  r0,r5,0,mpRb-32,mpCb-32         ; Copy in the RC
+                       addi    r2,r2,4                                         ; Offset to last half of field
+                       stw             r0,mpVAddr+4(r31)                       ; Set the new RC into the field
+                       sub             r11,r10,r11                                     ; Get the index into the table
+                       rlwinm  r11,r11,3,0,28                          ; Get offset to the physent
+
+
+mImrgRC:       lwarx   r10,r11,r2                                      ; Get the master RC
+                       rlwinm  r0,r5,27,ppRb-32,ppCb-32        ; Position the new RC
+                       or              r0,r0,r10                                       ; Merge in the new RC
+                       stwcx.  r0,r11,r2                                       ; Try to stick it back
+                       bne--   mImrgRC                                         ; Try again if we collided...
+                       
+                       blr                                                                     ; Leave with the PCA still locked up...
+
+mIPUnlock:     eieio                                                           ; Make sure all updates come first
+                               
+                       stw             r6,0(r7)                                        ; Unlock
+                       blr
+
+;
+;                      64-bit version
+;
+                       .align  5
+
+mapInvPte64:
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset
+                       ld              r5,mpVAddr(r31)                         ; Grab the virtual address
+                       mfsdr1  r7                                                      ; Get the pointer to the hash table
+                       rldicr  r10,r7,0,45                                     ; Clean up the hash table base
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       srdi    r7,r0,5                                         ; Convert to PCA units
+                       rldicr  r7,r7,0,61                                      ; Clean up PCA
+                       subfic  r7,r7,-4                                        ; Convert to -4 based negative index
+                       mflr    r2                                                      ; Save the return
+                       add             r7,r10,r7                                       ; Point to the PCA directly
+                       beqlr--                                                         ; There was no PTE to start with...
+                       
+                       bl              mapLockPteg                                     ; Lock the PTEG
+                       
+                       lwz             r0,mpPte(r31)                           ; Grab the PTE offset again
+                       mtlr    r2                                                      ; Restore the LR
+                       andi.   r3,r0,mpHValid                          ; Is there a possible PTE?
+                       beq--   mIPUnlock                                       ; There is no PTE, someone took it so just unlock and leave...
+
+                       rlwinm  r3,r0,0,0,30                            ; Clear the valid bit
+                       add             r3,r3,r10                                       ; Point to the actual PTE
+                       ld              r4,0(r3)                                        ; Get the top of the PTE
+
+                       li              r8,tlbieLock                            ; Get the TLBIE lock
+                       rldicr  r0,r4,0,62                                      ; Clear the valid bit
+                       std             r0,0(r3)                                        ; Invalidate the PTE
+                       
+                       rldicr  r2,r4,16,35                                     ; Shift the AVPN over to match VPN
+                       sync                                                            ; Make sure everyone sees the invalidate
+                       rldimi  r2,r5,0,36                                      ; Cram in the page portion of the EA
+                       
+mITLBIE64:     lwarx   r0,0,r8                                         ; Get the TLBIE lock 
+                       mr.             r0,r0                                           ; Is it locked? 
+                       li              r0,1                                            ; Get our lock word 
+                       bne--   mITLBIE64a                                      ; It is locked, toss reservation and wait...
+                       
+                       stwcx.  r0,0,r8                                         ; Try to get it
+                       bne--   mITLBIE64                                       ; We was beat...
+
+                       rldicl  r2,r2,0,16                                      ; Clear bits 0:15 because we are under orders
+                       
+                       li              r0,0                                            ; Lock clear value 
+
+                       tlbie   r2                                                      ; Invalidate it everywhere 
+
+                       eieio                                                           ; Make sure that the tlbie happens first 
+                       tlbsync                                                         ; Wait for everyone to catch up 
+                       ptesync                                                         ; Wait for quiet again
+
+                       stw             r0,tlbieLock(0)                         ; Clear the tlbie lock
+
+                       ld              r5,8(r3)                                        ; Get the real part
+                       srdi    r10,r5,12                                       ; Change physical address to a ppnum
+                       b               mINmerge                                        ; Join the common 32-64-bit code...
+
+mITLBIE64a:    li              r5,lgKillResv                           ; Killing field
+                       stwcx.  r5,0,r5                                         ; Kill reservation
+                       
+mITLBIE64b:    lwz             r0,0(r8)                                        ; Get the TLBIE lock
+                       mr.             r0,r0                                           ; Is it locked?
+                       beq++   mITLBIE64                                       ; Nope, try again...
+                       b               mITLBIE64b                                      ; Yup, wait for it...
+
+;
+;                      mapLockPteg - Locks a PTEG
+;                      R7 points to PCA entry
+;                      R6 contains PCA on return
+;
+;
+
+                       .align  5
+                       
+mapLockPteg:
+                       lwarx   r6,0,r7                                         ; Pick up the PCA
+                       rlwinm. r0,r6,0,PCAlockb,PCAlockb       ; Is the PTEG locked?
+                       ori             r0,r6,PCAlock                           ; Set the lock bit
+                       bne--   mLSkill                                         ; It is locked...
+                       
+                       stwcx.  r0,0,r7                                         ; Try to lock the PTEG
+                       bne--   mapLockPteg                                     ; We collided...
+                       
+                       isync                                                           ; Nostradamus lied
+                       blr                                                                     ; Leave...
+                               
+mLSkill:       li              r6,lgKillResv                           ; Get killing field
+                       stwcx.  r6,0,r6                                         ; Kill it
+
+mapLockPteh:
+                       lwz             r6,0(r7)                                        ; Pick up the PCA
+                       rlwinm. r0,r6,0,PCAlockb,PCAlockb       ; Is the PTEG locked?
+                       beq++   mapLockPteg                                     ; Nope, try again...
+                       b               mapLockPteh                                     ; Yes, wait for it...
+                       
+
+;
+;                      The mapSelSlot function selects a PTEG slot to use. As input, it expects R6 
+;                      to contain the PCA.  When it returns, R3 contains 0 if an unoccupied slot was
+;                      selected, 1 if it stole a non-block PTE, or 2 if it stole a block mapped PTE.
+;                      R4 returns the slot index.
+;
+;                      CR7 also indicates that we have a block mapping
+;
+;                      The PTEG allocation controls are a bit map of the state of the PTEG. 
+;                      PCAfree indicates that the PTE slot is empty. 
+;                      PCAauto means that it comes from an autogen area.  These
+;                      guys do not keep track of reference and change and are actually "wired".
+;                      They are easy to maintain. PCAsteal
+;                      is a sliding position mask used to "randomize" PTE slot stealing.  All 4 of these
+;                      fields fit in a single word and are loaded and stored under control of the
+;                      PTEG control area lock (PCAlock).
+;
+;                      Note that PCAauto does not contribute to the steal calculations at all.  Originally
+;                      it did, autogens were second in priority.  This can result in a pathalogical
+;                      case where an instruction can not make forward progress, or one PTE slot
+;                      thrashes.
+;
+;                      Note that the PCA must be locked when we get here.
+;
+;                      Physically, the fields are arranged:
+;                              0: PCAfree
+;                              1: PCAsteal
+;                              2: PCAauto
+;                              3: PCAmisc
+;                              
+;
+;                      At entry, R6 contains new unlocked PCA image (real PCA is locked and untouched)
+;
+;                      At exit:
+;
+;                      R3 = 0 - no steal
+;                      R3 = 1 - steal regular
+;                      R3 = 2 - steal autogen
+;                      R4 contains slot number
+;                      R6 contains updated PCA image
+;
+
+                       .align  5
+                       
+mapSelSlot:    lis             r10,0                                           ; Clear autogen mask
+                       li              r9,0                                            ; Start a mask
+                       beq             cr7,mSSnotblk                           ; Skip if this is not a block mapping
+                       ori             r10,r10,lo16(0xFFFF)            ; Make sure we mark a block mapping (autogen)
+
+mSSnotblk:     rlwinm  r11,r6,16,24,31                         ; Isolate just the steal mask
+                       oris    r9,r9,0x8000                            ; Get a mask
+                       cntlzw  r4,r6                                           ; Find a slot or steal one
+                       ori             r9,r9,lo16(0x8000)                      ; Insure that we have 0x80008000
+                       rlwinm  r4,r4,0,29,31                           ; Isolate bit position
+                       rlwimi  r11,r11,8,16,23                         ; Get set to march a 1 back into top of 8 bit rotate
+                       srw             r2,r9,r4                                        ; Get mask to isolate selected inuse and autogen flags
+                       srwi    r11,r11,1                                       ; Slide steal mask right
+                       and             r8,r6,r2                                        ; Isolate the old in use and autogen bits
+                       andc    r6,r6,r2                                        ; Allocate the slot and also clear autogen flag
+                       addi    r0,r8,0x7F00                            ; Push autogen flag to bit 16
+                       and             r2,r2,r10                                       ; Keep the autogen part if autogen
+                       addis   r8,r8,0xFF00                            ; Push in use to bit 0 and invert
+                       or              r6,r6,r2                                        ; Add in the new autogen bit 
+                       rlwinm  r0,r0,17,31,31                          ; Get a 1 if the old was autogenned (always 0 if not in use)
+                       rlwinm  r8,r8,1,31,31                           ; Isolate old in use
+                       rlwimi  r6,r11,16,8,15                          ; Stick the new steal slot in
+
+                       add             r3,r0,r8                                        ; Get 0 if no steal, 1 if steal normal, 2 if steal autogen                      
+                       blr                                                                     ; Leave...
+                       
+;
+;                      Shared/Exclusive locks
+;
+;                      A shared/exclusive lock allows multiple shares of a lock to be taken
+;                      but only one exclusive.  A shared lock can be "promoted" to exclusive
+;                      when it is the only share.  If there are multiple sharers, the lock
+;                      must be "converted".  A promotion drops the share and gains exclusive as
+;                      an atomic operation.  If anyone else has a share, the operation fails.
+;                      A conversion first drops the share and then takes an exclusive lock.
+;
+;                      We will want to add a timeout to this eventually.
+;
+;                      R3 is set to 0 for success, non-zero for failure
+;
+
+;
+;                      Convert a share into an exclusive
+;
+
+                       .align  5
+                       
+sxlkConvert:
+
+                       lis             r0,0x8000                                       ; Get the locked lock image
+#if 0
+                       mflr    r0                                                      ; (TEST/DEBUG)
+                       oris    r0,r0,0x8000                            ; (TEST/DEBUG)
+#endif
+               
+sxlkCTry:      lwarx   r2,0,r3                                         ; Get the lock word
+                       cmplwi  r2,1                                            ; Does it just have our share?
+                       subi    r2,r2,1                                         ; Drop our share in case we do not get it
+                       bne--   sxlkCnotfree                            ; No, we need to unlock...
+                       stwcx.  r0,0,r3                                         ; Try to take it exclusively
+                       bne--   sxlkCTry                                        ; Collision, try again...
+                       
+                       isync
+                       li              r3,0                                            ; Set RC
+                       blr                                                                     ; Leave...
+
+sxlkCnotfree:
+                       stwcx.  r2,0,r3                                         ; Try to drop our share...      
+                       bne--   sxlkCTry                                        ; Try again if we collided...
+                       b               sxlkExclusive                           ; Go take it exclusively...
+
+;
+;                      Promote shared to exclusive
+;
+
+                       .align  5
+                       
+sxlkPromote:
+                       lis             r0,0x8000                                       ; Get the locked lock image
+#if 0
+                       mflr    r0                                                      ; (TEST/DEBUG)
+                       oris    r0,r0,0x8000                            ; (TEST/DEBUG)
+#endif
+               
+sxlkPTry:      lwarx   r2,0,r3                                         ; Get the lock word
+                       cmplwi  r2,1                                            ; Does it just have our share?
+                       bne--   sxlkPkill                                       ; No, just fail (R3 is non-zero)...
+                       stwcx.  r0,0,r3                                         ; Try to take it exclusively
+                       bne--   sxlkPTry                                        ; Collision, try again...
+                       
+                       isync
+                       li              r3,0                                            ; Set RC
+                       blr                                                                     ; Leave...
+
+sxlkPkill:     li              r2,lgKillResv                           ; Point to killing field
+                       stwcx.  r2,0,r2                                         ; Kill reservation
+                       blr                                                                     ; Leave
+
+
+
+;
+;                      Take lock exclusivily
+;
+
+                       .align  5
+                       
+sxlkExclusive:
+                       lis             r0,0x8000                                       ; Get the locked lock image
+#if 0
+                       mflr    r0                                                      ; (TEST/DEBUG)
+                       oris    r0,r0,0x8000                            ; (TEST/DEBUG)
+#endif
+               
+sxlkXTry:      lwarx   r2,0,r3                                         ; Get the lock word
+                       mr.             r2,r2                                           ; Is it locked?
+                       bne--   sxlkXWait                                       ; Yes...
+                       stwcx.  r0,0,r3                                         ; Try to take it
+                       bne--   sxlkXTry                                        ; Collision, try again...
+                       
+                       isync                                                           ; Toss anything younger than us
+                       li              r3,0                                            ; Set RC
+                       blr                                                                     ; Leave...
+                       
+                       .align  5
+
+sxlkXWait:     li              r2,lgKillResv                           ; Point to killing field
+                       stwcx.  r2,0,r2                                         ; Kill reservation
+                       
+sxlkXWaiu:     lwz             r2,0(r3)                                        ; Get the lock again
+                       mr.             r2,r2                                           ; Is it free yet?
+                       beq++   sxlkXTry                                        ; Yup...
+                       b               sxlkXWaiu                                       ; Hang around a bit more...
+
+;
+;                      Take a share of the lock
+;
+
+                       .align  5
+                       
+sxlkShared:    lwarx   r2,0,r3                                         ; Get the lock word
+                       rlwinm. r0,r2,0,0,0                                     ; Is it locked exclusively?
+                       addi    r2,r2,1                                         ; Up the share count
+                       bne--   sxlkSWait                                       ; Yes...
+                       stwcx.  r2,0,r3                                         ; Try to take it
+                       bne--   sxlkShared                                      ; Collision, try again...
+                       
+                       isync                                                           ; Toss anything younger than us
+                       li              r3,0                                            ; Set RC
+                       blr                                                                     ; Leave...
+                       
+                       .align  5
+
+sxlkSWait:     li              r2,lgKillResv                           ; Point to killing field
+                       stwcx.  r2,0,r2                                         ; Kill reservation
+
+sxlkSWaiu:     lwz             r2,0(r3)                                        ; Get the lock again
+                       rlwinm. r0,r2,0,0,0                                     ; Is it locked exclusively?
+                       beq++   sxlkShared                                      ; Nope...
+                       b               sxlkSWaiu                                       ; Hang around a bit more...
+
+;
+;                      Unlock either exclusive or shared.
+;
+
+                       .align  5
+                       
+sxlkUnlock:    eieio                                                           ; Make sure we order our stores out
+               
+sxlkUnTry:     lwarx   r2,0,r3                                         ; Get the lock
+                       rlwinm. r0,r2,0,0,0                                     ; Do we hold it exclusively?
+                       subi    r2,r2,1                                         ; Remove our share if we have one
+                       li              r0,0                                            ; Clear this
+                       bne--   sxlkUExclu                                      ; We hold exclusive...
+                       
+                       stwcx.  r2,0,r3                                         ; Try to lose our share
+                       bne--   sxlkUnTry                                       ; Collision...
+                       blr                                                                     ; Leave...
+                       
+sxlkUExclu:    stwcx.  r0,0,r3                                         ; Unlock and release reservation
+                       beqlr++                                                         ; Leave if ok...
+                       b               sxlkUnTry                                       ; Could not store, try over...  
+                       
+
+                       .align  5
+                       .globl  EXT(fillPage)
+
+LEXT(fillPage)
+
+                       mfsprg  r0,2                                            ; Get feature flags 
+                       mtcrf   0x02,r0                                         ; move pf64Bit to cr
+
+                       rlwinm  r4,r4,0,1,0                                     ; Copy fill to top of 64-bit register
+                       lis             r2,0x0200                                       ; Get vec
+                       mr              r6,r4                                           ; Copy
+                       ori             r2,r2,0x2000                            ; Get FP
+                       mr              r7,r4                                           ; Copy
+                       mfmsr   r5                                                      ; Get MSR
+                       mr              r8,r4                                           ; Copy
+                       andc    r5,r5,r2                                        ; Clear out permanent turn-offs
+                       mr              r9,r4                                           ; Copy
+                       ori             r2,r2,0x8030                            ; Clear IR, DR and EE
+                       mr              r10,r4                                          ; Copy
+                       andc    r0,r5,r2                                        ; Kill them
+                       mr              r11,r4                                          ; Copy
+                       mr              r12,r4                                          ; Copy
+                       bt++    pf64Bitb,fpSF1                          ; skip if 64-bit (only they take the hint)
+                       
+                       slwi    r3,r3,12                                        ; Make into a physical address
+                       mtmsr   r2                                                      ; Interrupts and translation off
+                       isync
+                       
+                       li              r2,4096/32                                      ; Get number of cache lines
+                       
+fp32again:     dcbz    0,r3                                            ; Clear
+                       addic.  r2,r2,-1                                        ; Count down
+                       stw             r4,0(r3)                                        ; Fill
+                       stw             r6,4(r3)                                        ; Fill
+                       stw             r7,8(r3)                                        ; Fill
+                       stw             r8,12(r3)                                       ; Fill
+                       stw             r9,16(r3)                                       ; Fill
+                       stw             r10,20(r3)                                      ; Fill
+                       stw             r11,24(r3)                                      ; Fill
+                       stw             r12,28(r3)                                      ; Fill
+                       addi    r3,r3,32                                        ; Point next
+                       bgt+    fp32again                                       ; Keep going
+
+                       mtmsr   r5                                                      ; Restore all
                        isync
+                       blr                                                                     ; Return...
+                       
+                       .align  5
+                       
+fpSF1:         li              r2,1
+                       sldi    r2,r2,63                                        ; Get 64-bit bit
+                       or              r0,r0,r2                                        ; Turn on 64-bit
+                       sldi    r3,r3,12                                        ; Make into a physical address
 
-                       stw             r0,4(r10)                                       ; Force logging off
-                       lwz             r0,0(r12)                                       ; Get the end of memory
-                       
-                       lis             r12,hi16(EXT(mem_size))         ; High part of defined memory
-                       ori             r12,r12,lo16(EXT(mem_size))     ; Low part of defined memory
-                       lwz             r12,0(r12)                                      ; Make it end of defined
-                       
-                       cmplw   r0,r12                                          ; Is there room for the data?
-                       ble-    logmemexit                                      ; No, do not even try...
-
-                       stw             r12,0(r12)                                      ; Set defined memory size
-                       stw             r0,4(r12)                                       ; Set the actual amount of memory
-                       
-                       lis             r3,hi16(EXT(hash_table_base))   ; Hash table address
-                       lis             r4,hi16(EXT(hash_table_size))   ; Hash table size
-                       lis             r5,hi16(EXT(pmap_mem_regions))  ; Memory regions
-                       lis             r6,hi16(EXT(mapCtl))            ; Mappings
-                       ori             r3,r3,lo16(EXT(hash_table_base))        
-                       ori             r4,r4,lo16(EXT(hash_table_size))        
-                       ori             r5,r5,lo16(EXT(pmap_mem_regions))       
-                       ori             r6,r6,lo16(EXT(mapCtl)) 
-                       lwz             r3,0(r3)
-                       lwz             r4,0(r4)
-                       lwz             r5,4(r5)                                        ; Get the pointer to the phys_ent table
-                       lwz             r6,0(r6)                                        ; Get the pointer to the current mapping block
-                       stw             r3,8(r12)                                       ; Save the hash table address
-                       stw             r4,12(r12)                                      ; Save the hash table size
-                       stw             r5,16(r12)                                      ; Save the physent pointer
-                       stw             r6,20(r12)                                      ; Save the mappings
-                       
-                       addi    r11,r12,0x1000                          ; Point to area to move hash table and PCA
-                       
-                       add             r4,r4,r4                                        ; Double size for both
-                       
-copyhash:      lwz             r7,0(r3)                                        ; Copy both of them
-                       lwz             r8,4(r3)
-                       lwz             r9,8(r3)
-                       lwz             r10,12(r3)
-                       subic.  r4,r4,0x10
-                       addi    r3,r3,0x10
-                       stw             r7,0(r11)
-                       stw             r8,4(r11)
-                       stw             r9,8(r11)
-                       stw             r10,12(r11)
-                       addi    r11,r11,0x10
-                       bgt+    copyhash
-                       
-                       rlwinm  r4,r12,20,12,31                         ; Get number of phys_ents
-
-copyphys:      lwz             r7,0(r5)                                        ; Copy physents
-                       lwz             r8,4(r5)
-                       subic.  r4,r4,1
-                       addi    r5,r5,8
-                       stw             r7,0(r11)
-                       stw             r8,4(r11)
-                       addi    r11,r11,8
-                       bgt+    copyphys
-                       
-                       addi    r11,r11,4095                            ; Round up to next page
-                       rlwinm  r11,r11,0,0,19
-
-                       lwz             r4,4(r6)                                        ; Get the size of the mapping area
-                       
-copymaps:      lwz             r7,0(r6)                                        ; Copy the mappings
-                       lwz             r8,4(r6)
-                       lwz             r9,8(r6)
-                       lwz             r10,12(r6)
-                       subic.  r4,r4,0x10
-                       addi    r6,r6,0x10
-                       stw             r7,0(r11)
-                       stw             r8,4(r11)
-                       stw             r9,8(r11)
-                       stw             r10,12(r11)
-                       addi    r11,r11,0x10
-                       bgt+    copymaps
-
-                       sub             r11,r11,r12                                     ; Get the total length we saved
-                       stw             r11,24(r12)                                     ; Save the size
-                       
-logmemexit:    mtmsr   r2                                                      ; Back to normal
-                       li              r3,0
+                       mtmsrd  r0                                                      ; Interrupts and translation off
                        isync
+                       
+                       li              r2,4096/128                                     ; Get number of cache lines
+                                               
+fp64again:     dcbz128 0,r3                                            ; Clear
+                       addic.  r2,r2,-1                                        ; Count down
+                       std             r4,0(r3)                                        ; Fill
+                       std             r6,8(r3)                                        ; Fill
+                       std             r7,16(r3)                                       ; Fill
+                       std             r8,24(r3)                                       ; Fill
+                       std             r9,32(r3)                                       ; Fill
+                       std             r10,40(r3)                                      ; Fill
+                       std             r11,48(r3)                                      ; Fill
+                       std             r12,56(r3)                                      ; Fill
+                       std             r4,64+0(r3)                                     ; Fill
+                       std             r6,64+8(r3)                                     ; Fill
+                       std             r7,64+16(r3)                            ; Fill
+                       std             r8,64+24(r3)                            ; Fill
+                       std             r9,64+32(r3)                            ; Fill
+                       std             r10,64+40(r3)                           ; Fill
+                       std             r11,64+48(r3)                           ; Fill
+                       std             r12,64+56(r3)                           ; Fill
+                       addi    r3,r3,128                                       ; Point next
+                       bgt+    fp64again                                       ; Keep going
+
+                       mtmsrd  r5                                                      ; Restore all
+                       isync
+                       blr                                                                     ; Return...
+                       
+                       .align  5
+                       .globl  EXT(mapLog)
+
+LEXT(mapLog)
+
+                       mfmsr   r12
+                       lis             r11,hi16(EXT(mapdebug))
+                       ori             r11,r11,lo16(EXT(mapdebug))
+                       lwz             r10,0(r11)
+                       mr.             r10,r10
+                       bne++   mLxx
+                       mr              r10,r3
+mLxx:          rlwinm  r0,r12,0,MSR_DR_BIT+1,MSR_DR_BIT-1
+                       mtmsr   r0
+                       isync
+                       stw             r4,0(r10)
+                       stw             r4,4(r10)
+                       stw             r5,8(r10)
+                       stw             r6,12(r10)
+                       mtmsr   r12
+                       isync
+                       addi    r10,r10,16
+                       stw             r10,0(r11)
                        blr
+                       
+#if 1
+                       .align  5
+                       .globl  EXT(checkBogus)
+
+LEXT(checkBogus)
+
+                       BREAKPOINT_TRAP
+                       blr                                                                     ; No-op normally
+                       
+#endif                                         
+
+