Annotation of XNU/osfmk/ppc/pmap.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:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: /*
        !            26:  * Mach Operating System
        !            27:  * Copyright (c) 1990,1991,1992 The University of Utah and
        !            28:  * the Center for Software Science (CSS).
        !            29:  * Copyright (c) 1991,1987 Carnegie Mellon University.
        !            30:  * All rights reserved.
        !            31:  *
        !            32:  * Permission to use, copy, modify and distribute this software and its
        !            33:  * documentation is hereby granted, provided that both the copyright
        !            34:  * notice and this permission notice appear in all copies of the
        !            35:  * software, derivative works or modified versions, and any portions
        !            36:  * thereof, and that both notices appear in supporting documentation,
        !            37:  * and that all advertising materials mentioning features or use of
        !            38:  * this software display the following acknowledgement: ``This product
        !            39:  * includes software developed by the Center for Software Science at
        !            40:  * the University of Utah.''
        !            41:  *
        !            42:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF
        !            43:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
        !            44:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
        !            45:  * THIS SOFTWARE.
        !            46:  *
        !            47:  * CSS requests users of this software to return to [email protected] any
        !            48:  * improvements that they make and grant CSS redistribution rights.
        !            49:  *
        !            50:  * Carnegie Mellon requests users of this software to return to
        !            51:  *  Software Distribution Coordinator  or  [email protected]
        !            52:  *  School of Computer Science
        !            53:  *  Carnegie Mellon University
        !            54:  *  Pittsburgh PA 15213-3890
        !            55:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            56:  * the rights to redistribute these changes.
        !            57:  *
        !            58:  *     Utah $Hdr: pmap.c 1.28 92/06/23$
        !            59:  *     Author: Mike Hibler, Bob Wheeler, University of Utah CSS, 10/90
        !            60:  */
        !            61:  
        !            62: /*
        !            63:  *     Manages physical address maps for powerpc.
        !            64:  *
        !            65:  *     In addition to hardware address maps, this
        !            66:  *     module is called upon to provide software-use-only
        !            67:  *     maps which may or may not be stored in the same
        !            68:  *     form as hardware maps.  These pseudo-maps are
        !            69:  *     used to store intermediate results from copy
        !            70:  *     operations to and from address spaces.
        !            71:  *
        !            72:  *     Since the information managed by this module is
        !            73:  *     also stored by the logical address mapping module,
        !            74:  *     this module may throw away valid virtual-to-physical
        !            75:  *     mappings at almost any time.  However, invalidations
        !            76:  *     of virtual-to-physical mappings must be done as
        !            77:  *     requested.
        !            78:  *
        !            79:  *     In order to cope with hardware architectures which
        !            80:  *     make virtual-to-physical map invalidates expensive,
        !            81:  *     this module may delay invalidate or reduced protection
        !            82:  *     operations until such time as they are actually
        !            83:  *     necessary.  This module is given full information to
        !            84:  *     when physical maps must be made correct.
        !            85:  *     
        !            86:  */
        !            87: 
        !            88: #include <cpus.h>
        !            89: #include <debug.h>
        !            90: #include <mach_kgdb.h>
        !            91: #include <mach_vm_debug.h>
        !            92: #include <db_machine_commands.h>
        !            93: 
        !            94: #include <kern/thread.h>
        !            95: #include <mach/vm_attributes.h>
        !            96: #include <mach/vm_param.h>
        !            97: #include <kern/spl.h>
        !            98: 
        !            99: #include <kern/misc_protos.h>
        !           100: #include <ppc/misc_protos.h>
        !           101: #include <ppc/proc_reg.h>
        !           102: 
        !           103: #include <vm/pmap.h>
        !           104: #include <vm/vm_map.h>
        !           105: #include <vm/vm_page.h>
        !           106: 
        !           107: #include <ppc/pmap.h>
        !           108: #include <ppc/pmap_internals.h>
        !           109: #include <ppc/mem.h>
        !           110: #include <ppc/mappings.h>
        !           111: 
        !           112: #include <ppc/new_screen.h>
        !           113: #include <ppc/Firmware.h>
        !           114: #include <ppc/savearea.h>
        !           115: #include <ddb/db_output.h>
        !           116: 
        !           117: #if    DB_MACHINE_COMMANDS
        !           118: /* optionally enable traces of pmap operations in post-mortem trace table */
        !           119: /* #define PMAP_LOWTRACE 1 */
        !           120: #define PMAP_LOWTRACE 0
        !           121: #else  /* DB_MACHINE_COMMANDS */
        !           122: /* Can not trace even if we wanted to */
        !           123: #define PMAP_LOWTRACE 0
        !           124: #endif /* DB_MACHINE_COMMANDS */
        !           125: 
        !           126: #define PERFTIMES 0
        !           127: 
        !           128: #if PERFTIMES && DEBUG
        !           129: #define debugLog2(a, b, c) dbgLog2(a, b, c)
        !           130: #else
        !           131: #define debugLog2(a, b, c)
        !           132: #endif
        !           133: 
        !           134: extern unsigned int    avail_remaining;
        !           135: extern unsigned int    mappingdeb0;
        !           136: extern struct  Saveanchor saveanchor;                                          /* Aliged savearea anchor */
        !           137: unsigned int debugbackpocket;                                                          /* (TEST/DEBUG) */
        !           138: 
        !           139: vm_offset_t            avail_next;
        !           140: vm_offset_t            first_free_virt;
        !           141: int            current_free_region;                                            /* Used in pmap_next_page */
        !           142: 
        !           143: /* forward */
        !           144: void pmap_activate(pmap_t pmap, thread_t th, int which_cpu);
        !           145: void pmap_deactivate(pmap_t pmap, thread_t th, int which_cpu);
        !           146: void copy_to_phys(vm_offset_t sva, vm_offset_t dpa, int bytecount);
        !           147: 
        !           148: #if MACH_VM_DEBUG
        !           149: int pmap_list_resident_pages(pmap_t pmap, vm_offset_t *listp, int space);
        !           150: #endif
        !           151: 
        !           152: #if DEBUG
        !           153: #define PDB_USER       0x01    /* exported functions */
        !           154: #define PDB_MAPPING    0x02    /* low-level mapping routines */
        !           155: #define PDB_ENTER      0x04    /* pmap_enter specifics */
        !           156: #define PDB_COPY       0x08    /* copy page debugging */
        !           157: #define PDB_ZERO       0x10    /* zero page debugging */
        !           158: #define PDB_WIRED      0x20    /* things concerning wired entries */
        !           159: #define PDB_PTEG       0x40    /* PTEG overflows */
        !           160: #define PDB_LOCK       0x100   /* locks */
        !           161: #define PDB_IO         0x200   /* Improper use of WIMG_IO checks - PCI machines */
        !           162: 
        !           163: int pmdebug=0;
        !           164: 
        !           165: #define PCI_BASE       0x80000000
        !           166: #endif
        !           167: 
        !           168: struct pmap    kernel_pmap_store;
        !           169: pmap_t         kernel_pmap;
        !           170: struct zone    *pmap_zone;             /* zone of pmap structures */
        !           171: boolean_t      pmap_initialized = FALSE;
        !           172: 
        !           173: /*
        !           174:  * Physical-to-virtual translations are handled by inverted page table
        !           175:  * structures, phys_tables.  Multiple mappings of a single page are handled
        !           176:  * by linking the affected mapping structures. We initialise one region
        !           177:  * for phys_tables of the physical memory we know about, but more may be
        !           178:  * added as it is discovered (eg. by drivers).
        !           179:  */
        !           180: struct phys_entry *phys_table; /* For debugging */
        !           181: 
        !           182: lock_t pmap_system_lock;
        !           183: 
        !           184: decl_simple_lock_data(,tlb_system_lock)
        !           185: 
        !           186: /*
        !           187:  *     free pmap list. caches the first free_pmap_max pmaps that are freed up
        !           188:  */
        !           189: int            free_pmap_max = 32;
        !           190: int            free_pmap_count;
        !           191: queue_head_t   free_pmap_list;
        !           192: decl_simple_lock_data(,free_pmap_lock)
        !           193: 
        !           194: /*
        !           195:  * Function to get index into phys_table for a given physical address
        !           196:  */
        !           197: 
        !           198: struct phys_entry *pmap_find_physentry(vm_offset_t pa)
        !           199: {
        !           200:        int i;
        !           201:        struct phys_entry *entry;
        !           202: 
        !           203:        for (i = pmap_mem_regions_count-1; i >= 0; i--) {
        !           204:                if (pa < pmap_mem_regions[i].start)
        !           205:                        continue;
        !           206:                if (pa >= pmap_mem_regions[i].end)
        !           207:                        return PHYS_NULL;
        !           208:                
        !           209:                entry = &pmap_mem_regions[i].phys_table[(pa - pmap_mem_regions[i].start) >> PPC_PGSHIFT];
        !           210:                __asm__ volatile("dcbt 0,%0" : : "r" (entry));  /* We will use this in a little bit */
        !           211:                return entry;
        !           212:        }
        !           213:        kprintf("DEBUG : pmap_find_physentry 0x%08x out of range\n",pa);
        !           214:        return PHYS_NULL;
        !           215: }
        !           216: 
        !           217: /*
        !           218:  * kern_return_t
        !           219:  * pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa,
        !           220:  *                          boolean_t available, unsigned int attr)
        !           221:  *     Allocate some extra physentries for the physical addresses given,
        !           222:  *     specifying some default attribute that on the powerpc specifies
        !           223:  *      the default cachability for any mappings using these addresses
        !           224:  *     If the memory is marked as available, it is added to the general
        !           225:  *     VM pool, otherwise it is not (it is reserved for card IO etc).
        !           226:  */
        !           227: kern_return_t pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa,
        !           228:                                       boolean_t available, unsigned int attr)
        !           229: {
        !           230:        int i,j;
        !           231:        spl_t s;
        !           232: 
        !           233:        /* Only map whole pages */
        !           234:        
        !           235:        panic("Forget it! You can't map no more memory, you greedy puke!\n");
        !           236: 
        !           237:        spa = trunc_page(spa);
        !           238:        epa = round_page(epa);
        !           239: 
        !           240:        /* First check that the region doesn't already exist */
        !           241: 
        !           242:        assert (epa >= spa);
        !           243:        for (i = 0; i < pmap_mem_regions_count; i++) {
        !           244:                /* If we're below the next region, then no conflict */
        !           245:                if (epa < pmap_mem_regions[i].start)
        !           246:                        break;
        !           247:                if (spa < pmap_mem_regions[i].end) {
        !           248: #if DEBUG
        !           249:                        kprintf("pmap_add_physical_memory(0x%08x,0x%08x,0x%08x) - memory already present\n",spa,epa,attr);
        !           250: #endif /* DEBUG */
        !           251:                        return KERN_NO_SPACE;
        !           252:                }
        !           253:        }
        !           254: 
        !           255: #if DEBUG
        !           256:        kprintf("pmap_add_physical_memory; region insert spot: %d out of %d\n", i, pmap_mem_regions_count);     /* (TEST/DEBUG) */
        !           257: #endif
        !           258: 
        !           259:        /* Check that we've got enough space for another region */
        !           260:        if (pmap_mem_regions_count == PMAP_MEM_REGION_MAX)
        !           261:                return KERN_RESOURCE_SHORTAGE;
        !           262: 
        !           263:        /* Once here, i points to the mem_region above ours in physical mem */
        !           264: 
        !           265:        /* allocate a new phys_table for this new region */
        !           266: #if DEBUG
        !           267:        kprintf("pmap_add_physical_memory; kalloc\n");  /* (TEST/DEBUG) */
        !           268: #endif
        !           269: 
        !           270:        phys_table =  (struct phys_entry *)
        !           271:                kalloc(sizeof(struct phys_entry) * atop(epa-spa));
        !           272: #if DEBUG
        !           273:        kprintf("pmap_add_physical_memory; new phys_table: %08X\n", phys_table);        /* (TEST/DEBUG) */
        !           274: #endif
        !           275: 
        !           276:        /* Initialise the new phys_table entries */
        !           277:        for (j = 0; j < atop(epa-spa); j++) {
        !           278:                
        !           279:                phys_table[j].phys_link = MAPPING_NULL;
        !           280:                
        !           281:                mapping_phys_init(&phys_table[j], spa+(j*PAGE_SIZE), attr);     /* Initialize the hardware specific portions */
        !           282: 
        !           283:        }
        !           284:        s = splhigh();
        !           285:        
        !           286:        /* Move all the phys_table entries up some to make room in
        !           287:         * the ordered list.
        !           288:         */
        !           289:        for (j = pmap_mem_regions_count; j > i ; j--)
        !           290:                pmap_mem_regions[j] = pmap_mem_regions[j-1];
        !           291: 
        !           292:        /* Insert a new entry with some memory to back it */
        !           293: 
        !           294:        pmap_mem_regions[i].start            = spa;
        !           295:        pmap_mem_regions[i].end           = epa;
        !           296:        pmap_mem_regions[i].phys_table    = phys_table;
        !           297: 
        !           298:        pmap_mem_regions_count++;
        !           299:        splx(s);
        !           300:        
        !           301: #if DEBUG
        !           302:        for(i=0; i<pmap_mem_regions_count; i++) {                       /* (TEST/DEBUG) */
        !           303:                kprintf("region %d: %08X %08X %08X\n", i, pmap_mem_regions[i].start,
        !           304:                        pmap_mem_regions[i].end, pmap_mem_regions[i].phys_table);       /* (TEST/DEBUG) */
        !           305:        }
        !           306: #endif
        !           307: 
        !           308:        if (available) {
        !           309:                kprintf("warning : pmap_add_physical_mem() "
        !           310:                       "available not yet supported\n");
        !           311:        }
        !           312: 
        !           313:        return KERN_SUCCESS;
        !           314: }
        !           315: 
        !           316: /*
        !           317:  * pmap_map(va, spa, epa, prot)
        !           318:  *     is called during boot to map memory in the kernel's address map.
        !           319:  *     A virtual address range starting at "va" is mapped to the physical
        !           320:  *     address range "spa" to "epa" with machine independent protection
        !           321:  *     "prot".
        !           322:  *
        !           323:  *     "va", "spa", and "epa" are byte addresses and must be on machine
        !           324:  *     independent page boundaries.
        !           325:  *
        !           326:  *     If we can allocate an autogen area, we will.  Autogenned area are contiguous physical
        !           327:  *     pages with a contiguous virtual address range, the same protection, and attributes.
        !           328:  *     The autogen_map routine tells us if it could do it or not.
        !           329:  */
        !           330: vm_offset_t
        !           331: pmap_map(
        !           332:        vm_offset_t va,
        !           333:        vm_offset_t spa,
        !           334:        vm_offset_t epa,
        !           335:        vm_prot_t prot)
        !           336: {
        !           337: 
        !           338: 
        !           339:        if (spa == epa)
        !           340:                return(va);
        !           341: 
        !           342:        assert(epa > spa);
        !           343: 
        !           344:        if(autogen_map(kernel_pmap->space, va, spa, epa, prot, PTE_WIMG_DEFAULT)) return(va);   /* Allocate an autogen area if we can */
        !           345:        
        !           346: 
        !           347:        debugLog2(40, va, spa);                                                         /* Log pmap_map call */
        !           348: 
        !           349:        while (spa < epa) {
        !           350:                pmap_enter(kernel_pmap, va, spa, prot, TRUE);
        !           351: 
        !           352:                va += PAGE_SIZE;
        !           353:                spa += PAGE_SIZE;
        !           354:        }
        !           355:        
        !           356:        debugLog2(41, epa, prot);                                                               /* Log pmap_map call */
        !           357: 
        !           358:        return(va);
        !           359: }
        !           360: 
        !           361: /*
        !           362:  * pmap_map_bd(va, spa, epa, prot)
        !           363:  *     Back-door routine for mapping kernel VM at initialisation.
        !           364:  *     Used for mapping memory outside the known physical memory
        !           365:  *      space, with caching disabled. Designed for use by device probes.
        !           366:  * 
        !           367:  *     A virtual address range starting at "va" is mapped to the physical
        !           368:  *     address range "spa" to "epa" with machine independent protection
        !           369:  *     "prot".
        !           370:  *
        !           371:  *     "va", "spa", and "epa" are byte addresses and must be on machine
        !           372:  *     independent page boundaries.
        !           373:  *
        !           374:  * WARNING: The current version of memcpy() can use the dcbz instruction
        !           375:  * on the destination addresses.  This will cause an alignment exception
        !           376:  * and consequent overhead if the destination is caching-disabled.  So
        !           377:  * avoid memcpy()ing into the memory mapped by this function.
        !           378:  *
        !           379:  * also, many other pmap_ routines will misbehave if you try and change
        !           380:  * protections or remove these mappings, they are designed to be permanent.
        !           381:  *
        !           382:  * These areas will be added to the autogen list, if possible.  Existing translations
        !           383:  * are overridden and their mapping stuctures are released.  This takes place in
        !           384:  * the autogen_map function.
        !           385:  *
        !           386:  * Locking:
        !           387:  *     this routine is called only during system initialization when only
        !           388:  *     one processor is active, so no need to take locks...
        !           389:  */
        !           390: vm_offset_t
        !           391: pmap_map_bd(
        !           392:        vm_offset_t va,
        !           393:        vm_offset_t spa,
        !           394:        vm_offset_t epa,
        !           395:        vm_prot_t prot)
        !           396: {
        !           397:        spl_t   spl;
        !           398:        register struct mapping *mp;
        !           399:        register struct phys_entry      *pp;
        !           400:        
        !           401: 
        !           402:        if (spa == epa)
        !           403:                return(va);
        !           404: 
        !           405:        assert(epa > spa);
        !           406: 
        !           407:        debugLog2(42, va, epa);                                                         /* Log pmap_map call */
        !           408: 
        !           409:        spl = splhigh();
        !           410: 
        !           411:        if(autogen_map(PPC_SID_KERNEL, va, spa, epa, prot, PTE_WIMG_IO)) {      /* Allocate an autogen area if we can */
        !           412:                splx(spl);                                                                              /* Ok, we allocated one, set back the spl */
        !           413: 
        !           414:                debugLog2(43, epa, prot);                                                               /* Log pmap_map call */
        !           415: 
        !           416:                return(va);                                                                             /* Return... */
        !           417:        }
        !           418: 
        !           419:        while (spa < epa) {
        !           420:        
        !           421: 
        !           422:                mapping_remove(PPC_SID_KERNEL, va);                             /* Remove any active mapping for this VADDR */
        !           423: 
        !           424:                pp = pmap_find_physentry(spa);                                  /* Get the physent, note, it's ok to fail, 
        !           425:                                                                                                                   we don't care about a physical page here */
        !           426:                mapping_make(kernel_pmap, PPC_SID_KERNEL, pp, va, spa, prot, PTE_WIMG_IO);      /* Make the address mapping*/
        !           427:                
        !           428:                va += PAGE_SIZE;
        !           429:                spa += PAGE_SIZE;
        !           430:        }
        !           431: 
        !           432:        splx(spl);
        !           433: 
        !           434:        debugLog2(43, epa, prot);                                                               /* Log pmap_map call */
        !           435: 
        !           436:        return(va);
        !           437: }
        !           438: 
        !           439: /*
        !           440:  *     Bootstrap the system enough to run with virtual memory.
        !           441:  *     Map the kernel's code and data, and allocate the system page table.
        !           442:  *     Called with mapping done by BATs. Page_size must already be set.
        !           443:  *
        !           444:  *     Parameters:
        !           445:  *     mem_size:       Total memory present
        !           446:  *     first_avail:    First virtual address available
        !           447:  *     first_phys_avail:       First physical address available
        !           448:  */
        !           449: void
        !           450: pmap_bootstrap(unsigned int mem_size, vm_offset_t *first_avail, vm_offset_t *first_phys_avail, unsigned int kmapsize)
        !           451: {
        !           452:        register struct mapping *mp;
        !           453:        vm_offset_t     addr;
        !           454:        vm_size_t               size;
        !           455:        int                     i, num, j, rsize, mapsize, vmpagesz, vmmapsz;
        !           456:        unsigned int     mask;
        !           457:        vm_offset_t             first_used_addr;
        !           458:        PCA                             *pcaptr;
        !           459:        savectl                 *savec, *savec2;
        !           460:        vm_offset_t             save, save2;
        !           461: 
        !           462:        *first_avail = round_page(*first_avail);
        !           463:        
        !           464: #if DEBUG
        !           465:        kprintf("first_avail=%08X; first_phys_avail=%08X; avail_remaining=%d\n", 
        !           466:                *first_avail, *first_phys_avail, avail_remaining);
        !           467: #endif
        !           468: 
        !           469:        assert(PAGE_SIZE == PPC_PGBYTES);
        !           470: 
        !           471:        /*
        !           472:         * Initialize kernel pmap
        !           473:         */
        !           474:        kernel_pmap = &kernel_pmap_store;
        !           475: 
        !           476:        lock_init(&pmap_system_lock,
        !           477:                  FALSE,                /* NOT a sleep lock */
        !           478:                  ETAP_VM_PMAP_SYS,
        !           479:                  ETAP_VM_PMAP_SYS_I);
        !           480: 
        !           481:        simple_lock_init(&kernel_pmap->lock, ETAP_VM_PMAP_KERNEL);
        !           482: 
        !           483:        kernel_pmap->ref_count = 1;
        !           484:        kernel_pmap->space = PPC_SID_KERNEL;
        !           485: 
        !           486:        /*
        !           487:         * Allocate: (from first_avail up)
        !           488:         *      Aligned to its own size:
        !           489:         *       hash table (for mem size 2**x, allocate 2**(x-10) entries)
        !           490:         *       mapping table (same size and immediatly following hash table)
        !           491:         */
        !           492:        /* hash_table_size must be a power of 2, recommended sizes are
        !           493:         * taken from PPC601 User Manual, table 6-19. We take the next
        !           494:         * highest size if mem_size is not a power of two.
        !           495:         * TODO NMGS make this configurable at boot time.
        !           496:         */
        !           497: 
        !           498:        num = sizeof(pte_t) * (mem_size >> 10);
        !           499: 
        !           500:        for (hash_table_size = 64 * 1024;       /* minimum size = 64Kbytes */
        !           501:             hash_table_size < num; 
        !           502:             hash_table_size *= 2)
        !           503:                continue;
        !           504: 
        !           505:        /* Scale to within any physical memory layout constraints */
        !           506:        do {
        !           507:                num = atop(mem_size);   /* num now holds mem_size in pages */
        !           508: 
        !           509:                /* size of all structures that we're going to allocate */
        !           510: 
        !           511:                size = (vm_size_t) (
        !           512:                        (InitialSaveBloks * PAGE_SIZE) +        /* Allow space for the initial context saveareas */
        !           513:                        (8 * PAGE_SIZE) +                                       /* For backpocket saveareas */
        !           514:                        hash_table_size +                                       /* For hash table */
        !           515:                        hash_table_size +                                       /* For PTEG allocation table */
        !           516:                        (num * sizeof(struct phys_entry))       /* For the physical entries */
        !           517:                        );
        !           518: 
        !           519:                mapsize = size = round_page(size);              /* Get size of area to map that we just calculated */
        !           520:                mapsize = mapsize + kmapsize;                   /* Account for the kernel text size */
        !           521: 
        !           522:                vmpagesz = round_page(num * sizeof(struct vm_page));    /* Allow for all vm_pages needed to map physical mem */
        !           523:                vmmapsz = round_page((num / 2) * sizeof(struct vm_map_entry));  /* Allow for vm_maps */
        !           524:                
        !           525:                mapsize = mapsize + vmpagesz + vmmapsz; /* Add the VM system estimates into the grand total */
        !           526: 
        !           527:                mapsize = mapsize + (4 * 1024 * 1024);  /* Allow for 4 meg of extra mappings */
        !           528:                mapsize = ((mapsize / PAGE_SIZE) + MAPPERBLOK - 1) / MAPPERBLOK;        /* Get number of blocks of mappings we need */
        !           529:                mapsize = mapsize + ((mapsize  + MAPPERBLOK - 1) / MAPPERBLOK); /* Account for the mappings themselves */
        !           530: 
        !           531: #if DEBUG
        !           532:                kprintf("pmap_bootstrap: initial vm_pages     = %08X\n", vmpagesz);
        !           533:                kprintf("pmap_bootstrap: initial vm_maps      = %08X\n", vmmapsz);
        !           534:                kprintf("pmap_bootstrap: size before mappings = %08X\n", size);
        !           535:                kprintf("pmap_bootstrap: kernel map size      = %08X\n", kmapsize);
        !           536:                kprintf("pmap_bootstrap: mapping blocks rqrd  = %08X\n", mapsize);
        !           537: #endif
        !           538:                
        !           539:                size = size + (mapsize * PAGE_SIZE);    /* Get the true size we need */
        !           540: 
        !           541:                /* hash table must be aligned to its size */
        !           542: 
        !           543:                addr = (*first_avail +
        !           544:                        (hash_table_size-1)) & ~(hash_table_size-1);
        !           545: 
        !           546:                if (addr + size > pmap_mem_regions[0].end) {
        !           547:                        hash_table_size /= 2;
        !           548:                } else {
        !           549:                        break;
        !           550:                }
        !           551:                /* If we have had to shrink hash table to too small, panic */
        !           552:                if (hash_table_size == 32 * 1024)
        !           553:                        panic("cannot lay out pmap memory map correctly");
        !           554:        } while (1);
        !           555:        
        !           556: #if DEBUG
        !           557:        kprintf("hash table size=%08X, total size of area=%08X, addr=%08X\n", 
        !           558:                hash_table_size, size, addr);
        !           559: #endif
        !           560:        if (round_page(*first_phys_avail) < trunc_page(addr)) {
        !           561:                /* We are stepping over at least one page here, so
        !           562:                 * add this region to the free regions so that it can
        !           563:                 * be allocated by pmap_steal
        !           564:                 */
        !           565:                free_regions[free_regions_count].start = round_page(*first_phys_avail);
        !           566:                free_regions[free_regions_count].end = trunc_page(addr);
        !           567: 
        !           568:                avail_remaining += (free_regions[free_regions_count].end -
        !           569:                                    free_regions[free_regions_count].start) /
        !           570:                                            PPC_PGBYTES;
        !           571: #if DEBUG
        !           572:                kprintf("ADDED FREE REGION from 0x%08x to 0x%08x, avail_remaining = %d\n",
        !           573:                        free_regions[free_regions_count].start,free_regions[free_regions_count].end, 
        !           574:                        avail_remaining);
        !           575: #endif /* DEBUG */
        !           576:                free_regions_count++;
        !           577:        }
        !           578: 
        !           579:        /* Zero everything - this also invalidates the hash table entries */
        !           580:        bzero((char *)addr, size);
        !           581: 
        !           582:        /* Set up some pointers to our new structures */
        !           583: 
        !           584:        /* from here,  addr points to the next free address */
        !           585:        
        !           586:        first_used_addr = addr; /* remember where we started */
        !           587: 
        !           588:        /* Set up hash table address and dma buffer address, keeping
        !           589:         * alignment. These mappings are all 1-1,  so dma_r == dma_v
        !           590:         * 
        !           591:         * If hash_table_size == dma_buffer_alignment, then put hash_table
        !           592:         * first, since dma_buffer_size may be smaller than alignment, but
        !           593:         * hash table alignment==hash_table_size.
        !           594:         */
        !           595:        hash_table_base = addr;
        !           596:                
        !           597:        addr += hash_table_size;
        !           598:        addr += hash_table_size;                                                        /* Add another for the PTEG Control Area */
        !           599:        assert((hash_table_base & (hash_table_size-1)) == 0);
        !           600: 
        !           601:        pcaptr = (PCA *)(hash_table_base+hash_table_size);      /* Point to the PCA table */
        !           602:        
        !           603:        for(i=0; i < (hash_table_size/64) ; i++) {                      /* For all of PTEG control areas: */
        !           604:                pcaptr[i].flgs.PCAalflgs.PCAfree=0xFF;                  /* Mark all slots free */
        !           605:                pcaptr[i].flgs.PCAalflgs.PCAsteal=0x01;                 /* Initialize steal position */
        !           606:        }
        !           607:        
        !           608: /*
        !           609:  *             Allocate our initial context save areas.  As soon as we do this,
        !           610:  *             we can take an interrupt. We do the saveareas here, 'cause they're guaranteed
        !           611:  *             to be at least page aligned.
        !           612:  */
        !           613:        save2 = addr;                                                                           /* Remember first page */       
        !           614:        save =  addr;                                                                           /* Point to the whole block of blocks */        
        !           615:        savec2 = (savectl *)(addr + PAGE_SIZE - sizeof(savectl));       /* Point to the first's control area */
        !           616: 
        !           617:        for(i=0; i < InitialSaveBloks; i++) {                           /* Initialize the saveareas */
        !           618: 
        !           619:                savec = (savectl *)(save + PAGE_SIZE - sizeof(savectl));        /* Get the control area for this one */
        !           620: 
        !           621:                savec->sac_alloc = sac_empty;                                   /* Mark both free */
        !           622:                savec->sac_vrswap = 0;                                                  /* V=R, so the translation factor is 0 */
        !           623:                savec->sac_flags = sac_perm;                                    /* Mark it permanent */
        !           624: 
        !           625:                savec->sac_flags |= 0x0000EE00;                                 /* (TEST/DEBUG) */
        !           626: 
        !           627:                save += PAGE_SIZE;                                                              /* Jump up to the next one now */
        !           628:                
        !           629:                savec->sac_next = (unsigned int *)save;                 /* Link these two */
        !           630:        
        !           631:        }
        !           632:        
        !           633:        savec->sac_next = (unsigned int *)0;                            /* Clear the forward pointer for the last */
        !           634:        savec2->sac_alloc &= 0x7FFFFFFF;                                        /* Mark the first one in use */
        !           635: 
        !           636:        saveanchor.savefree             = (unsigned int)save2;          /* Point to the first one */
        !           637:        saveanchor.savecount    = InitialSaveBloks * sac_cnt;   /* The total number of save areas allocated */
        !           638:        saveanchor.saveinuse    = 1;                                            /* Number of areas in use */
        !           639:        saveanchor.savemin              = InitialSaveMin;                       /* We abend if lower than this */
        !           640:        saveanchor.saveneghyst  = InitialNegHysteresis;         /* The minimum number to keep free (must be a multiple of sac_cnt) */
        !           641:        saveanchor.savetarget   = InitialSaveTarget;            /* The target point for free save areas (must be a multiple of sac_cnt) */
        !           642:        saveanchor.saveposhyst  = InitialPosHysteresis;         /* The high water mark for free save areas (must be a multiple of sac_cnt) */
        !           643:        __asm__ volatile ("mtsprg 1, %0" : : "r" (save2));      /* Tell the exception handler about it */
        !           644:                
        !           645:        addr += InitialSaveBloks * PAGE_SIZE;                           /* Move up the next free address */
        !           646: 
        !           647:        save2 = addr;                                                                           
        !           648:        save =  addr;                                                                           
        !           649:        savec2 = (savectl *)(addr + PAGE_SIZE - sizeof(savectl));       
        !           650: 
        !           651:        for(i=0; i < 8; i++) {                                                          /* Allocate backpocket saveareas */
        !           652:        
        !           653:                savec = (savectl *)(save + PAGE_SIZE - sizeof(savectl));        
        !           654:        
        !           655:                savec->sac_alloc = sac_empty;                                   
        !           656:                savec->sac_vrswap = 0;                                                  
        !           657:                savec->sac_flags = sac_perm;                                    
        !           658:                savec->sac_flags |= 0x0000EE00;                                 
        !           659:                
        !           660:                save += PAGE_SIZE;                                                              
        !           661:                
        !           662:                savec->sac_next = (unsigned int *)save;                 
        !           663:        
        !           664:        }
        !           665:        
        !           666:        savec->sac_next = (unsigned int *)0;                            
        !           667:        savec2->sac_alloc &= 0x7FFFFFFF;                                        
        !           668:        debugbackpocket = save2;                                                        
        !           669:        addr += 8 * PAGE_SIZE;                                                          
        !           670:                        
        !           671:        /* phys_table is static to help debugging,
        !           672:         * this variable is no longer actually used
        !           673:         * outside of this scope
        !           674:         */
        !           675: 
        !           676:        phys_table = (struct phys_entry *) addr;
        !           677: 
        !           678: #if DEBUG
        !           679:        kprintf("hash_table_base                 =%08X\n", hash_table_base);
        !           680:        kprintf("phys_table                      =%08X\n", phys_table);
        !           681:        kprintf("pmap_mem_regions_count          =%08X\n", pmap_mem_regions_count);
        !           682: #endif
        !           683: 
        !           684:        for (i = 0; i < pmap_mem_regions_count; i++) {
        !           685:                
        !           686:                pmap_mem_regions[i].phys_table = phys_table;
        !           687:                rsize = (pmap_mem_regions[i].end - (unsigned int)pmap_mem_regions[i].start)/PAGE_SIZE;
        !           688:                
        !           689: #if DEBUG
        !           690:                kprintf("Initializing physical table for region %d\n", i);
        !           691:                kprintf("   table=%08X, size=%08X, start=%08X, end=%08X\n",
        !           692:                        phys_table, rsize, pmap_mem_regions[i].start, 
        !           693:                        (unsigned int)pmap_mem_regions[i].end);
        !           694: #endif         
        !           695:                
        !           696:                for (j = 0; j < rsize; j++) {
        !           697:                        phys_table[j].phys_link = MAPPING_NULL;
        !           698:                        mapping_phys_init(&phys_table[j], (unsigned int)pmap_mem_regions[i].start+(j*PAGE_SIZE), 
        !           699:                                PTE_WIMG_DEFAULT);                                              /* Initializes hw specific storage attributes */
        !           700:                }
        !           701:                phys_table = phys_table +
        !           702:                        atop(pmap_mem_regions[i].end - pmap_mem_regions[i].start);
        !           703:        }
        !           704: 
        !           705:        /* restore phys_table for debug */
        !           706:        phys_table = (struct phys_entry *) addr;
        !           707: 
        !           708:        addr += sizeof(struct phys_entry) * num;
        !           709:        
        !           710:        simple_lock_init(&tlb_system_lock, ETAP_VM_PMAP_TLB);
        !           711: 
        !           712:        /* Initialise the registers necessary for supporting the hashtable */
        !           713: #if DEBUG
        !           714:        kprintf("*** hash_table_init: base=%08X, size=%08X\n", hash_table_base, hash_table_size);
        !           715: #endif
        !           716: 
        !           717:        hash_table_init(hash_table_base, hash_table_size);
        !           718:                        
        !           719: /*
        !           720:  *             Remaining space is for mapping entries.  Tell the initializer routine that
        !           721:  *             the mapping system can't release this block because it's permanently assigned
        !           722:  */
        !           723: 
        !           724:        mapping_init();                                                                 /* Initialize the mapping tables */
        !           725: 
        !           726:        for(i = addr; i < first_used_addr + size; i += PAGE_SIZE) {     /* Add initial mapping blocks */
        !           727:                mapping_free_init(i, 1, 0);                                     /* Pass block address and say that this one is not releasable */
        !           728:        }
        !           729:        mapCtl.mapcmin = MAPPERBLOK;                                    /* Make sure we only adjust one at a time */
        !           730: 
        !           731: #if DEBUG
        !           732: 
        !           733:        kprintf("mapping kernel memory from 0x%08x to 0x%08x, to address 0x%08x\n",
        !           734:                 first_used_addr, round_page(first_used_addr+size),
        !           735:                 first_used_addr);
        !           736: #endif /* DEBUG */
        !           737: 
        !           738:        /* Map V=R the page tables */
        !           739:        pmap_map(first_used_addr, first_used_addr,
        !           740:                 round_page(first_used_addr+size), VM_PROT_READ | VM_PROT_WRITE);
        !           741: 
        !           742: #if DEBUG
        !           743: 
        !           744:        for(i=first_used_addr; i < round_page(first_used_addr+size); i+=PAGE_SIZE) {    /* Step through all these mappings */
        !           745:                if(i != (j = kvtophys(i))) {                                                    /* Verify that the mapping was made V=R */
        !           746:                        kprintf("*** V=R mapping failed to verify: V=%08X; R=%08X\n", i, j);
        !           747:                }
        !           748:        }
        !           749: #endif
        !           750: 
        !           751:        *first_avail = round_page(first_used_addr + size);
        !           752:        first_free_virt = round_page(first_used_addr + size);
        !           753: 
        !           754:        /* All the rest of memory is free - add it to the free
        !           755:         * regions so that it can be allocated by pmap_steal
        !           756:         */
        !           757:        free_regions[free_regions_count].start = *first_avail;
        !           758:        free_regions[free_regions_count].end = pmap_mem_regions[0].end;
        !           759: 
        !           760:        avail_remaining += (free_regions[free_regions_count].end -
        !           761:                            free_regions[free_regions_count].start) /
        !           762:                                    PPC_PGBYTES;
        !           763: 
        !           764: #if DEBUG
        !           765:        kprintf("ADDED FREE REGION from 0x%08x to 0x%08x, avail_remaining = %d\n",
        !           766:                free_regions[free_regions_count].start,free_regions[free_regions_count].end, 
        !           767:                avail_remaining);
        !           768: #endif /* DEBUG */
        !           769: 
        !           770:        free_regions_count++;
        !           771: 
        !           772:        current_free_region = 0;
        !           773: 
        !           774:        avail_next = free_regions[current_free_region].start;
        !           775:        
        !           776: #if DEBUG
        !           777:        kprintf("Number of free regions=%d\n",free_regions_count);      /* (TEST/DEBUG) */
        !           778:        kprintf("Current free region=%d\n",current_free_region);        /* (TEST/DEBUG) */
        !           779:        for(i=0;i<free_regions_count; i++) {                                    /* (TEST/DEBUG) */
        !           780:                kprintf("Free region %3d - from %08X to %08X\n", i, free_regions[i].start,
        !           781:                        free_regions[i].end);                                                   /* (TEST/DEBUG) */
        !           782:        }
        !           783:        for (i = 0; i < pmap_mem_regions_count; i++) {                  /* (TEST/DEBUG) */
        !           784:                kprintf("PMAP region %3d - from %08X to %08X; phys=%08X\n", i,  /* (TEST/DEBUG) */
        !           785:                        pmap_mem_regions[i].start,                                              /* (TEST/DEBUG) */
        !           786:                        pmap_mem_regions[i].end,                                                /* (TEST/DEBUG) */
        !           787:                        pmap_mem_regions[i].phys_table);                                /* (TEST/DEBUG) */
        !           788:        }
        !           789: #endif
        !           790: 
        !           791: }
        !           792: 
        !           793: /*
        !           794:  * pmap_init(spa, epa)
        !           795:  *     finishes the initialization of the pmap module.
        !           796:  *     This procedure is called from vm_mem_init() in vm/vm_init.c
        !           797:  *     to initialize any remaining data structures that the pmap module
        !           798:  *     needs to map virtual memory (VM is already ON).
        !           799:  */
        !           800: 
        !           801: void
        !           802: pmap_init(void)
        !           803: {
        !           804:        vm_size_t s;
        !           805: 
        !           806:        s = sizeof(struct pmap);
        !           807:        pmap_zone = zinit(s, 400*s, 4096, "pmap");
        !           808: 
        !           809:        pmap_initialized = TRUE;
        !           810: 
        !           811:        /*
        !           812:         *      Initialize list of freed up pmaps
        !           813:         */
        !           814:        queue_init(&free_pmap_list);
        !           815:        free_pmap_count = 0;
        !           816:        simple_lock_init(&free_pmap_lock, ETAP_VM_PMAP_CACHE);
        !           817: }
        !           818: 
        !           819: unsigned int pmap_free_pages(void)
        !           820: {
        !           821:        return avail_remaining;
        !           822: }
        !           823: 
        !           824: boolean_t pmap_next_page(vm_offset_t *addrp)
        !           825: {
        !           826:        /* Non optimal, but only used for virtual memory startup.
        !           827:      * Allocate memory from a table of free physical addresses
        !           828:         * If there are no more free entries, too bad. We have two
        !           829:         * tables to look through, free_regions[] which holds free
        !           830:         * regions from inside pmap_mem_regions[0], and the others...
        !           831:         * pmap_mem_regions[1..]
        !           832:      */
        !           833:         
        !           834:        /* current_free_region indicates the next free entry,
        !           835:         * if it's less than free_regions_count, then we're still
        !           836:         * in free_regions, otherwise we're in pmap_mem_regions
        !           837:         */
        !           838: 
        !           839:        if (current_free_region >= free_regions_count) {
        !           840:                /* We're into the pmap_mem_regions, handle this
        !           841:                 * separately to free_regions
        !           842:                 */
        !           843: 
        !           844:                int current_pmap_mem_region = current_free_region -
        !           845:                                         free_regions_count + 1;
        !           846:                if (current_pmap_mem_region > pmap_mem_regions_count)
        !           847:                        return FALSE;
        !           848:                *addrp = avail_next;
        !           849:                avail_next += PAGE_SIZE;
        !           850:                avail_remaining--;
        !           851:                if (avail_next >= pmap_mem_regions[current_pmap_mem_region].end) {
        !           852:                        current_free_region++;
        !           853:                        current_pmap_mem_region++;
        !           854:                        avail_next = pmap_mem_regions[current_pmap_mem_region].start;
        !           855: #if DEBUG
        !           856:                        kprintf("pmap_next_page : next region start=0x%08x\n",avail_next);
        !           857: #endif /* DEBUG */
        !           858:                }
        !           859:                return TRUE;
        !           860:        }
        !           861:        
        !           862:        /* We're in the free_regions, allocate next page and increment
        !           863:         * counters
        !           864:         */
        !           865:        *addrp = avail_next;
        !           866: 
        !           867:        avail_next += PAGE_SIZE;
        !           868:        avail_remaining--;
        !           869: 
        !           870:        if (avail_next >= free_regions[current_free_region].end) {
        !           871:                current_free_region++;
        !           872:                if (current_free_region < free_regions_count)
        !           873:                        avail_next = free_regions[current_free_region].start;
        !           874:                else
        !           875:                        avail_next = pmap_mem_regions[current_free_region -
        !           876:                                                 free_regions_count + 1].start;
        !           877: #if DEBUG
        !           878:                kprintf("pmap_next_page : next region start=0x%08x\n",avail_next);
        !           879: #endif 
        !           880:        }
        !           881:        return TRUE;
        !           882: }
        !           883: 
        !           884: void pmap_virtual_space(
        !           885:        vm_offset_t *startp,
        !           886:        vm_offset_t *endp)
        !           887: {
        !           888:        *startp = round_page(first_free_virt);
        !           889:        *endp   = VM_MAX_KERNEL_ADDRESS;
        !           890: }
        !           891: 
        !           892: /*
        !           893:  * pmap_create
        !           894:  *
        !           895:  * Create and return a physical map.
        !           896:  *
        !           897:  * If the size specified for the map is zero, the map is an actual physical
        !           898:  * map, and may be referenced by the hardware.
        !           899:  *
        !           900:  * If the size specified is non-zero, the map will be used in software 
        !           901:  * only, and is bounded by that size.
        !           902:  */
        !           903: pmap_t
        !           904: pmap_create(vm_size_t size)
        !           905: {
        !           906:        pmap_t pmap;
        !           907:        int s;
        !           908:        space_t sid;
        !           909: 
        !           910: #if PMAP_LOWTRACE
        !           911:        dbgTrace(0xF1D00001, size, 0);                  /* (TEST/DEBUG) */
        !           912: #endif
        !           913: 
        !           914: #if DEBUG
        !           915:        if (pmdebug & PDB_USER)
        !           916:                kprintf("pmap_create(size=%x)%c", size, size ? '\n' : ' ');
        !           917: #endif
        !           918: 
        !           919:        /*
        !           920:         * A software use-only map doesn't even need a pmap structure.
        !           921:         */
        !           922:        if (size)
        !           923:                return(PMAP_NULL);
        !           924: 
        !           925:        /* 
        !           926:         * If there is a pmap in the pmap free list, reuse it. 
        !           927:         */
        !           928:        s = splhigh();
        !           929:        simple_lock(&free_pmap_lock);
        !           930:        if (!queue_empty(&free_pmap_list)) {
        !           931:                queue_remove_first(&free_pmap_list,
        !           932:                                   pmap,
        !           933:                                   pmap_t,
        !           934:                                   pmap_link);
        !           935:                free_pmap_count--;
        !           936:        } else {
        !           937:                pmap = PMAP_NULL;
        !           938:        }
        !           939:        simple_unlock(&free_pmap_lock);
        !           940:        splx(s);
        !           941: 
        !           942:        /*
        !           943:         * Couldn't find a pmap on the free list, try to allocate a new one.
        !           944:         */
        !           945:        if (pmap == PMAP_NULL) {
        !           946:                pmap = (pmap_t) zalloc(pmap_zone);
        !           947:                if (pmap == PMAP_NULL)
        !           948:                        return(PMAP_NULL);
        !           949: 
        !           950:                /*
        !           951:                 * Allocate space IDs for the pmap.
        !           952:                 * If all are allocated, there is nothing we can do.
        !           953:                 */
        !           954:                pmap->space = mapping_space();
        !           955: 
        !           956:                simple_lock_init(&pmap->lock, ETAP_VM_PMAP);
        !           957:        }
        !           958:        pmap->ref_count = 1;
        !           959:        pmap->stats.resident_count = 0;
        !           960:        pmap->stats.wired_count = 0;
        !           961: 
        !           962: #if PMAP_LOWTRACE
        !           963:        dbgTrace(0xF1D00002, (unsigned int)pmap, (unsigned int)pmap->space);    /* (TEST/DEBUG) */
        !           964: #endif
        !           965: 
        !           966: #if DEBUG
        !           967:        if (pmdebug & PDB_USER)
        !           968:                kprintf("-> %x, space id = %d\n", pmap, pmap->space);
        !           969: #endif
        !           970:        return(pmap);
        !           971: }
        !           972: 
        !           973: /* 
        !           974:  * pmap_destroy
        !           975:  * 
        !           976:  * Gives up a reference to the specified pmap.  When the reference count 
        !           977:  * reaches zero the pmap structure is added to the pmap free list.
        !           978:  *
        !           979:  * Should only be called if the map contains no valid mappings.
        !           980:  */
        !           981: void
        !           982: pmap_destroy(pmap_t pmap)
        !           983: {
        !           984:        int ref_count;
        !           985:        spl_t s;
        !           986: 
        !           987: #if PMAP_LOWTRACE
        !           988:        dbgTrace(0xF1D00003, (unsigned int)pmap, 0);                    /* (TEST/DEBUG) */
        !           989: #endif
        !           990: 
        !           991: #if DEBUG
        !           992:        if (pmdebug & PDB_USER)
        !           993:                kprintf("pmap_destroy(pmap=%x)\n", pmap);
        !           994: #endif
        !           995: 
        !           996:        if (pmap == PMAP_NULL)
        !           997:                return;
        !           998: 
        !           999:        ref_count=hw_atomic_sub(&pmap->ref_count, 1);                   /* Back off the count */
        !          1000:        if(ref_count>0) return;                                                                 /* Still more users, leave now... */
        !          1001: 
        !          1002:        if(ref_count < 0)                                                                               /* Did we go too far? */
        !          1003:                panic("pmap_destroy(): ref_count < 0");
        !          1004:        
        !          1005: 
        !          1006:        assert(pmap->stats.resident_count == 0);
        !          1007: 
        !          1008:        /* 
        !          1009:         * Add the pmap to the pmap free list. 
        !          1010:         */
        !          1011: 
        !          1012:        s = splhigh();
        !          1013:        /* 
        !          1014:         * Add the pmap to the pmap free list. 
        !          1015:         */
        !          1016:        simple_lock(&free_pmap_lock);
        !          1017:        if (free_pmap_count <= free_pmap_max) {
        !          1018:                
        !          1019:                queue_enter_first(&free_pmap_list, pmap, pmap_t, pmap_link);
        !          1020:                free_pmap_count++;
        !          1021:                simple_unlock(&free_pmap_lock);
        !          1022:        } else {
        !          1023:                simple_unlock(&free_pmap_lock);
        !          1024:                zfree(pmap_zone, (vm_offset_t) pmap);
        !          1025:        }
        !          1026:        splx(s);
        !          1027: }
        !          1028: 
        !          1029: /*
        !          1030:  * pmap_reference(pmap)
        !          1031:  *     gains a reference to the specified pmap.
        !          1032:  */
        !          1033: void
        !          1034: pmap_reference(pmap_t pmap)
        !          1035: {
        !          1036:        spl_t s;
        !          1037: 
        !          1038: #if PMAP_LOWTRACE
        !          1039:        dbgTrace(0xF1D00004, (unsigned int)pmap, 0);                    /* (TEST/DEBUG) */
        !          1040: #endif
        !          1041: 
        !          1042: #if DEBUG
        !          1043:        if (pmdebug & PDB_USER)
        !          1044:                kprintf("pmap_reference(pmap=%x)\n", pmap);
        !          1045: #endif
        !          1046: 
        !          1047:        if (pmap != PMAP_NULL) hw_atomic_add(&pmap->ref_count, 1);      /* Bump the count */
        !          1048: }
        !          1049: 
        !          1050: /*
        !          1051:  * pmap_remove(pmap, s, e)
        !          1052:  *     unmaps all virtual addresses v in the virtual address
        !          1053:  *     range determined by [s, e) and pmap.
        !          1054:  *     s and e must be on machine independent page boundaries and
        !          1055:  *     s must be less than or equal to e.
        !          1056:  */
        !          1057: void
        !          1058: pmap_remove(
        !          1059:            pmap_t pmap,
        !          1060:            vm_offset_t sva,
        !          1061:            vm_offset_t eva)
        !          1062: {
        !          1063:        spl_t                   spl;
        !          1064:        struct mapping          *mp;
        !          1065: 
        !          1066: #if PMAP_LOWTRACE
        !          1067:        dbgTrace(0xF1D00005, (unsigned int)pmap, sva|((eva-sva)>>12));  /* (TEST/DEBUG) */
        !          1068: #endif
        !          1069: 
        !          1070: #if DEBUG
        !          1071:        if (pmdebug & PDB_USER)
        !          1072:                kprintf("pmap_remove(pmap=%x, sva=%x, eva=%x)\n",
        !          1073:                       pmap, sva, eva);
        !          1074: #endif
        !          1075: 
        !          1076:        if (pmap == PMAP_NULL)
        !          1077:                return;
        !          1078: 
        !          1079:        /* It is just possible that eva might have wrapped around to zero,
        !          1080:         * and sometimes we get asked to liberate something of size zero
        !          1081:         * even though it's dumb (eg. after zero length read_overwrites)
        !          1082:         */
        !          1083:        assert(eva >= sva);
        !          1084: 
        !          1085:        /* If these are not page aligned the loop might not terminate */
        !          1086:        assert((sva == trunc_page(sva)) && (eva == trunc_page(eva)));
        !          1087: 
        !          1088:        /* We liberate addresses from high to low, since the stack grows
        !          1089:         * down. This means that we won't need to test addresses below
        !          1090:         * the limit of stack growth
        !          1091:         */
        !          1092: 
        !          1093:        debugLog2(44, sva, eva);                                                                /* Log pmap_map call */
        !          1094: 
        !          1095:        while (pmap->stats.resident_count && (eva > sva)) {
        !          1096: 
        !          1097:                eva -= PAGE_SIZE;                                                               /* Back up a page */
        !          1098:                mapping_remove(pmap->space, eva);                               /* Remove the mapping for this address */
        !          1099:        }
        !          1100: 
        !          1101:        debugLog2(45, 0, 0);                                                                    /* Log pmap_map call */
        !          1102: }
        !          1103: 
        !          1104: /*
        !          1105:  *     Routine:
        !          1106:  *             pmap_page_protect
        !          1107:  *
        !          1108:  *     Function:
        !          1109:  *             Lower the permission for all mappings to a given page.
        !          1110:  */
        !          1111: void
        !          1112: pmap_page_protect(
        !          1113:        vm_offset_t pa,
        !          1114:        vm_prot_t prot)
        !          1115: {
        !          1116:        spl_t                           spl;
        !          1117:        register struct phys_entry      *pp;
        !          1118:        boolean_t                       remove;
        !          1119: 
        !          1120: 
        !          1121: #if PMAP_LOWTRACE
        !          1122:        dbgTrace(0xF1D00006, (unsigned int)pa, (unsigned int)prot);     /* (TEST/DEBUG) */
        !          1123: #endif
        !          1124: 
        !          1125: #if DEBUG
        !          1126:        if (pmdebug & PDB_USER)
        !          1127:                kprintf("pmap_page_protect(pa=%x, prot=%x)\n", pa, prot);
        !          1128: #endif
        !          1129: 
        !          1130:        debugLog2(46, pa, prot);                                                                /* Log pmap_page_protect call */
        !          1131: 
        !          1132:        switch (prot) {
        !          1133:                case VM_PROT_READ:
        !          1134:                case VM_PROT_READ|VM_PROT_EXECUTE:
        !          1135:                        remove = FALSE;
        !          1136:                        break;
        !          1137:                case VM_PROT_ALL:
        !          1138:                        return;
        !          1139:                default:
        !          1140:                        remove = TRUE;
        !          1141:                        break;
        !          1142:        }
        !          1143: 
        !          1144:        pp = pmap_find_physentry(pa);                           /* Get the physent for this page */
        !          1145:        if (pp == PHYS_NULL) return;                            /* Leave if not in physical RAM */
        !          1146: 
        !          1147:        if (remove) {                                                           /* If the protection was set to none, we'll remove all mappings */
        !          1148:                mapping_purge(pp);                                              /* Get rid of them all */
        !          1149: 
        !          1150:                debugLog2(47, 0, 0);                                    /* Log pmap_map call */
        !          1151:                return;                                                                 /* Leave... */
        !          1152:        }
        !          1153:        
        !          1154:        /*      When we get here, it means that we are to change the protection for a 
        !          1155:         *      physical page.  
        !          1156:         */
        !          1157:         
        !          1158:        spl=splhigh();                                                          /* No interruptions during this */
        !          1159:        mapping_protect(pp, prot, 0);                           /* Change protection of all mappings to page. 
        !          1160:                                                                                                   Say that the physent is not locked yet */
        !          1161:        splx(spl);                                                                      /* Restore interrupt state */
        !          1162: 
        !          1163:        debugLog2(47, 1, 0);                                                    /* Log pmap_map call */
        !          1164: }
        !          1165: 
        !          1166: /*
        !          1167:  * pmap_protect(pmap, s, e, prot)
        !          1168:  *     changes the protection on all virtual addresses v in the 
        !          1169:  *     virtual address range determined by [s, e] and pmap to prot.
        !          1170:  *     s and e must be on machine independent page boundaries and
        !          1171:  *     s must be less than or equal to e.
        !          1172:  */
        !          1173: void pmap_protect(
        !          1174:             pmap_t pmap,
        !          1175:             vm_offset_t sva, 
        !          1176:             vm_offset_t eva,
        !          1177:             vm_prot_t prot)
        !          1178: {
        !          1179:        spl_t                                           spl;
        !          1180:        register struct phys_entry      *pp;
        !          1181:        register struct mapping         *mp, *mpv;
        !          1182: 
        !          1183: #if PMAP_LOWTRACE
        !          1184:        dbgTrace(0xF1D00008, (unsigned int)pmap, (unsigned int)(sva|((eva-sva)>>12)));  /* (TEST/DEBUG) */
        !          1185: #endif
        !          1186: 
        !          1187: #if DEBUG
        !          1188:        if (pmdebug & PDB_USER)
        !          1189:                kprintf("pmap_protect(pmap=%x, sva=%x, eva=%x, prot=%x)\n", pmap, sva, eva, prot);
        !          1190:        
        !          1191:        assert(sva < eva);
        !          1192: #endif
        !          1193: 
        !          1194:        if (pmap == PMAP_NULL)
        !          1195:                return;
        !          1196: 
        !          1197:        debugLog2(48, sva, eva);                                                                /* Log pmap_map call */
        !          1198: 
        !          1199:        if (prot == VM_PROT_NONE) {                                     /* Should we kill the address range?? */
        !          1200:                pmap_remove(pmap, sva, eva);                    /* Yeah, dump 'em */
        !          1201: 
        !          1202:                debugLog2(49, prot, 0);                                                         /* Log pmap_map call */
        !          1203: 
        !          1204:                return;                                                                 /* Leave... */
        !          1205:        }
        !          1206: 
        !          1207:        sva = trunc_page(sva);                                          /* Start up a page boundary */
        !          1208:        
        !          1209:        for ( ; sva < eva; sva += PAGE_SIZE) {          /* Step it a page at a time */
        !          1210:        
        !          1211:                spl=splhigh();                                                  /* Don't interrupt me, I'm busy */
        !          1212: 
        !          1213:                mp = hw_lock_phys_vir(pmap->space, sva);        /* Lock the physical entry for this mapping */
        !          1214:                if(mp) {                                                                /* Only do this if it is mapped */
        !          1215:                        if((unsigned int)mp&1) {                        /* Did the lock on the phys entry time out? */
        !          1216:                                panic("pmap_protect: timeout obtaining lock on physical entry\n");      /* Scream bloody murder! */
        !          1217:                                splx(spl);                                              /* I'm not busy no more */
        !          1218:                                return;
        !          1219:                        }
        !          1220: 
        !          1221:                mpv = hw_cpv(mp);                                               /* Get virtual address of mapping */
        !          1222:                        if(mpv->physent) {                                      /* If there is a physical page, */
        !          1223:                                mapping_protect(mpv->physent, prot, 1); /* Change the protection in every translation for
        !          1224:                                                                                                   this physical page and say the physent's locked already */           
        !          1225:                                hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);     /* Unlock the physical entry */
        !          1226:                        }
        !          1227:                }
        !          1228:                splx(spl);                                                              /* I'm not busy no more */
        !          1229:        }
        !          1230: 
        !          1231:        debugLog2(49, prot, 1);                                         /* Log pmap_map call */
        !          1232:        return;                                                                         /* Leave... */
        !          1233: }
        !          1234: 
        !          1235: /*
        !          1236:  * pmap_enter
        !          1237:  *
        !          1238:  * Create a translation for the virtual address (virt) to the physical
        !          1239:  * address (phys) in the pmap with the protection requested. If the
        !          1240:  * translation is wired then we can not allow a full page fault, i.e., 
        !          1241:  * the mapping control block is not eligible to be stolen in a low memory
        !          1242:  * condition.
        !          1243:  *
        !          1244:  * NB: This is the only routine which MAY NOT lazy-evaluate
        !          1245:  *     or lose information.  That is, this routine must actually
        !          1246:  *     insert this page into the given map NOW.
        !          1247:  */
        !          1248: void
        !          1249: pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot,
        !          1250:           boolean_t wired)
        !          1251: {
        !          1252:        spl_t                           spl;
        !          1253:        struct mapping          *mp;
        !          1254:        struct phys_entry       *pp;
        !          1255:        int                                     memattr;
        !          1256:        
        !          1257: #if PMAP_LOWTRACE
        !          1258:        dbgTrace(0xF1D00009, (unsigned int)pmap, (unsigned int)va);     /* (TEST/DEBUG) */
        !          1259:        dbgTrace(0xF1D04009, (unsigned int)pa, (unsigned int)prot);     /* (TEST/DEBUG) */
        !          1260: #endif         
        !          1261:        
        !          1262:        if (pmap == PMAP_NULL) return;                                  /* If they gave us no pmap, just leave... */
        !          1263: 
        !          1264:        debugLog2(50, va, pa);                                                  /* Log pmap_map call */
        !          1265: 
        !          1266:        pp = pmap_find_physentry(pa);                                   /* Get the physent for this physical page */
        !          1267: 
        !          1268:        spl=splhigh();                                                                  /* Have to disallow interrupts between the
        !          1269:                                                                                                           time we possibly clear a mapping and the time
        !          1270:                                                                                                           we get it remapped again.  An I/O SLIH could
        !          1271:                                                                                                           try to drive an IOR using the page before
        !          1272:                                                                                                           we get it mapped (Dude! This was a tough 
        !          1273:                                                                                                           bug!!!!) */
        !          1274: 
        !          1275:        mapping_remove(pmap->space, va);                                /* Remove any other mapping at this address */
        !          1276:        memattr = PTE_WIMG_IO;                                                  /* Assume I/O mapping for a moment */
        !          1277:        if(pp) {                                                                                /* Is there a physical mapping? */
        !          1278:                mapping_phys_attr(pp, prot, pp->pte1&0x00000078);       /* Set the physical protect default */
        !          1279:                memattr = ((pp->pte1&0x00000078) >> 3);         /* Set the mapping properly */
        !          1280:        }
        !          1281:        mp=mapping_make(pmap, pmap->space, pp, va, pa, prot, memattr);  /* Make the address mapping */
        !          1282: 
        !          1283:        splx(spl);                                                                              /* I'm not busy no more - come what may */
        !          1284: 
        !          1285:        debugLog2(51, prot, 0);                                                 /* Log pmap_map call */
        !          1286: 
        !          1287: #if    DEBUG
        !          1288:        if (pmdebug & (PDB_USER|PDB_ENTER))
        !          1289:                kprintf("leaving pmap_enter\n");
        !          1290: #endif
        !          1291: 
        !          1292: }
        !          1293: 
        !          1294: /*
        !          1295:  * pmap_extract(pmap, va)
        !          1296:  *     returns the physical address corrsponding to the 
        !          1297:  *     virtual address specified by pmap and va if the
        !          1298:  *     virtual address is mapped and 0 if it is not.
        !          1299:  */
        !          1300: vm_offset_t pmap_extract(pmap_t pmap, vm_offset_t va) {
        !          1301: 
        !          1302:        spl_t                                   spl;
        !          1303:        register struct mapping *mp, *mpv;
        !          1304:        register vm_offset_t    pa;
        !          1305: 
        !          1306: 
        !          1307: #if PMAP_LOWTRACE
        !          1308:        dbgTrace(0xF1D0000B, (unsigned int)pmap, (unsigned int)va);     /* (TEST/DEBUG) */
        !          1309: #endif
        !          1310: #if DEBUG
        !          1311:        if (pmdebug & PDB_USER)
        !          1312:                kprintf("pmap_extract(pmap=%x, va=%x)\n", pmap, va);
        !          1313: #endif
        !          1314: 
        !          1315:        pa = (vm_offset_t) 0;                                                   /* Clear this to 0 */ 
        !          1316: 
        !          1317:        debugLog2(52, pmap->space, va);                                 /* Log pmap_map call */
        !          1318: 
        !          1319:        spl = splhigh();                                                                /* We can't allow any loss of control here */
        !          1320: 
        !          1321:        if(mp=hw_lock_phys_vir(pmap->space, va)) {              /* Find the mapping for this vaddr and lock physent */  
        !          1322:                if((unsigned int)mp&1) {                                        /* Did the lock on the phys entry time out? */
        !          1323:                        panic("pmap_extract: timeout obtaining lock on physical entry\n");      /* Scream bloody murder! */
        !          1324:                        splx(spl);                                                              /* Interruptions are cool now */
        !          1325:                        return 0;
        !          1326:                }
        !          1327:                mpv = hw_cpv(mp);                                                       /* Get virtual address of mapping */
        !          1328:                pa = (vm_offset_t)((mpv->PTEr & -PAGE_SIZE) | ((unsigned int)va & (PAGE_SIZE-1)));      /* Build the physical address */
        !          1329:                if(mpv->physent) hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);    /* Unlock the physical entry */
        !          1330:                splx(spl);                                                                      /* Interruptions are cool now */
        !          1331: 
        !          1332:                debugLog2(53, pa, 0);                                           /* Log pmap_map call */
        !          1333: 
        !          1334:                return pa;                                                                      /* Return the physical address... */
        !          1335:        }
        !          1336: 
        !          1337:        splx(spl);                                                                              /* Interruptions are cool now */
        !          1338: 
        !          1339:        debugLog2(53, pa, 0);                                                   /* Log pmap_map call */
        !          1340: 
        !          1341:        return pa;                                                                              /* Send back a 0 'cause there's no translation... */
        !          1342: }
        !          1343: 
        !          1344: /*
        !          1345:  *     pmap_attributes:
        !          1346:  *
        !          1347:  *     Set/Get special memory attributes; Set is not implemented.
        !          1348:  *
        !          1349:  *     Note: 'VAL_GET_INFO' is used to return info about a page.
        !          1350:  *       If less than 1 page is specified, return the physical page
        !          1351:  *       mapping and a count of the number of mappings to that page.
        !          1352:  *       If more than one page is specified, return the number
        !          1353:  *       of resident pages and the number of shared (more than
        !          1354:  *       one mapping) pages in the range;
        !          1355:  *
        !          1356:  */
        !          1357: kern_return_t
        !          1358: pmap_attribute(pmap, address, size, attribute, value)
        !          1359:        pmap_t                  pmap;
        !          1360:        vm_offset_t             address;
        !          1361:        vm_size_t               size;
        !          1362:        vm_machine_attribute_t  attribute;
        !          1363:        vm_machine_attribute_val_t* value;      
        !          1364: {
        !          1365:        spl_t                   s;
        !          1366:        vm_offset_t     sva, eva;
        !          1367:        vm_offset_t             pa;
        !          1368:        kern_return_t   ret;
        !          1369:        register struct mapping *mp, *mpv;
        !          1370:        register struct phys_entry *pp;
        !          1371:        int                     total;
        !          1372: 
        !          1373:        if (attribute != MATTR_CACHE)
        !          1374:                return KERN_INVALID_ARGUMENT;
        !          1375: 
        !          1376:        /* We can't get the caching attribute for more than one page
        !          1377:         * at a time
        !          1378:         */
        !          1379:        if ((*value == MATTR_VAL_GET) &&
        !          1380:            (trunc_page(address) != trunc_page(address+size-1)))
        !          1381:                return KERN_INVALID_ARGUMENT;
        !          1382: 
        !          1383:        if (pmap == PMAP_NULL)
        !          1384:                return KERN_SUCCESS;
        !          1385: 
        !          1386:        sva = trunc_page(address);
        !          1387:        eva = round_page(address + size);
        !          1388:        ret = KERN_SUCCESS;
        !          1389: 
        !          1390:        debugLog2(54, address, attribute);                                              /* Log pmap_map call */
        !          1391: 
        !          1392:        switch (*value) {
        !          1393:                case MATTR_VAL_CACHE_SYNC:                                                      /* sync I+D caches */
        !          1394:                        if (PROCESSOR_VERSION == PROCESSOR_VERSION_601) {       /* Don't need this for 601s... */
        !          1395:                                break;
        !          1396:                        }
        !          1397:                case MATTR_VAL_CACHE_FLUSH:                                                     /* flush from all caches */
        !          1398:                case MATTR_VAL_DCACHE_FLUSH:                                            /* flush from data cache(s) */
        !          1399:                case MATTR_VAL_ICACHE_FLUSH:                                            /* flush from instr cache(s) */
        !          1400:                        sva = trunc_page(sva);
        !          1401:                        s = splhigh();
        !          1402:                        for (; sva < eva; sva += PAGE_SIZE) {
        !          1403:        
        !          1404:                                if(!(mp = hw_lock_phys_vir(pmap->space, sva)))  /* Find the mapping for this vaddr and lock physent */
        !          1405:                                        continue;                                                               /* Skip if the page is not mapped... */
        !          1406: 
        !          1407:                                if((unsigned int)mp&1) {                                        /* Did the lock on the phys entry time out? */
        !          1408:                                        panic("pmap_attribute: timeout obtaining lock on physical entry\n");    /* Scream bloody murder! */
        !          1409:                                        continue;
        !          1410:                                }
        !          1411:                                
        !          1412:                                mpv = hw_cpv(mp);                                                       /* Get virtual address of mapping */
        !          1413:                                if((unsigned int)mpv->physent) {                        /* Is there a physical entry? */
        !          1414:                                        pa = (vm_offset_t)mpv->physent->pte1 & -PAGE_SIZE;      /* Yes, get the physical address from there */
        !          1415:                                } 
        !          1416:                                else {
        !          1417:                                        pa = (vm_offset_t)(mpv->PTEr & PAGE_SIZE);      /* Otherwise from the mapping */
        !          1418:                                }
        !          1419: 
        !          1420:                                switch (*value) {                                                       /* What type was that again? */
        !          1421:                                        case MATTR_VAL_CACHE_SYNC:                              /* It is sync I+D caches */
        !          1422:                                                sync_cache(pa, PAGE_SIZE);                      /* Sync up dem caches */
        !          1423:                                                break;                                                          /* Done with this one here... */
        !          1424:                                        
        !          1425:                                        case MATTR_VAL_CACHE_FLUSH:                             /* It is flush from all caches */
        !          1426:                                                flush_dcache(pa, PAGE_SIZE, TRUE);      /* Flush out the data cache */
        !          1427:                                                invalidate_icache(pa, PAGE_SIZE, TRUE); /* Flush out the instruction cache */
        !          1428:                                                break;                                                          /* Done with this one here... */
        !          1429:                                        
        !          1430:                                        case MATTR_VAL_DCACHE_FLUSH:                    /* It is flush from data cache(s) */
        !          1431:                                                flush_dcache(pa, PAGE_SIZE, TRUE);      /* Flush out the data cache */
        !          1432:                                                break;                                                          /* Done with this one here... */
        !          1433: 
        !          1434:                                        case MATTR_VAL_ICACHE_FLUSH:                    /* It is flush from instr cache(s) */
        !          1435:                                                invalidate_icache(pa, PAGE_SIZE, TRUE); /* Flush out the instruction cache */
        !          1436:                                                break;                                                          /* Done with this one here... */
        !          1437:                                }
        !          1438:                                if(mpv->physent) hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);    /* Unlock the physical entry if it exists*/
        !          1439: 
        !          1440:                        }
        !          1441:                        splx(s);
        !          1442:                        break;
        !          1443: 
        !          1444:                case MATTR_VAL_GET_INFO:                                                        /* Get info */
        !          1445:                        total = 0;
        !          1446:                        s = splhigh();                                                                  /* Lock 'em out */
        !          1447:                        if (size <= PAGE_SIZE) {                                                /* Do they want just one page */
        !          1448:                                if(!(mp = hw_lock_phys_vir(pmap->space, sva))) {        /* Find the mapping for this vaddr and lock physent */
        !          1449:                                        *value = 0;                                                             /* Return nothing if no mapping */
        !          1450:                                }
        !          1451:                                else {
        !          1452:                                        if((unsigned int)mp&1) {                                /* Did the lock on the phys entry time out? */
        !          1453:                                                panic("pmap_attribute: timeout obtaining lock on physical entry\n");    /* Scream bloody murder! */
        !          1454:                                        }
        !          1455:                                        mpv = hw_cpv(mp);                                               /* Get virtual address of mapping */
        !          1456:                                        if(pp = mpv->physent) {                                 /* Check for a physical entry */
        !          1457:                                                total = 0;                                                      /* Clear the count */
        !          1458:                                                for (mpv = (mapping *)hw_cpv((mapping *)((unsigned int)pp->phys_link & ~PHYS_FLAGS)); mpv != NULL; mpv = hw_cpv(mp->next)) total++;     /* Count the mapping */
        !          1459:                                                *value = (vm_machine_attribute_val_t) ((pp->pte1 & -PAGE_SIZE) | total);        /* Pass back the physical address and the count of mappings */
        !          1460:                                                hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);       /* Clear the physical entry lock */
        !          1461:                                        }
        !          1462:                                        else {                                                                  /* This is the case for an I/O mapped area */
        !          1463:                                                *value = (vm_machine_attribute_val_t) ((mpv->PTEr & -PAGE_SIZE) | 1);   /* Pass back the physical address and the count of mappings */
        !          1464:                                        }
        !          1465:                                }
        !          1466:                        }
        !          1467:                        else {
        !          1468:                                total = 0;
        !          1469:                                while (sva < eva) {
        !          1470:                                        if(mp = hw_lock_phys_vir(pmap->space, sva)) {   /* Find the mapping for this vaddr and lock physent */
        !          1471:                                                if((unsigned int)mp&1) {                                        /* Did the lock on the phys entry time out? */
        !          1472:                                                        panic("pmap_attribute: timeout obtaining lock on physical entry\n");    /* Scream bloody murder! */
        !          1473:                                                        continue;
        !          1474:                                                }
        !          1475:                                                mpv = hw_cpv(mp);                                       /* Get virtual address of mapping */
        !          1476:                                                total += 65536 + (mpv->physent && ((mapping *)((unsigned int)mpv->physent->phys_link & -32))->next);    /* Count the "resident" and shared pages */
        !          1477:                                                hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK);     /* Clear the physical entry lock */
        !          1478:                                        }
        !          1479:                                        sva += PAGE_SIZE;
        !          1480:                                }
        !          1481:                                *value = total;
        !          1482:                        }
        !          1483:                        splx(s);
        !          1484:                        break;
        !          1485:        
        !          1486:                case MATTR_VAL_GET:             /* return current value */
        !          1487:                case MATTR_VAL_OFF:             /* turn attribute off */
        !          1488:                case MATTR_VAL_ON:              /* turn attribute on */
        !          1489:                default:
        !          1490:                        ret = KERN_INVALID_ARGUMENT;
        !          1491:                        break;
        !          1492:        }
        !          1493: 
        !          1494:        debugLog2(55, 0, 0);                                    /* Log pmap_map call */
        !          1495: 
        !          1496:        return ret;
        !          1497: }
        !          1498: 
        !          1499: /*
        !          1500:  * pmap_collect
        !          1501:  * 
        !          1502:  * Garbage collects the physical map system for pages that are no longer used.
        !          1503:  * It isn't implemented or needed or wanted.
        !          1504:  */
        !          1505: void
        !          1506: pmap_collect(pmap_t pmap)
        !          1507: {
        !          1508:        return;
        !          1509: }
        !          1510: 
        !          1511: /*
        !          1512:  *     Routine:        pmap_activate
        !          1513:  *     Function:
        !          1514:  *             Binds the given physical map to the given
        !          1515:  *             processor, and returns a hardware map description.
        !          1516:  *             It isn't implemented or needed or wanted.
        !          1517:  */
        !          1518: void
        !          1519: pmap_activate(
        !          1520:        pmap_t pmap,
        !          1521:        thread_t th,
        !          1522:        int which_cpu)
        !          1523: {
        !          1524:        return;
        !          1525: }
        !          1526: /*
        !          1527:  * pmap_deactivate:
        !          1528:  * It isn't implemented or needed or wanted.
        !          1529:  */
        !          1530: void
        !          1531: pmap_deactivate(
        !          1532:        pmap_t pmap,
        !          1533:        thread_t th,
        !          1534:        int which_cpu)
        !          1535: {
        !          1536:        return;
        !          1537: }
        !          1538: 
        !          1539: #if DEBUG
        !          1540: 
        !          1541: /*
        !          1542:  * pmap_zero_page
        !          1543:  * pmap_copy page
        !          1544:  * 
        !          1545:  * are implemented in movc.s, these
        !          1546:  * are just wrappers to help debugging
        !          1547:  */
        !          1548: 
        !          1549: extern void pmap_zero_page_assembler(vm_offset_t p);
        !          1550: extern void pmap_copy_page_assembler(vm_offset_t src, vm_offset_t dst);
        !          1551: 
        !          1552: /*
        !          1553:  * pmap_zero_page(pa)
        !          1554:  *
        !          1555:  * pmap_zero_page zeros the specified (machine independent) page pa.
        !          1556:  */
        !          1557: void
        !          1558: pmap_zero_page(
        !          1559:        vm_offset_t p)
        !          1560: {
        !          1561:        register struct mapping *mp;
        !          1562:        register struct phys_entry *pp;
        !          1563: 
        !          1564:        if (pmdebug & (PDB_USER|PDB_ZERO))
        !          1565:                kprintf("pmap_zero_page(pa=%x)\n", p);
        !          1566: 
        !          1567:        /*
        !          1568:         * XXX can these happen?
        !          1569:         */
        !          1570:        if (pmap_find_physentry(p) == PHYS_NULL)
        !          1571:                panic("zero_page: physaddr out of range");
        !          1572: 
        !          1573:        pmap_zero_page_assembler(p);
        !          1574: }
        !          1575: 
        !          1576: /*
        !          1577:  * pmap_copy_page(src, dst)
        !          1578:  *
        !          1579:  * pmap_copy_page copies the specified (machine independent)
        !          1580:  * page from physical address src to physical address dst.
        !          1581:  *
        !          1582:  * We need to invalidate the cache for address dst before
        !          1583:  * we do the copy. Apparently there won't be any mappings
        !          1584:  * to the dst address normally.
        !          1585:  */
        !          1586: void
        !          1587: pmap_copy_page(
        !          1588:        vm_offset_t src,
        !          1589:        vm_offset_t dst)
        !          1590: {
        !          1591:        register struct phys_entry *pp;
        !          1592: 
        !          1593:        if (pmdebug & (PDB_USER|PDB_COPY))
        !          1594:                kprintf("pmap_copy_page(spa=%x, dpa=%x)\n", src, dst);
        !          1595:        if (pmdebug & PDB_COPY)
        !          1596:                kprintf("pmap_copy_page: phys_copy(%x, %x, %x)\n",
        !          1597:                       src, dst, PAGE_SIZE);
        !          1598: 
        !          1599:        pmap_copy_page_assembler(src, dst);
        !          1600: }
        !          1601: #endif /* DEBUG */
        !          1602: 
        !          1603: /*
        !          1604:  * pmap_pageable(pmap, s, e, pageable)
        !          1605:  *     Make the specified pages (by pmap, offset)
        !          1606:  *     pageable (or not) as requested.
        !          1607:  *
        !          1608:  *     A page which is not pageable may not take
        !          1609:  *     a fault; therefore, its page table entry
        !          1610:  *     must remain valid for the duration.
        !          1611:  *
        !          1612:  *     This routine is merely advisory; pmap_enter()
        !          1613:  *     will specify that these pages are to be wired
        !          1614:  *     down (or not) as appropriate.
        !          1615:  *
        !          1616:  *     (called from vm/vm_fault.c).
        !          1617:  */
        !          1618: void
        !          1619: pmap_pageable(
        !          1620:        pmap_t          pmap,
        !          1621:        vm_offset_t     start,
        !          1622:        vm_offset_t     end,
        !          1623:        boolean_t       pageable)
        !          1624: {
        !          1625: 
        !          1626:        return;                                                                                         /* This is not used... */
        !          1627: 
        !          1628: }
        !          1629: /*
        !          1630:  *     Routine:        pmap_change_wiring
        !          1631:  *     NOTE USED ANYMORE.
        !          1632:  */
        !          1633: void
        !          1634: pmap_change_wiring(
        !          1635:        register pmap_t pmap,
        !          1636:        vm_offset_t     va,
        !          1637:        boolean_t       wired)
        !          1638: {
        !          1639:        return;                                                                                         /* This is not used... */
        !          1640: }
        !          1641: 
        !          1642: /*
        !          1643:  * pmap_modify_pages(pmap, s, e)
        !          1644:  *     sets the modified bit on all virtual addresses v in the 
        !          1645:  *     virtual address range determined by [s, e] and pmap,
        !          1646:  *     s and e must be on machine independent page boundaries and
        !          1647:  *     s must be less than or equal to e.
        !          1648:  */
        !          1649: void
        !          1650: pmap_modify_pages(
        !          1651:             pmap_t pmap,
        !          1652:             vm_offset_t sva, 
        !          1653:             vm_offset_t eva)
        !          1654: {
        !          1655:        spl_t           spl;
        !          1656:        mapping         *mp;
        !          1657: 
        !          1658: #if PMAP_LOWTRACE
        !          1659:        dbgTrace(0xF1D00010, (unsigned int)pmap, (unsigned int)(sva|((eva-sva)>>12)));  /* (TEST/DEBUG) */
        !          1660: #endif
        !          1661: 
        !          1662: #if DEBUG
        !          1663:        if (pmdebug & PDB_USER) kprintf("pmap_modify_pages(pmap=%x, sva=%x, eva=%x)\n", pmap, sva, eva);
        !          1664: #endif
        !          1665: 
        !          1666:        if (pmap == PMAP_NULL) return;                                          /* If no pmap, can't do it... */
        !          1667: 
        !          1668:        debugLog2(56, sva, eva);                                                        /* Log pmap_map call */
        !          1669: 
        !          1670:        spl=splhigh();                                                                          /* Don't bother me */
        !          1671: 
        !          1672:        for ( ; sva < eva; sva += PAGE_SIZE) {                          /* Cycle through the whole range */     
        !          1673:                mp = hw_lock_phys_vir(pmap->space, sva);                /* Lock the physical entry for this mapping */
        !          1674:                if(mp) {                                                                                /* Did we find one? */
        !          1675:                        if((unsigned int)mp&1) {                                        /* Did the lock on the phys entry time out? */
        !          1676:                                panic("pmap_modify_pages: timeout obtaining lock on physical entry\n"); /* Scream bloody murder! */
        !          1677:                                continue;
        !          1678:                        }
        !          1679:                        mp = hw_cpv(mp);                                                        /* Convert to virtual addressing */                             
        !          1680:                        if(!mp->physent) continue;                                      /* No physical entry means an I/O page, we can't set attributes */
        !          1681:                        mapping_set_mod(mp->physent);                           /* Set the modfied bit for this page */
        !          1682:                        hw_unlock_bit((unsigned int *)&mp->physent->phys_link, PHYS_LOCK);      /* Unlock the physical entry */
        !          1683:                }
        !          1684:        }
        !          1685:        splx(spl);                                                                                      /* Restore the interrupt level */
        !          1686: 
        !          1687:        debugLog2(57, 0, 0);                                                            /* Log pmap_map call */
        !          1688:        return;                                                                                         /* Leave... */
        !          1689: }
        !          1690: 
        !          1691: /*
        !          1692:  * pmap_clear_modify(phys)
        !          1693:  *     clears the hardware modified ("dirty") bit for one
        !          1694:  *     machine independant page starting at the given
        !          1695:  *     physical address.  phys must be aligned on a machine
        !          1696:  *     independant page boundary.
        !          1697:  */
        !          1698: void
        !          1699: pmap_clear_modify(vm_offset_t pa)
        !          1700: {
        !          1701:        register struct phys_entry      *pp;
        !          1702:        spl_t           spl;
        !          1703: 
        !          1704: #if PMAP_LOWTRACE
        !          1705:        dbgTrace(0xF1D00011, (unsigned int)pa, 0);                      /* (TEST/DEBUG) */
        !          1706: #endif
        !          1707: #if DEBUG
        !          1708:        if (pmdebug & PDB_USER)
        !          1709:                kprintf("pmap_clear_modify(pa=%x)\n", pa);
        !          1710: #endif
        !          1711: 
        !          1712:        pp = pmap_find_physentry(pa);                                           /* Find the physent for this page */
        !          1713:        if (pp == PHYS_NULL) return;                                            /* If there isn't one, just leave... */
        !          1714: 
        !          1715:        debugLog2(58, pa, 0);                                   /* Log pmap_map call */
        !          1716: 
        !          1717:        spl=splhigh();                                                                          /* Don't bother me */
        !          1718: 
        !          1719:        if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Try to get the lock on the physical entry */
        !          1720:                panic("pmap_clear_modify: Timeout getting lock on physent at %08X\n", pp);      /* Arrrgghhhh! */
        !          1721:                splx(spl);                                                                              /* Restore 'rupts */
        !          1722:                return;                                                                                 /* Should die before here */
        !          1723:        }
        !          1724: 
        !          1725:        mapping_clr_mod(pp);                                                            /* Clear all change bits for physical page */
        !          1726: 
        !          1727:        hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);       /* Unlock the physical entry */
        !          1728:        splx(spl);                                                                                      /* Restore the interrupt level */
        !          1729: 
        !          1730:        debugLog2(59, 0, 0);                                    /* Log pmap_map call */
        !          1731: }
        !          1732: 
        !          1733: /*
        !          1734:  * pmap_is_modified(phys)
        !          1735:  *     returns TRUE if the given physical page has been modified 
        !          1736:  *     since the last call to pmap_clear_modify().
        !          1737:  */
        !          1738: boolean_t
        !          1739: pmap_is_modified(register vm_offset_t pa)
        !          1740: {
        !          1741:        register struct phys_entry      *pp;
        !          1742:        spl_t           spl;
        !          1743:        boolean_t       ret;
        !          1744: 
        !          1745: 
        !          1746: #if PMAP_LOWTRACE
        !          1747:        dbgTrace(0xF1D00012, (unsigned int)pa, 0);                      /* (TEST/DEBUG) */
        !          1748: #endif
        !          1749: #if DEBUG
        !          1750:        if (pmdebug & PDB_USER)
        !          1751:                kprintf("pmap_is_modified(pa=%x)\n", pa);
        !          1752: #endif
        !          1753: 
        !          1754:        pp = pmap_find_physentry(pa);                                           /* Find the physent for this page */
        !          1755:        if (pp == PHYS_NULL) return(FALSE);                                     /* Just indicate not set... */
        !          1756:        
        !          1757:        debugLog2(60, pa, 0);                                   /* Log pmap_map call */
        !          1758: 
        !          1759:        spl=splhigh();                                                                          /* Don't bother me */
        !          1760: 
        !          1761:        if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Try to get the lock on the physical entry */
        !          1762:                panic("pmap_is_modified: Timeout getting lock on physent at %08X\n", pp);       /* Arrrgghhhh! */
        !          1763:                splx(spl);                                                                              /* Restore 'rupts */
        !          1764:                return 0;                                                                               /* Should die before here */
        !          1765:        }
        !          1766:        
        !          1767:        ret = mapping_tst_mod(pp);                                                      /* Check for modified */
        !          1768:        
        !          1769:        hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);       /* Unlock the physical entry */
        !          1770:        splx(spl);                                                                                      /* Restore the interrupt level */
        !          1771:        
        !          1772:        debugLog2(61, ret, 0);                                  /* Log pmap_map call */
        !          1773: 
        !          1774:        return ret;                                                                             
        !          1775: }
        !          1776: 
        !          1777: /*
        !          1778:  * pmap_clear_reference(phys)
        !          1779:  *     clears the hardware referenced bit in the given machine
        !          1780:  *     independant physical page.  
        !          1781:  *
        !          1782:  */
        !          1783: void
        !          1784: pmap_clear_reference(vm_offset_t pa)
        !          1785: {
        !          1786:        register struct phys_entry      *pp;
        !          1787:        spl_t           spl;
        !          1788: 
        !          1789: 
        !          1790: #if PMAP_LOWTRACE
        !          1791:        dbgTrace(0xF1D00013, (unsigned int)pa, 0);                              /* (TEST/DEBUG) */
        !          1792: #endif
        !          1793: #if DEBUG
        !          1794:        if (pmdebug & PDB_USER)
        !          1795:                kprintf("pmap_clear_reference(pa=%x)\n", pa);
        !          1796: #endif
        !          1797: 
        !          1798:        pp = pmap_find_physentry(pa);                                                   /* Find the physent for this page */
        !          1799:        if (pp == PHYS_NULL) return;                                                    /* If there isn't one, just leave... */
        !          1800: 
        !          1801:        debugLog2(62, pa, 0);                                   /* Log pmap_map call */
        !          1802: 
        !          1803:        spl=splhigh();                                                                                  /* Don't bother me */
        !          1804:        mapping_clr_ref(pp);                                                                    /* Clear all reference bits for physical page */
        !          1805:        splx(spl);                                                                                              /* Restore the interrupt level */
        !          1806: 
        !          1807:        debugLog2(63, 0, 0);                                    /* Log pmap_map call */
        !          1808: 
        !          1809: }
        !          1810: 
        !          1811: /*
        !          1812:  * pmap_is_referenced(phys)
        !          1813:  *     returns TRUE if the given physical page has been referenced 
        !          1814:  *     since the last call to pmap_clear_reference().
        !          1815:  */
        !          1816: boolean_t
        !          1817: pmap_is_referenced(vm_offset_t pa)
        !          1818: {
        !          1819:        register struct phys_entry      *pp;
        !          1820:        spl_t           spl;
        !          1821:        boolean_t       ret;
        !          1822: 
        !          1823: 
        !          1824: #if PMAP_LOWTRACE
        !          1825:        dbgTrace(0xF1D00014, (unsigned int)pa, 0);                      /* (TEST/DEBUG) */
        !          1826: #endif
        !          1827: #if DEBUG
        !          1828:        if (pmdebug & PDB_USER)
        !          1829:                kprintf("pmap_is_referenced(pa=%x)\n", pa);
        !          1830: #endif
        !          1831: 
        !          1832:        pp = pmap_find_physentry(pa);                                           /* Find the physent for this page */
        !          1833:        if (pp == PHYS_NULL) return(FALSE);                                     /* Just indicate not set... */
        !          1834:        
        !          1835:        debugLog2(64, pa, 0);                                   /* Log pmap_map call */
        !          1836: 
        !          1837:        spl=splhigh();                                                                          /* Don't bother me */
        !          1838: 
        !          1839:        if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) {      /* Try to get the lock on the physical entry */
        !          1840:                panic("pmap_is_referenced: Timeout getting lock on physent at %08X\n", pp);     /* Arrrgghhhh! */
        !          1841:                splx(spl);                                                                              /* Restore 'rupts */
        !          1842:                return 0;                                                                               /* Should die before here */
        !          1843:        }
        !          1844:        
        !          1845:        ret = mapping_tst_ref(pp);                                                      /* Check for referenced */
        !          1846:        
        !          1847:        hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK);       /* Unlock the physical entry */
        !          1848:        splx(spl);                                                                                      /* Restore the interrupt level */
        !          1849:        
        !          1850:        debugLog2(65, ret, 0);                                  /* Log pmap_map call */
        !          1851: 
        !          1852:        return ret;                                                                             
        !          1853: }
        !          1854: 
        !          1855: #if    MACH_VM_DEBUG
        !          1856: int
        !          1857: pmap_list_resident_pages(
        !          1858:        register pmap_t         pmap,
        !          1859:        register vm_offset_t    *listp,
        !          1860:        register int            space)
        !          1861: {
        !          1862:        return 0;
        !          1863: }
        !          1864: #endif /* MACH_VM_DEBUG */
        !          1865: 
        !          1866: /*
        !          1867:  * Locking:
        !          1868:  *     spl: VM
        !          1869:  */
        !          1870: void
        !          1871: pmap_copy_part_page(
        !          1872:        vm_offset_t     src,
        !          1873:        vm_offset_t     src_offset,
        !          1874:        vm_offset_t     dst,
        !          1875:        vm_offset_t     dst_offset,
        !          1876:        vm_size_t       len)
        !          1877: {
        !          1878:        register struct phys_entry *pp_src, *pp_dst;
        !          1879:        spl_t   s;
        !          1880: 
        !          1881: 
        !          1882: #if PMAP_LOWTRACE
        !          1883:        dbgTrace(0xF1D00019, (unsigned int)src+src_offset, (unsigned int)dst+dst_offset);       /* (TEST/DEBUG) */
        !          1884:        dbgTrace(0xF1D04019, (unsigned int)len, 0);                     /* (TEST/DEBUG) */
        !          1885: #endif
        !          1886:        s = splhigh();
        !          1887: 
        !          1888:         assert(((dst & PAGE_MASK)+dst_offset+len) <= PAGE_SIZE);
        !          1889:         assert(((src & PAGE_MASK)+src_offset+len) <= PAGE_SIZE);
        !          1890: 
        !          1891:        /*
        !          1892:         * Since the source and destination are physical addresses, 
        !          1893:         * turn off data translation to perform a  bcopy() in bcopy_phys().
        !          1894:         */
        !          1895:        phys_copy((vm_offset_t) src+src_offset,
        !          1896:                  (vm_offset_t) dst+dst_offset, len);
        !          1897: 
        !          1898:        splx(s);
        !          1899: }
        !          1900: 
        !          1901: void
        !          1902: pmap_zero_part_page(
        !          1903:        vm_offset_t     p,
        !          1904:        vm_offset_t     offset,
        !          1905:        vm_size_t       len)
        !          1906: {
        !          1907:     panic("pmap_zero_part_page");
        !          1908: }
        !          1909: 
        !          1910: boolean_t pmap_verify_free(vm_offset_t pa) {
        !          1911: 
        !          1912:        struct phys_entry       *pp;
        !          1913: 
        !          1914: #if PMAP_LOWTRACE
        !          1915:        dbgTrace(0xF1D00007, (unsigned int)pa, 0);                              /* (TEST/DEBUG) */
        !          1916: #endif
        !          1917: 
        !          1918: #if DEBUG
        !          1919:        if (pmdebug & PDB_USER)
        !          1920:                kprintf("pmap_verify_free(pa=%x)\n", pa);
        !          1921: #endif
        !          1922: 
        !          1923:        if (!pmap_initialized) return(TRUE);
        !          1924: 
        !          1925:        pp = pmap_find_physentry(pa);                                                   /* Look up the physical entry */
        !          1926:        if (pp == PHYS_NULL) return FALSE;                                              /* If there isn't one, show no mapping... */
        !          1927:        return ((mapping *)((unsigned int)pp->phys_link & ~PHYS_FLAGS) == MAPPING_NULL);        /* Otherwise, return TRUE if mapping exists... */
        !          1928: }
        !          1929: 
        !          1930: 
        !          1931: /* Determine if we need to switch space and set up for it if so */
        !          1932: 
        !          1933: void pmap_switch(pmap_t map)
        !          1934: {
        !          1935:        unsigned int i;
        !          1936: 
        !          1937: #if DEBUG
        !          1938:        if (watchacts & WA_PCB) {
        !          1939:                kprintf("Switching to map at 0x%08x, space=%d\n",
        !          1940:                       map,map->space);
        !          1941:        }
        !          1942: #endif /* DEBUG */
        !          1943: 
        !          1944: 
        !          1945: /* when changing to kernel space (collocated servers), don't bother
        !          1946:  * doing anything, the kernel is mapped from here already.
        !          1947:  */
        !          1948:        if (map->space == PPC_SID_KERNEL) {                     /* Are we switching into kernel space? */
        !          1949:                return;                                                                 /* If so, we don't do anything... */
        !          1950:        }
        !          1951:        
        !          1952:        hw_set_user_space(map->space);                          /* Indicate if we need to load the SRs or not */
        !          1953:        return;                                                                         /* Bye, bye, butterfly... */
        !          1954: }
        !          1955: 
        !          1956: #ifdef MACH_BSD
        !          1957: /*
        !          1958:  * pmap_move_page - Move pages from one kernel vaddr to another.
        !          1959:  *
        !          1960:  * Parameters:
        !          1961:  *      from    - Original kernel va    (Mach. indep. page boundary)
        !          1962:  *      to      - New kernel va         (Mach. indep. page boundary)
        !          1963:  *      size    - Bytes to move.        (Mach. indep. pages)
        !          1964:  *
        !          1965:  * Returns:
        !          1966:  *      Nothing.
        !          1967:  */
        !          1968: void pmap_move_page(unsigned long from, unsigned long to, vm_size_t size) {
        !          1969: 
        !          1970:        mapping         *mp;
        !          1971:        vm_offset_t     pa;
        !          1972:        vm_size_t       cs;
        !          1973:        
        !          1974: 
        !          1975:        if ((size & page_mask) != 0) {
        !          1976:                panic("pmap_move_page: partial mach indep page");
        !          1977:        }
        !          1978:        
        !          1979:        debugLog2(66, from, to);                                        /* Log pmap_map call */
        !          1980: 
        !          1981:        for(cs = 0; cs < size; cs += PAGE_SIZE) {                                       /* Do the whole range */        
        !          1982:                
        !          1983:                if(!mapping_remap(kernel_pmap->space, from, to)) {              /* Remap the vaddr */
        !          1984:                        panic("pmap_move_page: from address not mapped (from=%08X; to=%08X; size=%08X", from, to, size);        /* Didn't work, squeal like a piggy... */
        !          1985:                        return;                                                                                         /* Didn't find any, return... */
        !          1986:                }
        !          1987:        
        !          1988:                from += PAGE_SIZE;                                                                              /* Get the next "from" address */
        !          1989:                to += PAGE_SIZE;                                                                                /* Get the next "to" address */
        !          1990:        }
        !          1991: 
        !          1992:        debugLog2(67, from, to);                                        /* Log pmap_map call */
        !          1993:                
        !          1994:        return;                                                                                                         /* Bye... */
        !          1995: }
        !          1996: 
        !          1997: /*
        !          1998:  * Move pages from one kernel virtual address to another.
        !          1999:  * Both addresses are assumed to reside in the Sysmap,
        !          2000:  * and size must be a multiple of the page size.
        !          2001:  */
        !          2002: void
        !          2003: pagemove(
        !          2004:        register caddr_t from,
        !          2005:        register caddr_t to,
        !          2006:        int size)
        !          2007: {
        !          2008:        pmap_move_page((unsigned long)from, (unsigned long)to, (vm_size_t)size);
        !          2009: }
        !          2010: #endif

unix.superglobalmegacorp.com

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