Annotation of XNU/osfmk/ppc/hw_vm.s, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.