Annotation of XNU/osfmk/ppc/mappings.c, 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: /*
        !            23:  *     This file is used to maintain the virtual to real mappings for a PowerPC machine.
        !            24:  *     The code herein is primarily used to bridge between the pmap layer and the hardware layer.
        !            25:  *     Currently, some of the function of this module is contained within pmap.c.  We may want to move
        !            26:  *     all of this into it (or most anyway) for the sake of performance.  We shall see as we write it.
        !            27:  *
        !            28:  *     We also depend upon the structure of the phys_entry control block.  We do put some processor 
        !            29:  *     specific stuff in there.
        !            30:  *
        !            31:  */
        !            32: 
        !            33: #include <cpus.h>
        !            34: #include <debug.h>
        !            35: #include <mach_kgdb.h>
        !            36: #include <mach_vm_debug.h>
        !            37: #include <db_machine_commands.h>
        !            38: 
        !            39: #include <kern/thread.h>
        !            40: #include <kern/thread_act.h>
        !            41: #include <mach/vm_attributes.h>
        !            42: #include <mach/vm_param.h>
        !            43: #include <vm/vm_kern.h>
        !            44: #include <vm/vm_map.h>
        !            45: #include <vm/vm_page.h>
        !            46: #include <kern/spl.h>
        !            47: 
        !            48: #include <kern/misc_protos.h>
        !            49: #include <ppc/misc_protos.h>
        !            50: #include <ppc/proc_reg.h>
        !            51: 
        !            52: #include <vm/pmap.h>
        !            53: #include <ppc/pmap.h>
        !            54: #include <ppc/pmap_internals.h>
        !            55: #include <ppc/mem.h>
        !            56: 
        !            57: #include <ppc/new_screen.h>
        !            58: #include <ppc/Firmware.h>
        !            59: #include <ppc/mappings.h>
        !            60: #include <ppc/miscserv.h>
        !            61: #include <ddb/db_output.h>
        !            62: 
        !            63: #define PERFTIMES 0
        !            64: 
        !            65: #if PERFTIMES && DEBUG
        !            66: #define debugLog2(a, b, c) dbgLog2(a, b, c)
        !            67: #else
        !            68: #define debugLog2(a, b, c)
        !            69: #endif
        !            70: 
        !            71: autogenblok            *AutoGenList;                                                                   /* Anchor for the autogeb list */
        !            72: space_t                        curr_spaceID = 0;                                                               /* Highest used space ID */
        !            73: unsigned int   incrVSID = 0;                                                                   /* VSID increment value */
        !            74: unsigned int   mappingdeb0 = 0;                                                
        !            75: extern unsigned int    hash_table_size;                                                
        !            76: extern unsigned int    debsave0;                                               
        !            77: extern unsigned int dbdbdb;                                                                            /* (TEST/DEBUG) */
        !            78: extern vm_offset_t mem_size;
        !            79: /*
        !            80:  *     ppc_prot translates from the mach representation of protections to the PPC version.
        !            81:  *     Calculation of it like this saves a memory reference - and maybe a couple of microseconds.
        !            82:  *     It eliminates the used of this table.
        !            83:  *     unsigned char ppc_prot[8] = { 0, 3, 2, 2, 3, 3, 2, 2 };
        !            84:  */
        !            85: 
        !            86: #define ppc_prot(p) ((0xAFAC >> (p << 1)) & 3)
        !            87: 
        !            88: /*
        !            89:  *             mapping_space();
        !            90:  *                     This function is called to generate an address space ID. This space ID must be unique within
        !            91:  *                     the system.  For the PowerPC, it is used to build the VSID.  We build a VSID in the following
        !            92:  *                     way:  space ID << 4 | segment.  Since a VSID is 24 bits, and out of that, we reserve the last
        !            93:  *                     4, so, we can have 2^20 (2M) unique IDs.  Each pmap has a unique space ID, so we should be able
        !            94:  *                     to have 2M pmaps at a time, which we couldn't, we'd run out of memory way before then.  The 
        !            95:  *                     problem is that only a certain number of pmaps are kept in a free list and if that is full,
        !            96:  *                     they are release.  This causes us to lose track of what space IDs are free to be reused.
        !            97:  *                     We can do 4 things: 1) not worry about it, 2) keep all free pmaps, 3) rebuild all mappings
        !            98:  *                     when the space ID wraps, or 4) scan the list of pmaps and find a free one.
        !            99:  *
        !           100:  *                     Yet another consideration is the hardware use of the VSID.  It is used as part of the hash
        !           101:  *                     calculation for virtual address lookup.  An improperly chosen value could potentially cause
        !           102:  *                     too many hashes to hit the same bucket, causing PTEG overflows.  The actual hash function
        !           103:  *                     is (page index XOR vsid) mod number of ptegs. For a 32MB machine, using the suggested
        !           104:  *                     hash table size, there are 2^12 (8192) PTEGs.  Remember, though, that the bottom 4 bits
        !           105:  *                     are reserved for the segment number, which means that we really have 2^(12-4) 512 space IDs
        !           106:  *                     before we start hashing to the same buckets with the same vaddrs. Also, within a space ID,
        !           107:  *                     every 8192 pages (32MB) within a segment will hash to the same bucket.  That's 8 collisions
        !           108:  *                     per segment.  So, a scan of every page for 256MB would fill 32 PTEGs completely, but
        !           109:  *                     with no overflow.  I don't think that this is a problem.
        !           110:  *
        !           111:  *                     There may be a problem with the space ID, though. A new space ID is generate (mainly) 
        !           112:  *                     whenever there is a fork.  There shouldn't really be any problem because (for a 32MB
        !           113:  *                     machine) we can have 512 pmaps and still not have hash collisions for the same address.
        !           114:  *                     The potential problem, though, is if we get long-term pmaps that have space IDs that are
        !           115:  *                     the same modulo 512.  We can reduce this problem by having the segment number be bits
        !           116:  *                     0-3 of the space ID rather than 20-23.  Doing this means that, in effect, corresponding
        !           117:  *                     vaddrs in different segments hash to the same PTEG. While this is somewhat of a problem,
        !           118:  *                     I don't think that it is as signifigant as the other, so, I'll make the space ID
        !           119:  *                     with segment first.
        !           120:  *
        !           121:  *                     The final, and biggest problem is the wrap, which will happen every 2^20 space IDs.
        !           122:  *                     While this is a problem that should only happen in periods counted in weeks, it can and
        !           123:  *                     will happen.  This is assuming a monotonically increasing space ID. If we were to search
        !           124:  *                     for an inactive space ID, there could not be a wrap until there was 2^20 concurrent space IDs.
        !           125:  *                     That's pretty unlikely to happen.  There couldn't be enough storage to support a million tasks.
        !           126:  *                     Another potential solution is to monitor for the wrap, and reorganize the space IDs when it happens.
        !           127:  *                     This is rather severe, and would have user-perceivable performance impact.  It would be necessary
        !           128:  *                     to quiese all other processors, invalidate and purge the entire hash table, and then to reassign
        !           129:  *                     all space IDs in active pmaps.  It may be better to amortize the problem by keeping pmaps in sorted
        !           130:  *                     order and keeping track of the lowest unused space ID.  I'll think on this one and do a panic
        !           131:  *                     until I got it sussed.
        !           132:  */
        !           133: 
        !           134: space_t mapping_space(void) {                                                                  /* Generate a unique space ID */
        !           135: 
        !           136:        register space_t        currSID, nextSID;                                       
        !           137:        
        !           138:        while(1) {                                                                                                      /* Keep trying until something happens */
        !           139:                currSID=curr_spaceID;                                                                   /* Get a copy of the current ID */
        !           140:                if(!(nextSID = ((currSID + incrVSID) & SID_MAX))) {             /* Get the next one and check if we wrapped */
        !           141:                        panic("Address space ID wrapped;  Temporarily fatal system error.  Add more code here...\n");   /* Die */
        !           142:                }
        !           143:                if(hw_compare_and_store(currSID, nextSID, &curr_spaceID)) {     /* Have we found a good one yet? */
        !           144:                        debugLog2(0, nextSID, 0);                                                       /* Log mapping_space call */
        !           145:                        return (nextSID);                                                                       /* Yeah, return it... */
        !           146:                }                                                                                                               /* save the new  and exit if not, */
        !           147:        }
        !           148: }
        !           149: 
        !           150: 
        !           151: /*
        !           152:  *             mapping_init();
        !           153:  *                     Do anything that needs to be done before the mapping system can be used.
        !           154:  *                     Hash table must be initialized before we call this.
        !           155:  *
        !           156:  *                     Calculate the SID increment.  Currently we use size^(1/2) + size^(1/4) + 1;
        !           157:  */
        !           158: 
        !           159: void mapping_init(void) {
        !           160: 
        !           161:        unsigned int tmp;
        !           162:        
        !           163:        __asm__ volatile("cntlzw %0, %1" : "=r" (tmp) : "r" (hash_table_size)); /* Get number of leading 0s */
        !           164: 
        !           165:        incrVSID = 1 << ((32 - tmp + 1) >> 1);                                          /* Get ceiling of sqrt of table size */
        !           166:        incrVSID |= 1 << ((32 - tmp + 1) >> 2);                                         /* Get ceiling of quadroot of table size */
        !           167:        incrVSID |= 1;                                                                                          /* Set bit and add 1 */
        !           168:        return;
        !           169: 
        !           170: }
        !           171: 
        !           172: 
        !           173: /*
        !           174:  *             mapping_remove(space_t space, vm_offset_t va);
        !           175:  *                     Given a space ID and virtual address, this routine finds the mapping and removes if from
        !           176:  *                     both its PTEG hash list and the physical entry list.  The mapping block will be added to
        !           177:  *                     the free list.  If the free list threshold is reached, garbage collection will happen.
        !           178:  *                     We also kick back a return code to say whether or not we had one to remove.
        !           179:  *
        !           180:  *                     We have a strict ordering here:  the mapping must be removed from the PTEG hash list before
        !           181:  *                     it can be removed from the physical entry list.  This allows us to get by with only the PTEG
        !           182:  *                     hash lock at page fault time. The physical entry lock must be held while we remove the mapping 
        !           183:  *                     from both lists. The PTEG lock is one of the lowest level locks.  No PTE fault, interruptions,
        !           184:  *                     losing control, getting other locks, etc., are allowed when you hold it. You do, and you die.
        !           185:  *                     It's just that simple!
        !           186:  *
        !           187:  *                     When the phys_entry lock is held, the mappings chained to that one are guaranteed to stay around.
        !           188:  *                     However, a mapping's order on the PTEG hash chain is not.  The interrupt handler uses the PTEG
        !           189:  *                     lock to control the hash cahin and may move the position of the mapping for MRU calculations.
        !           190:  *
        !           191:  *                     Note that mappings do not need to point to a physical entry. When they don't, it indicates 
        !           192:  *                     the mapping is outside of physical memory and usually refers to a memory mapped device of
        !           193:  *                     some sort.  Naturally, we can't lock what we don't have, so the phys entry lock and unlock
        !           194:  *                     routines return normally, but don't do anything.
        !           195:  */
        !           196: 
        !           197: boolean_t mapping_remove(space_t space, vm_offset_t va) {              /* Remove a single mapping for this VADDR 
        !           198:                                                                                                                                   Returns TRUE if a mapping was found to remove */
        !           199: 
        !           200:        mapping         *mp, *mpv;
        !           201:        spl_t           s;
        !           202:        
        !           203:        debugLog2(1, va, space);                                                                        /* start mapping_remove */
        !           204:        s=splhigh();                                                                                            /* Don't bother me */
        !           205:        
        !           206:        mp = hw_lock_phys_vir(space, va);                                                       /* Lock the physical entry for this mapping */
        !           207: 
        !           208:        if(!mp) {                                                                                                       /* Did we find one? */
        !           209:                splx(s);                                                                                                /* Restore the interrupt level */
        !           210:                debugLog2(2, 0, 0);                                                                             /* end mapping_remove */
        !           211:                return FALSE;                                                                                   /* Didn't find any, return FALSE... */
        !           212:        }
        !           213:        if((unsigned int)mp&1) {                                                                        /* Did we timeout? */
        !           214:                panic("mapping_remove: timeout locking physical entry\n");      /* Yeah, scream about it! */
        !           215:                splx(s);                                                                                                /* Restore the interrupt level */
        !           216:                return FALSE;                                                                                   /* Bad hair day, return FALSE... */
        !           217:        }
        !           218:        
        !           219:        mpv = hw_cpv(mp);                                                                                       /* Get virtual address of mapping */
        !           220:        if(mpv->pmap) {                                                                                         /* Check for a pmap */
        !           221: #if DEBUG
        !           222:                if(hw_atomic_sub(&mpv->pmap->stats.resident_count, 1) < 0) panic("pmap resident count went negative\n");
        !           223: #else
        !           224:                (void)hw_atomic_sub(&mpv->pmap->stats.resident_count, 1);       /* Decrement the resident page count */
        !           225: #endif
        !           226:        }
        !           227:        
        !           228:        hw_rem_map(mp);                                                                                         /* Remove the corresponding mapping */
        !           229:        
        !           230:        if(mpv->physent)hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);     /* Unlock physical entry associated with mapping */
        !           231:        
        !           232:        splx(s);                                                                                                        /* Was there something you needed? */
        !           233:                
        !           234:        mapping_free(mpv);                                                                                      /* Add mapping to the free list */
        !           235:        debugLog2(2, 1, 0);                                                                                     /* end mapping_remove */
        !           236:        return TRUE;                                                                                            /* Tell them we did it */
        !           237: }
        !           238: 
        !           239: /*
        !           240:  *             mapping_purge(struct phys_entry *pp) - release all mappings for this physent to the free list 
        !           241:  *
        !           242:  *             This guy releases any mappings that exist for a physical page.
        !           243:  *             We get the lock on the phys_entry, and hold it through out this whole routine.
        !           244:  *             That way, no one can change the queue out from underneath us.  We keep fetching
        !           245:  *             the physents mapping anchor until it is null, then we're done.  
        !           246:  *
        !           247:  *             For each mapping, we call the remove routine to remove it from the PTEG hash list and 
        !           248:  *             decriment the pmap's residency count.  Then we release the mapping back to the free list.
        !           249:  *
        !           250:  */
        !           251:  
        !           252: void mapping_purge(struct phys_entry *pp) {                                            /* Remove all mappings for this physent */
        !           253: 
        !           254:        mapping         *mp, *mpv;
        !           255:        spl_t           s;
        !           256:                
        !           257:        s=splhigh();                                                                                            /* Don't bother me */
        !           258:        debugLog2(3, pp->pte1, 0);                                                                      /* start mapping_purge */
        !           259:        
        !           260:        if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {              /* Lock the physical entry */
        !           261:                panic("\nmapping_purge: Timeout attempting to lock physical entry at %08X: %08X %08X\n", 
        !           262:                        pp, pp->phys_link, pp->pte1);   /* Complain about timeout */
        !           263:        }
        !           264:        
        !           265:        while(mp = (mapping *)((unsigned int)pp->phys_link & ~PHYS_FLAGS)) {    /* Keep going so long as there's another */
        !           266: 
        !           267:                mpv = hw_cpv(mp);                                                                               /* Get the virtual address */
        !           268:                if(mpv->pmap) {                                                                                 /* See if there is a pmap to worry about */
        !           269: #if DEBUG
        !           270:                        if(hw_atomic_sub(&mpv->pmap->stats.resident_count, 1) < 0) panic("pmap resident count went negative\n");
        !           271: #else
        !           272:                        (void)hw_atomic_sub(&mpv->pmap->stats.resident_count, 1);       /* Decrement the resident page count */
        !           273: #endif
        !           274:                }
        !           275:        
        !           276:                hw_rem_map(mp);                                                                                 /* Remove the mapping */
        !           277:                mapping_free(mpv);                                                                              /* Add mapping to the free list */
        !           278:        }
        !           279:                
        !           280:        hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);       /* We're done, unlock the physical entry */
        !           281:        
        !           282:        debugLog2(4, pp->pte1, 0);                                                                      /* end mapping_purge */
        !           283:        splx(s);                                                                                                        /* Was there something you needed? */
        !           284:        return;                                                                                                         /* Tell them we did it */
        !           285: }
        !           286: 
        !           287: 
        !           288: /*
        !           289:  *             mapping_make(pmap, space, pp, va, spa, prot, attr) - map a virtual address to a real one 
        !           290:  *
        !           291:  *             This routine takes the given parameters, builds a mapping block, and queues it into the 
        !           292:  *             correct lists.
        !           293:  *             
        !           294:  *             The pmap and pp parameters can be null.  This allows us to make a mapping that is not
        !           295:  *             associated with any physical page or pmap.  We may need this for certain I/O areas.
        !           296:  *
        !           297:  *             If the pmap is null, we don't diddle with it, i.e., the residency counts.
        !           298:  *             If the phys_entry address is null, we neither lock or chain into it.
        !           299:  */
        !           300:  
        !           301: mapping *mapping_make(pmap_t pmap, space_t space, struct phys_entry *pp, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, int attr) {   /* Make an address mapping */
        !           302: 
        !           303:        register mapping *mp, *mpv;
        !           304:        spl_t           s;
        !           305:        
        !           306:        debugLog2(5, va, pa);                                                                           /* start mapping_purge */
        !           307:        mpv = mapping_alloc();                                                                          /* Get a spare mapping block */
        !           308:        
        !           309:        mpv->pmap = pmap;                                                                                       /* Initialize the pmap pointer */
        !           310:        mpv->physent = pp;                                                                                      /* Initialize the pointer to the physical entry */
        !           311:        mpv->PTEr = ((unsigned int)pa & ~(PAGE_SIZE - 1)) | attr<<3 | ppc_prot(prot);   /* Build the real portion of the PTE */
        !           312:        mpv->PTEv = (((unsigned int)va >> 1) & 0x78000000) | (space << 7) | (((unsigned int)va >> 22) & 0x0000003F);    /* Build the VSID */
        !           313: 
        !           314:        s=splhigh();                                                                                            /* Don't bother from now on */
        !           315:        
        !           316:        mp = hw_cvp(mpv);                                                                                       /* Get the physical address of this */
        !           317: 
        !           318:        if(pp) {                                                                                                        /* Is there a physical entry? */
        !           319:                if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Lock the physical entry */
        !           320:                        panic("\nmapping_make: Timeout attempting to lock physical entry at %08X: %08X %08X\n", 
        !           321:                                pp, pp->phys_link, pp->pte1);                                   /* Complain about timeout */
        !           322:                }
        !           323:                
        !           324:                mpv->next = (mapping *)((unsigned int)pp->phys_link & ~PHYS_FLAGS);             /* Move the old anchor to the new mappings forward */
        !           325:                pp->phys_link = (mapping *)((unsigned int)mp | (unsigned int)pp->phys_link & PHYS_FLAGS);       /* Point the anchor at us.  Now we're on the list (keep the flags) */
        !           326:        }
        !           327:        
        !           328:        hw_add_map(mp, space, va);                                                                      /* Stick it on the PTEG hash list */
        !           329:        
        !           330:        if(pmap) {                                                                                                      /* If there is a pmap, adjust the residency count */
        !           331:                (void)hw_atomic_add(&mpv->pmap->stats.resident_count, 1);       /* Increment the resident page count */
        !           332:        }
        !           333:        
        !           334:        if(pp)hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK); /* If we have one, unlock the physical entry */
        !           335:                
        !           336:        splx(s);                                                                                                        /* Ok for interruptions now */
        !           337:        debugLog2(6, space, prot);                                                                      /* end mapping_purge */
        !           338:        return mpv;                                                                                                     /* Leave... */
        !           339: }
        !           340: 
        !           341: 
        !           342: /*
        !           343:  *             mapping_remap(space_t space, vm_offset_t from, vm_offset_t to) - remap a physical address to a different virtual address
        !           344:  *
        !           345:  *             This routine takes the given parameters, finds the mapping for the "from" address
        !           346:  *             and removes it.  Then it modifies the virtual address and adds it back.
        !           347:  *             
        !           348:  *             It returns failure if the "from" address is not mapped.
        !           349:  */
        !           350:  
        !           351: int    mapping_remap(space_t space, vm_offset_t from, vm_offset_t to) {        /* Remap an address mapping */
        !           352: 
        !           353:        register mapping *mp, *mpv;
        !           354:        spl_t           s;
        !           355:        
        !           356:        s=splhigh();                                                                                            /* Don't bother from now on */
        !           357:        
        !           358:        mp = hw_lock_phys_vir(space, from);                                                     /* Lock the physical entry for this mapping */
        !           359:        debugLog2(7, from, to);                                                                         /* start remap */
        !           360:        if(!mp) {                                                                                                       /* Did we find one? */
        !           361:                splx(s);                                                                                                /* Restore the interrupt level */
        !           362:                return FALSE;                                                                                   /* Didn't find source, return FALSE... */
        !           363:        }
        !           364:        if((unsigned int)mp&1) {                                                                        /* Did we timeout? */
        !           365:                panic("mapping_remap: timeout locking physical entry\n");       /* Yeah, scream about it! */
        !           366:                splx(s);                                                                                                /* Restore the interrupt level */
        !           367:                return FALSE;                                                                                   /* Bad hair day, return FALSE... */
        !           368:        }
        !           369:        
        !           370:        hw_rem_map(mp);                                                                                         /* Remove from the old address. Removes from both PTEG and physent lists */     
        !           371: 
        !           372:        mpv = hw_cpv(mp);                                                                                       /* Convert to virtual address */
        !           373: 
        !           374:        mpv->PTEv = (((unsigned int)to >> 1) & 0x78000000) | 
        !           375:                (space << 7) | (((unsigned int)to >> 22) & 0x0000003F); /* Rebuild the VSID */
        !           376:        
        !           377:        if(mpv->physent) {                                                                                      /* Is there a physical entry? */                
        !           378:                mpv->next = (mapping *)((unsigned int)mpv->physent->phys_link & ~PHYS_FLAGS);   /* Move the old anchor to the new mappings forward */
        !           379:                mpv->physent->phys_link = (mapping *)((unsigned int)mp | ((unsigned int)mpv->physent->phys_link & PHYS_FLAGS)); /* Point the anchor at us.  Now we're back on the list (keep the flags) */
        !           380:        }
        !           381:        
        !           382:        hw_add_map(mp, space, to);                                                                      /* Map it to the new one */
        !           383:        
        !           384:        if(mp->physent)hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);      /* Unlock physical entry associated with mapping */
        !           385:                
        !           386:        debugLog2(8, space, 0);                                                                         /* end remap */
        !           387:        splx(s);                                                                                                        /* Ok for interruptions now */
        !           388:        return TRUE;                                                                                            /* Leave... */
        !           389: }
        !           390: 
        !           391: 
        !           392: /*
        !           393:  *             void mapping_protect(phys_entry *pp, vm_prot_t prot, boolean_t locked) - change the protection of a physical page
        !           394:  *
        !           395:  *             This routine takes a physical entry and runs through all mappings attached to it and changes
        !           396:  *             the protection.  If there are PTEs associated with the mappings, they will be invalidated before
        !           397:  *             the protection is changed.  We don't try to save the PTE.  We won't worry about the LRU calculations
        !           398:  *             either (I don't think, maybe I'll change my mind later).  There is no limitation on changes, e.g., 
        !           399:  *             higher to lower, lower to higher.
        !           400:  *
        !           401:  *             If locked is true, the physent is already locked and should not be unlocked at exit.
        !           402:  *
        !           403:  *             Interruptions should be disabled at entry.
        !           404:  */
        !           405: 
        !           406: void mapping_protect(struct phys_entry *pp, vm_prot_t prot, boolean_t locked) {        /* Change protection of all mappings to page */
        !           407: 
        !           408:        debugLog2(9, pp->pte1, prot);                                                           /* end remap */
        !           409:        if(!locked) {                                                                                           /* Do we need to lock the physent? */
        !           410:                if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Lock the physical entry */
        !           411:                        panic("\nmapping_protect: Timeout attempting to lock physical entry at %08X: %08X %08X\n", 
        !           412:                                pp, pp->phys_link, pp->pte1);                                   /* Complain about timeout */
        !           413:                }
        !           414:        }       
        !           415: 
        !           416:        hw_prot(pp, ppc_prot(prot));                                                            /* Go set the protection on this physical page */
        !           417: 
        !           418:        if(!locked) hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);           /* We're done, unlock the physical entry */
        !           419:        debugLog2(10, pp->pte1, 0);                                                                     /* end remap */
        !           420:        
        !           421:        return;                                                                                                         /* Leave... */
        !           422: }
        !           423: 
        !           424: /*
        !           425:  *             mapping_phys_attr(struct phys_entry *pp, vm_prot_t prot, unsigned int wimg) Sets the default physical page attributes
        !           426:  *
        !           427:  *             This routine takes a physical entry and sets the physical attributes.  There can be no mappings
        !           428:  *             associated with this page when we do it.
        !           429:  */
        !           430: 
        !           431: void mapping_phys_attr(struct phys_entry *pp, vm_prot_t prot, unsigned int wimg) {     /* Sets the default physical page attributes */
        !           432: 
        !           433:        debugLog2(11, pp->pte1, prot);                                                          /* end remap */
        !           434: 
        !           435:        if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Lock the physical entry */
        !           436:                panic("\nmapping_phys_attr: Timeout attempting to lock physical entry at %08X: %08X %08X\n", 
        !           437:                        pp, pp->phys_link, pp->pte1);                                           /* Complain about timeout */
        !           438:        }
        !           439: 
        !           440: //     if(pp->phys_link) panic("\nmapping_phys_attr: attempt to change default attributes when mappings exist!\n");
        !           441: 
        !           442:        hw_phys_attr(pp, ppc_prot(prot), wimg);                                         /* Go set the default WIMG and protection */
        !           443: 
        !           444:        hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);       /* We're done, unlock the physical entry */
        !           445:        debugLog2(12, pp->pte1, wimg);                                                          /* end remap */
        !           446:        
        !           447:        return;                                                                                                         /* Leave... */
        !           448: }
        !           449: 
        !           450: /*
        !           451:  *             void mapping_invall(phys_entry *pp) - invalidates all ptes associated with a page
        !           452:  *
        !           453:  *             This routine takes a physical entry and runs through all mappings attached to it and invalidates
        !           454:  *             any PTEs it finds.
        !           455:  *
        !           456:  *             Interruptions must be disabled and the physical entry locked at entry.
        !           457:  */
        !           458: 
        !           459: void mapping_invall(struct phys_entry *pp) {                                   /* Clear all PTEs pointing to a physical page */
        !           460: 
        !           461:        hw_inv_all(pp);                                                                                         /* Go set the change bit of a physical page */
        !           462:        
        !           463:        return;                                                                                                         /* Leave... */
        !           464: }
        !           465: 
        !           466: 
        !           467: /*
        !           468:  *             void mapping_clr_mod(phys_entry *pp) - clears the change bit of a physical page
        !           469:  *
        !           470:  *             This routine takes a physical entry and runs through all mappings attached to it and turns
        !           471:  *             off the change bit.  If there are PTEs associated with the mappings, they will be invalidated before
        !           472:  *             the change bit is changed.  We don't try to save the PTE.  We won't worry about the LRU calculations
        !           473:  *             either (I don't think, maybe I'll change my mind later).
        !           474:  *
        !           475:  *             Interruptions must be disabled and the physical entry locked at entry.
        !           476:  */
        !           477: 
        !           478: void mapping_clr_mod(struct phys_entry *pp) {                                  /* Clears the change bit of a physical page */
        !           479: 
        !           480:        hw_clr_mod(pp);                                                                                         /* Go clear the change bit of a physical page */
        !           481:        return;                                                                                                         /* Leave... */
        !           482: }
        !           483: 
        !           484: 
        !           485: /*
        !           486:  *             void mapping_set_mod(phys_entry *pp) - set the change bit of a physical page
        !           487:  *
        !           488:  *             This routine takes a physical entry and runs through all mappings attached to it and turns
        !           489:  *             on the change bit.  If there are PTEs associated with the mappings, they will be invalidated before
        !           490:  *             the change bit is changed.  We don't try to save the PTE.  We won't worry about the LRU calculations
        !           491:  *             either (I don't think, maybe I'll change my mind later).
        !           492:  *
        !           493:  *             Interruptions must be disabled and the physical entry locked at entry.
        !           494:  */
        !           495: 
        !           496: void mapping_set_mod(struct phys_entry *pp) {                                  /* Sets the change bit of a physical page */
        !           497: 
        !           498:        hw_set_mod(pp);                                                                                         /* Go set the change bit of a physical page */
        !           499:        return;                                                                                                         /* Leave... */
        !           500: }
        !           501: 
        !           502: 
        !           503: /*
        !           504:  *             void mapping_clr_ref(struct phys_entry *pp) - clears the reference bit of a physical page
        !           505:  *
        !           506:  *             This routine takes a physical entry and runs through all mappings attached to it and turns
        !           507:  *             off the reference bit.  If there are PTEs associated with the mappings, they will be invalidated before
        !           508:  *             the reference bit is changed.  We don't try to save the PTE.  We won't worry about the LRU calculations
        !           509:  *             either (I don't think, maybe I'll change my mind later).
        !           510:  *
        !           511:  *             Interruptions must be disabled at entry.
        !           512:  */
        !           513: 
        !           514: void mapping_clr_ref(struct phys_entry *pp) {                                  /* Clears the reference bit of a physical page */
        !           515: 
        !           516:        mapping *mp;
        !           517: 
        !           518:        debugLog2(13, pp->pte1, 0);                                                                     /* end remap */
        !           519:        if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Lock the physical entry for this mapping */
        !           520:                panic("Lock timeout getting lock on physical entry\n"); /* Just die... */
        !           521:        }
        !           522:        hw_clr_ref(pp);                                                                                         /* Go clear the reference bit of a physical page */
        !           523:        hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);       /* Unlock physical entry */
        !           524:        debugLog2(14, pp->pte1, 0);                                                                     /* end remap */
        !           525:        return;                                                                                                         /* Leave... */
        !           526: }
        !           527: 
        !           528: 
        !           529: /*
        !           530:  *             void mapping_set_ref(phys_entry *pp) - set the reference bit of a physical page
        !           531:  *
        !           532:  *             This routine takes a physical entry and runs through all mappings attached to it and turns
        !           533:  *             on the reference bit.  If there are PTEs associated with the mappings, they will be invalidated before
        !           534:  *             the reference bit is changed.  We don't try to save the PTE.  We won't worry about the LRU calculations
        !           535:  *             either (I don't think, maybe I'll change my mind later).
        !           536:  *
        !           537:  *             Interruptions must be disabled and the physical entry locked at entry.
        !           538:  */
        !           539: 
        !           540: void mapping_set_ref(struct phys_entry *pp) {                                  /* Sets the reference bit of a physical page */
        !           541: 
        !           542:        hw_set_ref(pp);                                                                                         /* Go set the reference bit of a physical page */
        !           543:        return;                                                                                                         /* Leave... */
        !           544: }
        !           545: 
        !           546: 
        !           547: /*
        !           548:  *             void mapping_tst_mod(phys_entry *pp) - test the change bit of a physical page
        !           549:  *
        !           550:  *             This routine takes a physical entry and runs through all mappings attached to it and tests
        !           551:  *             the changed bit.  If there are PTEs associated with the mappings, they will be invalidated before
        !           552:  *             the changed bit is tested.  We don't try to save the PTE.  We won't worry about the LRU calculations
        !           553:  *             either (I don't think, maybe I'll change my mind later).
        !           554:  *
        !           555:  *             Interruptions must be disabled and the physical entry locked at entry.
        !           556:  */
        !           557: 
        !           558: boolean_t mapping_tst_mod(struct phys_entry *pp) {                             /* Tests the change bit of a physical page */
        !           559: 
        !           560:        return(hw_tst_mod(pp));                                                                         /* Go test the change bit of a physical page */
        !           561: }
        !           562: 
        !           563: 
        !           564: /*
        !           565:  *             void mapping_tst_ref(phys_entry *pp) - tests the reference bit of a physical page
        !           566:  *
        !           567:  *             This routine takes a physical entry and runs through all mappings attached to it and tests
        !           568:  *             the reference bit.  If there are PTEs associated with the mappings, they will be invalidated before
        !           569:  *             the reference bit is changed.  We don't try to save the PTE.  We won't worry about the LRU calculations
        !           570:  *             either (I don't think, maybe I'll change my mind later).
        !           571:  *
        !           572:  *             Interruptions must be disabled and the physical entry locked at entry.
        !           573:  */
        !           574: 
        !           575: boolean_t mapping_tst_ref(struct phys_entry *pp) {                             /* Tests the reference bit of a physical page */
        !           576: 
        !           577:        return(hw_tst_ref(pp));                                                                         /* Go test the reference bit of a physical page */
        !           578: }
        !           579: 
        !           580: 
        !           581: /*
        !           582:  *             void mapping_phys_init(physent, wimg) - fills in the default processor dependent areas of the phys ent
        !           583:  *
        !           584:  *             Currently, this sets the default word 1 of the PTE.  The only bits set are the WIMG bits
        !           585:  */
        !           586: 
        !           587: void mapping_phys_init(struct phys_entry *pp, unsigned int pa, unsigned int wimg) {            /* Initializes hw specific storage attributes */
        !           588: 
        !           589:        pp->pte1 = (pa & -PAGE_SIZE) | ((wimg << 3) & 0x00000078);      /* Set the WIMG and phys addr in the default PTE1 */
        !           590: 
        !           591:        return;                                                                                                         /* Leave... */
        !           592: }
        !           593: 
        !           594: 
        !           595: /*
        !           596:  *             mapping_adjust(void) - Releases free mapping blocks and/or allocates new ones 
        !           597:  *
        !           598:  *             This routine frees any mapping blocks queued to mapCtl.mapcrel. It also checks
        !           599:  *             the number of free mappings remaining, and if below a threshold, replenishes them.
        !           600:  *             The list will be replenshed from mapCtl.mapcrel if there are enough.  Otherwise,
        !           601:  *             a new one is allocated.
        !           602:  *
        !           603:  *             This routine allocates and/or memory and must be called from a safe place. 
        !           604:  *             Currently, vm_pageout_scan is the safest place. We insure that the 
        !           605:  */
        !           606: 
        !           607: thread_call_t                          mapping_adjust_call;
        !           608: static thread_call_data_t      mapping_adjust_call_data;
        !           609: 
        !           610: void mapping_adjust(void) {                                                                            /* Adjust free mappings */
        !           611: 
        !           612:        kern_return_t   retr;
        !           613:        mappingblok     *mb, *mbn;
        !           614:        spl_t                   s;
        !           615:        int                             allocsize, i;
        !           616: 
        !           617:        if(mapCtl.mapcmin <= MAPPERBLOK) {                                                      /* Do the first time only */
        !           618:                mapCtl.mapcmin = mem_size >> 12;                                                /* Make sure we have enough for all of physical memory */
        !           619: #if DEBUG
        !           620:                kprintf("mapping_adjust: minimum entries rqrd = %08X\n", mapCtl.mapcmin);
        !           621:                kprintf("mapping_adjust: free = %08X; in use = %08X; release = %08X\n",
        !           622:                  mapCtl.mapcfree, mapCtl.mapcinuse, mapCtl.mapcreln);
        !           623: #endif
        !           624:        }
        !           625: 
        !           626:        s = splhigh();                                                                                          /* Don't bother from now on */
        !           627:        if(!hw_lock_to((hw_lock_t)&mapCtl.mapclock, LockTimeOut)) {     /* Lock the control header */ 
        !           628:                panic("mapping_adjust - timeout getting control lock (1)\n");   /* Tell all and die */
        !           629:        }
        !           630:        
        !           631:        if (mapping_adjust_call == NULL) {
        !           632:                thread_call_setup(&mapping_adjust_call_data, mapping_adjust, NULL);
        !           633:                mapping_adjust_call = &mapping_adjust_call_data;
        !           634:        }
        !           635: 
        !           636:        while(1) {                                                                                                      /* Keep going until we've got enough */
        !           637:                
        !           638:                allocsize = mapCtl.mapcmin - mapCtl.mapcfree;                   /* Figure out how much we need */
        !           639:                if(allocsize < 1) break;                                                                /* Leave if we have all we need */
        !           640:                
        !           641:                if((unsigned int)(mbn = mapCtl.mapcrel)) {                              /* Can we rescue a free one? */
        !           642:                        mapCtl.mapcrel = mbn->nextblok;                                         /* Dequeue it */
        !           643:                        mapCtl.mapcreln--;                                                                      /* Back off the count */
        !           644:                        allocsize = MAPPERBLOK;                                                         /* Show we allocated one block */                       
        !           645:                }
        !           646:                else {                                                                                                  /* No free ones, try to get it */
        !           647:                        
        !           648:                        allocsize = (allocsize + MAPPERBLOK - 1) / MAPPERBLOK;  /* Get the number of pages we need */
        !           649:                        if(allocsize > (mapCtl.mapcfree / 2)) allocsize = (mapCtl.mapcfree / 2);        /* Don't try for anything that we can't comfortably map */
        !           650:                        
        !           651:                        hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);            /* Unlock our stuff */
        !           652:                        splx(s);                                                                                        /* Restore 'rupts */
        !           653: 
        !           654:                        for(; allocsize > 0; allocsize >>= 1) {                         /* Try allocating in descending halves */ 
        !           655:                                retr = kmem_alloc_wired(kernel_map, (vm_offset_t *)&mbn, PAGE_SIZE * allocsize);        /* Find a virtual address to use */
        !           656:                                if((retr != KERN_SUCCESS) && (allocsize == 1)) {        /* Did we find any memory at all? */
        !           657:                                        panic("Whoops...  Not a bit of wired memory left for anyone\n");
        !           658:                                }
        !           659:                                if(retr == KERN_SUCCESS) break;                                 /* We got some memory, bail out... */
        !           660:                        }
        !           661:                
        !           662:                        allocsize = allocsize * MAPPERBLOK;                                     /* Convert pages to number of maps allocated */
        !           663:                        s = splhigh();                                                                          /* Don't bother from now on */
        !           664:                        if(!hw_lock_to((hw_lock_t)&mapCtl.mapclock, LockTimeOut)) {     /* Lock the control header */ 
        !           665:                                panic("mapping_adjust - timeout getting control lock (2)\n");   /* Tell all and die */
        !           666:                        }
        !           667:                }
        !           668:                for(; allocsize > 0; allocsize -= MAPPERBLOK) {                 /* Release one block at a time */
        !           669:                        mapping_free_init((vm_offset_t)mbn, 0, 1);                      /* Initialize a non-permanent block */
        !           670:                        mbn = (mappingblok *)((unsigned int)mbn + PAGE_SIZE);   /* Point to the next slot */
        !           671:                }
        !           672:        }
        !           673: 
        !           674:        if(mapCtl.mapcholdoff) {                                                                        /* Should we hold off this release? */
        !           675:                mapCtl.mapcrecurse = 0;                                                                 /* We are done now */
        !           676:                hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);                    /* Unlock our stuff */
        !           677:                splx(s);                                                                                                /* Restore 'rupts */
        !           678:                return;                                                                                                 /* Return... */
        !           679:        }
        !           680: 
        !           681:        mbn = mapCtl.mapcrel;                                                                           /* Get first pending release block */
        !           682:        mapCtl.mapcrel = 0;                                                                                     /* Dequeue them */
        !           683:        mapCtl.mapcreln = 0;                                                                            /* Set count to 0 */
        !           684: 
        !           685:        hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);                            /* Unlock our stuff */
        !           686:        splx(s);                                                                                                        /* Restore 'rupts */
        !           687: 
        !           688:        while((unsigned int)mbn) {                                                                      /* Toss 'em all */
        !           689:                mb = mbn->nextblok;                                                                             /* Get the next */
        !           690:                kmem_free(kernel_map, (vm_offset_t) mbn, PAGE_SIZE);    /* Release this mapping block */
        !           691:                mbn = mb;                                                                                               /* Chain to the next */
        !           692:        }
        !           693: 
        !           694:        __asm__ volatile("sync");                                                                       /* Make sure all is well */
        !           695:        mapCtl.mapcrecurse = 0;                                                                         /* We are done now */
        !           696:        return;
        !           697: }
        !           698: 
        !           699: /*
        !           700:  *             mapping_free(mapping *mp) - release a mapping to the free list 
        !           701:  *
        !           702:  *             This routine takes a mapping and adds it to the free list.
        !           703:  *             If this mapping make the block non-empty, we queue it to the free block list.
        !           704:  *             NOTE: we might want to queue it to the end to keep quelch the pathalogical
        !           705:  *             case when we get a mapping and free it repeatedly causing the block to chain and unchain.
        !           706:  *             If this release fills a block and we are above the threshold, we release the block
        !           707:  */
        !           708: 
        !           709: void mapping_free(struct mapping *mp) {                                                        /* Release a mapping */
        !           710: 
        !           711:        mappingblok     *mb, *mbn;
        !           712:        spl_t                   s;
        !           713:        unsigned int    full, mindx;
        !           714: 
        !           715:        mindx = ((unsigned int)mp & (PAGE_SIZE - 1)) >> 5;                      /* Get index to mapping */
        !           716:        mb = (mappingblok *)((unsigned int)mp & -PAGE_SIZE);            /* Point to the mapping block */
        !           717: 
        !           718:        s = splhigh();                                                                                          /* Don't bother from now on */
        !           719:        if(!hw_lock_to((hw_lock_t)&mapCtl.mapclock, LockTimeOut)) {     /* Lock the control header */ 
        !           720:                panic("mapping_free - timeout getting control lock\n"); /* Tell all and die */
        !           721:        }
        !           722:        
        !           723:        full = !(mb->mapblokfree[0] | mb->mapblokfree[1] | mb->mapblokfree[2] | mb->mapblokfree[3]);    /* See if full now */ 
        !           724:        mb->mapblokfree[mindx >> 5] |= (0x80000000 >> (mindx & 31));    /* Flip on the free bit */
        !           725:        
        !           726:        if(full) {                                                                                                      /* If it was full before this: */
        !           727:                mb->nextblok = mapCtl.mapcnext;                                                 /* Move head of list to us */
        !           728:                mapCtl.mapcnext = mb;                                                                   /* Chain us to the head of the list */
        !           729:        }
        !           730: 
        !           731:        mapCtl.mapcfree++;                                                                                      /* Bump free count */
        !           732:        mapCtl.mapcinuse--;                                                                                     /* Decriment in use count */
        !           733:        
        !           734:        mapCtl.mapcfreec++;                                                                                     /* Count total calls */
        !           735: 
        !           736:        if(mapCtl.mapcfree > mapCtl.mapcmin) {                                          /* Should we consider releasing this? */
        !           737:                if(((mb->mapblokfree[0] | 0x80000000) & mb->mapblokfree[1] & mb->mapblokfree[2] & mb->mapblokfree[3]) 
        !           738:                   == 0xFFFFFFFF) {                                                                             /* See if empty now */ 
        !           739: 
        !           740:                        if(mapCtl.mapcnext == mb) {                                                     /* Are we first on the list? */
        !           741:                                mapCtl.mapcnext = mb->nextblok;                                 /* Unchain us */
        !           742:                                if(!((unsigned int)mapCtl.mapcnext)) mapCtl.mapclast = 0;       /* If last, remove last */
        !           743:                        }
        !           744:                        else {                                                                                          /* We're not first */
        !           745:                                for(mbn = mapCtl.mapcnext; mbn != 0; mbn = mbn->nextblok) {     /* Search for our block */
        !           746:                                        if(mbn->nextblok == mb) break;                          /* Is the next one our's? */
        !           747:                                }
        !           748:                                if(!mbn) panic("mapping_free: attempt to release mapping block (%08X) not on list\n", mp);
        !           749:                                mbn->nextblok = mb->nextblok;                                   /* Dequeue us */
        !           750:                                if(mapCtl.mapclast == mb) mapCtl.mapclast = mbn;        /* If last, make our predecessor last */
        !           751:                        }
        !           752:                        
        !           753:                        if(mb->mapblokflags & mbPerm) {                                         /* Is this permanently assigned? */
        !           754:                                mb->nextblok = mapCtl.mapcnext;                                 /* Move chain head to us */
        !           755:                                mapCtl.mapcnext = mb;                                                   /* Chain us to the head */
        !           756:                                if(!((unsigned int)mb->nextblok)) mapCtl.mapclast = mb; /* If last, make us so */
        !           757:                        }
        !           758:                        else {
        !           759:                                mapCtl.mapcfree -= MAPPERBLOK;                                  /* Remove the block from the free count */
        !           760:                                mapCtl.mapcreln++;                                                              /* Count on release list */
        !           761:                                mb->nextblok = mapCtl.mapcrel;                                  /* Move pointer */
        !           762:                                mapCtl.mapcrel = mb;                                                    /* Chain us in front */
        !           763:                        }
        !           764:                }
        !           765:        }
        !           766: 
        !           767:        if(mapCtl.mapcreln > MAPFRTHRSH) {                                                      /* Do we have way too many releasable mappings? */
        !           768:                if(hw_compare_and_store(0, 1, &mapCtl.mapcrecurse)) {   /* Make sure we aren't recursing */
        !           769:                        thread_call_enter(mapping_adjust_call);                 /* Go toss some */
        !           770:                }
        !           771:        }
        !           772:        hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);                            /* Unlock our stuff */
        !           773:        splx(s);                                                                                                        /* Restore 'rupts */
        !           774: 
        !           775:        return;                                                                                                         /* Bye, dude... */
        !           776: }
        !           777: 
        !           778: 
        !           779: /*
        !           780:  *             mapping_alloc(void) - obtain a mapping from the free list 
        !           781:  *
        !           782:  *             This routine takes a mapping off of the free list and returns it's address.
        !           783:  *
        !           784:  *             We do this by finding a free entry in the first block and allocating it.
        !           785:  *             If this allocation empties the block, we remove it from the free list.
        !           786:  *             If this allocation drops the total number of free entries below a threshold,
        !           787:  *             we allocate a new block.
        !           788:  *
        !           789:  */
        !           790: 
        !           791: mapping *mapping_alloc(void) {                                                                 /* Obtain a mapping */
        !           792: 
        !           793:        register mapping *mp;
        !           794:        mappingblok     *mb, *mbn;
        !           795:        spl_t                   s;
        !           796:        int                             mindx;
        !           797:        kern_return_t   retr;
        !           798: 
        !           799:        s = splhigh();                                                                                          /* Don't bother from now on */
        !           800:        if(!hw_lock_to((hw_lock_t)&mapCtl.mapclock, LockTimeOut)) {     /* Lock the control header */ 
        !           801:                panic("mapping_alloc - timeout getting control lock\n");        /* Tell all and die */
        !           802:        }
        !           803: 
        !           804:        if(!(mb = mapCtl.mapcnext)) {                                                           /* Get the first block entry */
        !           805:                panic("mapping_alloc - free mappings exhausted\n");             /* Whine and moan */
        !           806:        }
        !           807:        
        !           808: 
        !           809:        if(!(mindx = mapalc(mb))) {                                                                     /* Allocate a slot */
        !           810:                panic("mapping_alloc - empty mapping block detected at %08X\n", mb);    /* Not allowed to find none */
        !           811:        }
        !           812:        
        !           813:        if(mindx < 0) {                                                                                         /* Did we just take the last one */
        !           814:                mindx = -mindx;                                                                                 /* Make positive */
        !           815:                mapCtl.mapcnext = mb->nextblok;                                                 /* Remove us from the list */
        !           816:                if(!((unsigned int)mapCtl.mapcnext)) mapCtl.mapclast = 0;       /* Removed the last one */
        !           817:        }
        !           818:        
        !           819:        mapCtl.mapcfree--;                                                                                      /* Decrement free count */
        !           820:        mapCtl.mapcinuse++;                                                                                     /* Bump in use count */
        !           821:        
        !           822:        mapCtl.mapcallocc++;                                                                            /* Count total calls */
        !           823: 
        !           824: /*
        !           825:  *     Note: in the following code, we will attempt to rescue blocks only one at a time.
        !           826:  *     Eventually, after a few more mapping_alloc calls, we will catch up.  If there are none
        !           827:  *     rescueable, we will kick the misc scan who will allocate some for us.  We only do this
        !           828:  *     if we haven't already done it.
        !           829:  *     For early boot, we are set up to only rescue one block at a time.  This is because we prime
        !           830:  *     the release list with as much as we need until threads start.
        !           831:  */
        !           832:        if(mapCtl.mapcfree < mapCtl.mapcmin) {                                          /* See if we need to replenish */
        !           833:                if(mbn = mapCtl.mapcrel) {                                                              /* Try to rescue a block from impending doom */
        !           834:                        mapCtl.mapcrel = mbn->nextblok;                                         /* Pop the queue */
        !           835:                        mapCtl.mapcreln--;                                                                      /* Back off the count */
        !           836:                        mapping_free_init((vm_offset_t)mbn, 0, 1);                      /* Initialize a non-permanent block */
        !           837:                }
        !           838:                else {                                                                                                  /* We need to replenish */
        !           839:                        if(hw_compare_and_store(0, 1, &mapCtl.mapcrecurse)) {   /* Make sure we aren't recursing */
        !           840:                                thread_call_enter(mapping_adjust_call);         /* Go allocate some more */
        !           841:                        }
        !           842:                }
        !           843:        }
        !           844: 
        !           845:        hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);                            /* Unlock our stuff */
        !           846:        splx(s);                                                                                                        /* Restore 'rupts */
        !           847:        
        !           848:        mp = &((mapping *)mb)[mindx];                                                           /* Point to the allocated mapping */
        !           849:     __asm__ volatile("dcbz 0,%0" : : "r" (mp));                                        /* Clean it up */
        !           850:        return mp;                                                                                                      /* Send it back... */
        !           851: }
        !           852: 
        !           853: 
        !           854: /*
        !           855:  *             void mapping_free_init(mb, perm) - Adds a block of storage to the free mapping list
        !           856:  *
        !           857:  *             The mapping block is a page size area on a page boundary.  It contains 1 header and 127
        !           858:  *             mappings.  This call adds and initializes a block for use.
        !           859:  *     
        !           860:  *             The header contains a chain link, bit maps, a virtual to real translation mask, and
        !           861:  *             some statistics. Bit maps map each slot on the page (bit 0 is not used because it 
        !           862:  *             corresponds to the header).  The translation mask is the XOR of the virtual and real
        !           863:  *             addresses (needless to say, the block must be wired).
        !           864:  *
        !           865:  *             We handle these mappings the same way as saveareas: the block is only on the chain so
        !           866:  *             long as there are free entries in it.
        !           867:  *
        !           868:  *             Empty blocks are garbage collected when there are at least mapCtl.mapcmin pages worth of free 
        !           869:  *             mappings. Blocks marked PERM won't ever be released.
        !           870:  *
        !           871:  *             If perm is negative, the mapping is initialized, but immediately queued to the mapCtl.mapcrel
        !           872:  *             list.  We do this only at start up time. This is done because we only allocate blocks 
        !           873:  *             in the pageout scan and it doesn't start up until after we run out of the initial mappings.
        !           874:  *             Therefore, we need to preallocate a bunch, but we don't want them to be permanent.  If we put
        !           875:  *             them on the release queue, the allocate routine will rescue them.  Then when the
        !           876:  *             pageout scan starts, all extra ones will be released.
        !           877:  *
        !           878:  */
        !           879: 
        !           880: 
        !           881: void mapping_free_init(vm_offset_t mbl, int perm, boolean_t locked) {          
        !           882:                                                                                                                        /* Set's start and end of a block of mappings
        !           883:                                                                                                                           perm indicates if the block can be released 
        !           884:                                                                                                                           or goes straight to the release queue .
        !           885:                                                                                                                           locked indicates if the lock is held already */
        !           886:                                                                                                                   
        !           887:        mappingblok     *mb;
        !           888:        spl_t           s;
        !           889:        int                     i;
        !           890:        unsigned int    raddr;
        !           891: 
        !           892:        mb = (mappingblok *)mbl;                                                                /* Start of area */
        !           893:        
        !           894:        
        !           895:        if(perm >= 0) {                                                                                 /* See if we need to initialize the block */
        !           896:                if(perm) {
        !           897:                        raddr = (unsigned int)mbl;                                              /* Perm means V=R */
        !           898:                        mb->mapblokflags = mbPerm;                                              /* Set perm */
        !           899:                }
        !           900:                else {
        !           901:                        raddr = kvtophys(mbl);                                                  /* Get real address */
        !           902:                        mb->mapblokflags = 0;                                                   /* Set not perm */
        !           903:                }
        !           904:                
        !           905:                mb->mapblokvrswap = raddr ^ (unsigned int)mbl;          /* Form translation mask */
        !           906:                
        !           907:                mb->mapblokfree[0] = 0x7FFFFFFF;                                        /* Set first 32 (minus 1) free */
        !           908:                mb->mapblokfree[1] = 0xFFFFFFFF;                                        /* Set next 32 free */
        !           909:                mb->mapblokfree[2] = 0xFFFFFFFF;                                        /* Set next 32 free */
        !           910:                mb->mapblokfree[3] = 0xFFFFFFFF;                                        /* Set next 32 free */
        !           911:        }
        !           912:        
        !           913:        s = splhigh();                                                                                  /* Don't bother from now on */
        !           914:        if(!locked) {                                                                                   /* Do we need the lock? */
        !           915:                if(!hw_lock_to((hw_lock_t)&mapCtl.mapclock, LockTimeOut)) {             /* Lock the control header */ 
        !           916:                        panic("mapping_free_init - timeout getting control lock\n");    /* Tell all and die */
        !           917:                }
        !           918:        }
        !           919:        
        !           920:        if(perm < 0) {                                                                                  /* Direct to release queue? */
        !           921:                mb->nextblok = mapCtl.mapcrel;                                          /* Move forward pointer */
        !           922:                mapCtl.mapcrel = mb;                                                            /* Queue us on in */
        !           923:                mapCtl.mapcreln++;                                                                      /* Count the free block */
        !           924:        }
        !           925:        else {                                                                                                  /* Add to the free list */
        !           926:                
        !           927:                mb->nextblok = 0;                                                                       /* We always add to the end */
        !           928:                mapCtl.mapcfree += MAPPERBLOK;                                          /* Bump count */
        !           929:                
        !           930:                if(!((unsigned int)mapCtl.mapcnext)) {                          /* First entry on list? */
        !           931:                        mapCtl.mapcnext = mapCtl.mapclast = mb;                 /* Chain to us */
        !           932:                }
        !           933:                else {                                                                                          /* We are not the first */
        !           934:                        mapCtl.mapclast->nextblok = mb;                                 /* Point the last to us */
        !           935:                        mapCtl.mapclast = mb;                                                   /* We are now last */
        !           936:                }
        !           937:        }
        !           938:                
        !           939:        if(!locked) {                                                                                   /* Do we need to unlock? */
        !           940:                hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);            /* Unlock our stuff */
        !           941:        }
        !           942:                splx(s);                                                                                        /* Restore 'rupts */
        !           943:        return;                                                                                                 /* All done, leave... */
        !           944: }
        !           945: 
        !           946: 
        !           947: /*
        !           948:  *             void mapping_prealloc(unsigned int) - Preallocates mapppings for large request
        !           949:  *     
        !           950:  *             No locks can be held, because we allocate memory here.
        !           951:  *             This routine needs a corresponding mapping_relpre call to remove the
        !           952:  *             hold off flag so that the adjust routine will free the extra mapping
        !           953:  *             blocks on the release list.  I don't like this, but I don't know
        !           954:  *             how else to do this for now...
        !           955:  *
        !           956:  */
        !           957: 
        !           958: void mapping_prealloc(unsigned int size) {                                     /* Preallocates mapppings for large request */
        !           959: 
        !           960:        int     nmapb, i;
        !           961:        kern_return_t   retr;
        !           962:        mappingblok     *mbn;
        !           963:        spl_t           s;
        !           964: 
        !           965:        s = splhigh();                                                                                  /* Don't bother from now on */
        !           966:        if(!hw_lock_to((hw_lock_t)&mapCtl.mapclock, LockTimeOut)) {             /* Lock the control header */ 
        !           967:                panic("mapping_prealloc - timeout getting control lock\n");     /* Tell all and die */
        !           968:        }
        !           969: 
        !           970:        nmapb = (size >> 12) + mapCtl.mapcmin;                                  /* Get number of entries needed for this and the minimum */
        !           971:        
        !           972:        mapCtl.mapcholdoff++;                                                                   /* Bump the hold off count */
        !           973:        
        !           974:        if((nmapb = (nmapb - mapCtl.mapcfree)) <= 0) {                  /* Do we already have enough? */
        !           975:                hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);            /* Unlock our stuff */
        !           976:                splx(s);                                                                                        /* Restore 'rupts */
        !           977:                return;
        !           978:        }
        !           979: 
        !           980:        nmapb = (nmapb + MAPPERBLOK - 1) / MAPPERBLOK;                  /* Get number of blocks to get */
        !           981:        
        !           982:        hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);                    /* Unlock our stuff */
        !           983:        splx(s);                                                                                                /* Restore 'rupts */
        !           984:        
        !           985:        for(i = 0; i < nmapb; i++) {                                                    /* Allocate 'em all */
        !           986:                retr = kmem_alloc_wired(kernel_map, (vm_offset_t *)&mbn, PAGE_SIZE);    /* Find a virtual address to use */
        !           987:                if(retr != KERN_SUCCESS) {                                                      /* Did we get some memory? */
        !           988:                        panic("Whoops...  Not a bit of wired memory left for anyone\n");
        !           989:                }
        !           990:                mapping_free_init((vm_offset_t)mbn, -1, 0);                     /* Initialize on to the release queue */
        !           991:        }
        !           992: }
        !           993: 
        !           994: /*
        !           995:  *             void mapping_relpre(void) - Releases preallocation release hold off
        !           996:  *     
        !           997:  *             This routine removes the
        !           998:  *             hold off flag so that the adjust routine will free the extra mapping
        !           999:  *             blocks on the release list.  I don't like this, but I don't know
        !          1000:  *             how else to do this for now...
        !          1001:  *
        !          1002:  */
        !          1003: 
        !          1004: void mapping_relpre(void) {                                                                    /* Releases release hold off */
        !          1005: 
        !          1006:        spl_t           s;
        !          1007: 
        !          1008:        s = splhigh();                                                                                  /* Don't bother from now on */
        !          1009:        if(!hw_lock_to((hw_lock_t)&mapCtl.mapclock, LockTimeOut)) {             /* Lock the control header */ 
        !          1010:                panic("mapping_relpre - timeout getting control lock\n");       /* Tell all and die */
        !          1011:        }
        !          1012:        if(--mapCtl.mapcholdoff < 0) {                                                  /* Back down the hold off count */
        !          1013:                panic("mapping_relpre: hold-off count went negative\n");
        !          1014:        }
        !          1015: 
        !          1016:        hw_lock_unlock((hw_lock_t)&mapCtl.mapclock);                    /* Unlock our stuff */
        !          1017:        splx(s);                                                                                                /* Restore 'rupts */
        !          1018: }
        !          1019: 
        !          1020: /*
        !          1021:  *             void mapping_free_prime(void) - Primes the mapping block release list
        !          1022:  *
        !          1023:  *             See mapping_free_init.
        !          1024:  *             No locks can be held, because we allocate memory here.
        !          1025:  *             One processor running only.
        !          1026:  *
        !          1027:  */
        !          1028: 
        !          1029: void mapping_free_prime(void) {                                                                        /* Primes the mapping block release list */
        !          1030: 
        !          1031:        int     nmapb, i;
        !          1032:        kern_return_t   retr;
        !          1033:        mappingblok     *mbn;
        !          1034:        
        !          1035:        nmapb = (mapCtl.mapcfree + mapCtl.mapcinuse + MAPPERBLOK - 1) / MAPPERBLOK;     /* Get permanent allocation */
        !          1036:        nmapb = nmapb * 4;                                                                                      /* Get 4 times our initial allocation */
        !          1037: 
        !          1038: #if DEBUG
        !          1039:        kprintf("mapping_free_prime: free = %08X; in use = %08X; priming = %08X\n", 
        !          1040:          mapCtl.mapcfree, mapCtl.mapcinuse, nmapb);
        !          1041: #endif
        !          1042:        
        !          1043:        for(i = 0; i < nmapb; i++) {                                                            /* Allocate 'em all */
        !          1044:                retr = kmem_alloc_wired(kernel_map, (vm_offset_t *)&mbn, PAGE_SIZE);    /* Find a virtual address to use */
        !          1045:                if(retr != KERN_SUCCESS) {                                                              /* Did we get some memory? */
        !          1046:                        panic("Whoops...  Not a bit of wired memory left for anyone\n");
        !          1047:                }
        !          1048:                mapping_free_init((vm_offset_t)mbn, -1, 0);                             /* Initialize onto release queue */
        !          1049:        }
        !          1050: }
        !          1051: 
        !          1052: /*
        !          1053:  *             vm_offset_t     mapping_p2v(space_t space, phys_entry *pp) - Finds first virtual mapping of a physical page in a space
        !          1054:  *
        !          1055:  *             Gets a lock on the physical entry.  Then it searches the list of attached mappings for one with
        !          1056:  *             the same space.  If it finds it, it returns the virtual address.
        !          1057:  */
        !          1058: 
        !          1059: vm_offset_t    mapping_p2v(space_t space, struct phys_entry *pp) {             /* Finds first virtual mapping of a physical page in a space */
        !          1060: 
        !          1061:        spl_t                           s;
        !          1062:        register mapping        *mp, *mpv;
        !          1063:        vm_offset_t                     va;
        !          1064: 
        !          1065:        if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Try to get the lock on the physical entry */
        !          1066:                splx(s);                                                                                        /* Restore 'rupts */
        !          1067:                panic("mapping_p2v: timeout getting lock on physent\n");                        /* Arrrgghhhh! */
        !          1068:                return(0);                                                                                      /* Should die before here */
        !          1069:        }
        !          1070:        
        !          1071:        va = 0;                                                                                                 /* Assume failure */
        !          1072:        
        !          1073:        for(mpv = hw_cpv(pp->phys_link); mpv; mp = hw_cpv(mp->next)) {  /* Scan 'em all */
        !          1074:                
        !          1075:                if(!(((mpv->PTEv >> 7) & 0x000FFFFF) == space)) continue;       /* Skip all the rest if this is not the right space... */ 
        !          1076:                
        !          1077:                va = ((((unsigned int)mpv->PTEhash & -64) << 5) ^ (space  << 12)) & 0x003FF000; /* Backward hash to the wrapped VADDR */
        !          1078:                va = va | ((mpv->PTEv << 8) & 0xF0000000);                      /* Move in the segment number */
        !          1079:                va = va | ((mpv->PTEv << 22) & 0x0FC00000);                     /* Add in the API for the top of the address */
        !          1080:                break;                                                                                          /* We're done now, pass virtual address back */
        !          1081:        }
        !          1082:        
        !          1083:        hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);                               /* Unlock the physical entry */
        !          1084:        splx(s);                                                                                                /* Restore 'rupts */
        !          1085:        return(va);                                                                                             /* Return the result or 0... */
        !          1086: }
        !          1087: 
        !          1088: /*
        !          1089:  *     kvtophys(addr)
        !          1090:  *
        !          1091:  *     Convert a kernel virtual address to a physical address
        !          1092:  */
        !          1093: vm_offset_t kvtophys(vm_offset_t va) {
        !          1094: 
        !          1095:        register mapping                *mp, *mpv;
        !          1096:        register vm_offset_t    pa;
        !          1097:        spl_t                           s;
        !          1098:        
        !          1099:        s=splhigh();                                                                                    /* Don't bother from now on */
        !          1100:        mp = hw_lock_phys_vir(PPC_SID_KERNEL, va);                              /* Find mapping and lock the physical entry for this mapping */
        !          1101: 
        !          1102:        if((unsigned int)mp&1) {                                                                /* Did the lock on the phys entry time out? */
        !          1103:                splx(s);                                                                                        /* Restore 'rupts */
        !          1104:                panic("kvtophys: timeout obtaining lock on physical entry (vaddr=%08X)\n", va); /* Scream bloody murder! */
        !          1105:                return 0;
        !          1106:        }
        !          1107: 
        !          1108:        if(!mp) {                                                                                               /* If it was not found, or no physical entry */
        !          1109:                splx(s);                                                                                        /* Restore 'rupts */
        !          1110:                return 0;                                                                                       /* Return 0 */
        !          1111:        }
        !          1112: 
        !          1113:        mpv = hw_cpv(mp);                                                                               /* Convert to virtual addressing */
        !          1114:        
        !          1115:        if(!mpv->physent) {                                                                             /* Was there a physical entry? */
        !          1116:                pa = (vm_offset_t)((mpv->PTEr & -PAGE_SIZE) | ((unsigned int)va & (PAGE_SIZE-1)));      /* Get physical address from physent */
        !          1117:        }
        !          1118:        else {
        !          1119:                pa = (vm_offset_t)((mpv->physent->pte1 & -PAGE_SIZE) | ((unsigned int)va & (PAGE_SIZE-1)));     /* Get physical address from physent */
        !          1120:                hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);     /* Unlock the physical entry */
        !          1121:        }
        !          1122:        
        !          1123:        splx(s);                                                                                                /* Restore 'rupts */
        !          1124:        return pa;                                                                                              /* Return the physical address... */
        !          1125: }
        !          1126: 
        !          1127: /*
        !          1128:  *     phystokv(addr)
        !          1129:  *
        !          1130:  *     Convert a physical address to a kernel virtual address if
        !          1131:  *     there is a mapping, otherwise return NULL
        !          1132:  */
        !          1133: 
        !          1134: vm_offset_t phystokv(vm_offset_t pa) {
        !          1135: 
        !          1136:        struct phys_entry       *pp;
        !          1137:        vm_offset_t                     va;
        !          1138: 
        !          1139:        pp = pmap_find_physentry(pa);                                                   /* Find the physical entry */
        !          1140:        if (PHYS_NULL == pp) {
        !          1141:                return (vm_offset_t)NULL;                                                       /* If none, return null */
        !          1142:        }
        !          1143:        if(!(va=mapping_p2v(PPC_SID_KERNEL, pp))) {
        !          1144:                return 0;                                                                                       /* Can't find it, return 0... */
        !          1145:        }
        !          1146:        return (va | (pa & (PAGE_SIZE-1)));                                             /* Build and return VADDR... */
        !          1147: 
        !          1148: }
        !          1149: 
        !          1150: /*
        !          1151:  *             Enters translations into the autogen maps.
        !          1152:  *
        !          1153:  *             Not implemented yet, just stubbed out...
        !          1154:  */
        !          1155:  
        !          1156: boolean_t      autogen_map(space_t space, vm_offset_t va, vm_offset_t spa, vm_offset_t epa, vm_prot_t prot, int attr) { /* Build an autogen area */
        !          1157: 
        !          1158:                return(0);                                                                              /* Just return false for now */
        !          1159: }
        !          1160: 
        !          1161: 
        !          1162: /*
        !          1163:  *             Dumps out the mapping stuff associated with a virtual address
        !          1164:  */
        !          1165: void dumpaddr(space_t space, vm_offset_t va) {
        !          1166: 
        !          1167:        mapping         *mp, *mpv;
        !          1168:        vm_offset_t     pa;
        !          1169:        spl_t           s;
        !          1170: 
        !          1171:        s=splhigh();                                                                                    /* Don't bother me */
        !          1172: 
        !          1173:        mp = hw_lock_phys_vir(space, va);                                               /* Lock the physical entry for this mapping */
        !          1174:        if(!mp) {                                                                                               /* Did we find one? */
        !          1175:                splx(s);                                                                                        /* Restore the interrupt level */
        !          1176:                printf("dumpaddr: virtual address (%08X) not mapped\n", va);    
        !          1177:                return;                                                                                         /* Didn't find any, return FALSE... */
        !          1178:        }
        !          1179:        if((unsigned int)mp&1) {                                                                /* Did we timeout? */
        !          1180:                panic("dumpaddr: timeout locking physical entry for virtual address (%08X)\n", va);     /* Yeah, scream about it! */
        !          1181:                splx(s);                                                                                        /* Restore the interrupt level */
        !          1182:                return;                                                                                         /* Bad hair day, return FALSE... */
        !          1183:        }
        !          1184:        printf("dumpaddr: space=%08X; vaddr=%08X\n", space, va);        /* Say what address were dumping */
        !          1185:        mpv = hw_cpv(mp);                                                                               /* Get virtual address of mapping */
        !          1186:        dumpmapping(mpv);
        !          1187:        if(mpv->physent) {
        !          1188:                dumppca(mpv);
        !          1189:                hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);     /* Unlock physical entry associated with mapping */
        !          1190:        }
        !          1191:        splx(s);                                                                                                /* Was there something you needed? */
        !          1192:        return;                                                                                                 /* Tell them we did it */
        !          1193: }
        !          1194: 
        !          1195: 
        !          1196: 
        !          1197: /*
        !          1198:  *             Prints out a mapping control block
        !          1199:  *
        !          1200:  */
        !          1201:  
        !          1202: void dumpmapping(struct mapping *mp) {                                                 /* Dump out a mapping */
        !          1203: 
        !          1204:        printf("Dump of mapping block: %08X\n", mp);                    /* Header */
        !          1205:        printf("                 next: %08X\n", mp->next);                 
        !          1206:        printf("             hashnext: %08X\n", mp->hashnext);                 
        !          1207:        printf("              PTEhash: %08X\n", mp->PTEhash);                 
        !          1208:        printf("               PTEent: %08X\n", mp->PTEent);                 
        !          1209:        printf("              physent: %08X\n", mp->physent);                 
        !          1210:        printf("                 PTEv: %08X\n", mp->PTEv);                 
        !          1211:        printf("                 PTEr: %08X\n", mp->PTEr);                 
        !          1212:        printf("                 pmap: %08X\n", mp->pmap);
        !          1213:        
        !          1214:        if(mp->physent) {                                                                       /* Print physent if it exists */
        !          1215:                printf("Associated physical entry: %08X %08X\n", mp->physent->phys_link, mp->physent->pte1);
        !          1216:        }
        !          1217:        else {
        !          1218:                printf("Associated physical entry: none\n");
        !          1219:        }
        !          1220:        
        !          1221:        dumppca(mp);                                                                            /* Dump out the PCA information */
        !          1222:        
        !          1223:        return;
        !          1224: }
        !          1225: 
        !          1226: /*
        !          1227:  *             Prints out a PTEG control area
        !          1228:  *
        !          1229:  */
        !          1230:  
        !          1231: void dumppca(struct mapping *mp) {                                             /* PCA */
        !          1232: 
        !          1233:        PCA                             *pca;
        !          1234:        unsigned int    *pteg;
        !          1235:        
        !          1236:        pca = (PCA *)((unsigned int)mp->PTEhash&-64);           /* Back up to the start of the PCA */
        !          1237:        pteg=(unsigned int *)((unsigned int)pca-(((hash_table_base&0x0000FFFF)+1)<<16));
        !          1238:        printf(" Dump of PCA: %08X\n", pca);            /* Header */
        !          1239:        printf("     PCAlock: %08X\n", pca->PCAlock);                 
        !          1240:        printf("     PCAallo: %08X\n", pca->flgs.PCAallo);                 
        !          1241:        printf("     PCAhash: %08X %08X %08X %08X\n", pca->PCAhash[0], pca->PCAhash[1], pca->PCAhash[2], pca->PCAhash[3]);                 
        !          1242:        printf("              %08X %08X %08X %08X\n", pca->PCAhash[4], pca->PCAhash[5], pca->PCAhash[6], pca->PCAhash[7]);                 
        !          1243:        printf("Dump of PTEG: %08X\n", pteg);           /* Header */
        !          1244:        printf("              %08X %08X %08X %08X\n", pteg[0], pteg[1], pteg[2], pteg[3]);                 
        !          1245:        printf("              %08X %08X %08X %08X\n", pteg[4], pteg[5], pteg[6], pteg[7]);                 
        !          1246:        printf("              %08X %08X %08X %08X\n", pteg[8], pteg[9], pteg[10], pteg[11]);                 
        !          1247:        printf("              %08X %08X %08X %08X\n", pteg[12], pteg[13], pteg[14], pteg[15]);                 
        !          1248:        return;
        !          1249: }
        !          1250: 
        !          1251: /*
        !          1252:  *             Dumps starting with a physical entry
        !          1253:  */
        !          1254:  
        !          1255: void dumpphys(struct phys_entry *pp) {                                                 /* Dump from physent */
        !          1256: 
        !          1257:        mapping                 *mp;
        !          1258:        PCA                             *pca;
        !          1259:        unsigned int    *pteg;
        !          1260: 
        !          1261:        printf("Dump from physical entry %08X: %08X %08X\n", pp, pp->phys_link, pp->pte1);
        !          1262:        mp = hw_cpv(pp->phys_link);
        !          1263:        while(mp) {
        !          1264:                dumpmapping(mp);
        !          1265:                dumppca(mp);
        !          1266:                mp = hw_cpv(mp->next);
        !          1267:        }
        !          1268:        
        !          1269:        return;
        !          1270: }
        !          1271: 
        !          1272: /*
        !          1273:  *             void ignore_zero_fault(boolean_t) - Sets up to ignore or honor any fault on 
        !          1274:  *             page 0 access for the current thread.
        !          1275:  *
        !          1276:  *             If parameter is TRUE, faults are ignored
        !          1277:  *             If parameter is FALSE, faults are honored
        !          1278:  *
        !          1279:  */
        !          1280: 
        !          1281: void ignore_zero_fault(boolean_t type) {               /* Sets up to ignore or honor any fault on page 0 access for the current thread */
        !          1282: 
        !          1283:        if(type) current_act()->mact.specFlags |= ignoreZeroFault;      /* Ignore faults on page 0 */
        !          1284:        else     current_act()->mact.specFlags &= ~ignoreZeroFault;     /* Honor faults on page 0 */
        !          1285:        
        !          1286:        return;                                                                                         /* Return the result or 0... */
        !          1287: }
        !          1288: 
        !          1289: 
        !          1290: 
        !          1291: 
        !          1292: 
        !          1293: 
        !          1294: 
        !          1295: 

unix.superglobalmegacorp.com

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