Annotation of XNU/osfmk/ppc/pmap.c, revision 1.1.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.