X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/9bccf70c0258c7cac2dcb80011b2a964d884c552..4452a7af2eac33dbad800bcc91f2399d62c18f53:/osfmk/ppc/pmap.h?ds=inline diff --git a/osfmk/ppc/pmap.h b/osfmk/ppc/pmap.h index 0a4d2e97e..483726de0 100644 --- a/osfmk/ppc/pmap.h +++ b/osfmk/ppc/pmap.h @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ @@ -55,57 +61,203 @@ #include #include #include +#include -struct pmap { - queue_head_t pmap_link; /* MUST BE FIRST */ - unsigned int pmapvr; /* Virtual to real conversion mask */ - space_t space; /* space for this pmap */ -#define BMAPLOCK 0x00000001 - struct blokmap *bmaps; /* Physical pointer to odd-size page maps */ - int ref_count; /* reference count */ - unsigned int vflags; /* Alternate map validity flags */ -#define pmapBatVal 0xFF000000 -#define pmapBatDVal 0xF0000000 -#define pmapBatIVal 0x0F000000 -#define pmapFlags 0x00FF0000 -#define pmapSubord 0x00800000 -#define pmapAltSeg 0x0000FFFF - unsigned int spaceNum; /* Space number */ -/* PPC line boundary here - 020 */ - unsigned int pmapSegs[16]; /* Contents of segment register if different than base space */ -/* PPC line boundary here - 060 */ - struct pmap *pmapPmaps[16]; /* Pointer to next lower level of pmaps */ -/* PPC line boundary here - 0A0 */ -/* Note: this must start on a word boundary */ - unsigned short pmapUsage[128]; /* Count of pages mapped into 32mb (8192 page) slots */ -#define pmapUsageShft 25 -#define pmapUsageMask 0x0000007F -#define pmapUsageSize (32*1024*1024) +#define maxPPage32 0x000FFFFF /* Maximum page number in 32-bit machines */ + +typedef uint32_t shexlock; + +#pragma pack(4) /* Make sure the structure stays as we defined it */ + +struct sgc { + uint64_t sgcESID; /* ESID portion of segment cache */ +#define sgcESmsk 0xFFFFFFFFF0000000ULL /* ESID portion of segment register cache */ + uint64_t sgcVSID; /* VSID portion of segment cache */ +#define sgcVSmsk 0xFFFFFFFFFFFFF000ULL /* VSID mask */ +#define sgcVSKeys 0x0000000000000C00ULL /* Protection keys */ +#define sgcVSKeyUsr 53 /* User protection key */ +#define sgcVSNoEx 0x0000000000000200ULL /* No execute */ +}; +#pragma pack() + +typedef struct sgc sgc; + +#pragma pack(4) /* Make sure the structure stays as we defined it */ +struct pmap_vmm_stats { + unsigned int vxsGpf; /* Guest faults */ + unsigned int vxsGpfMiss; /* Faults that miss in hash table */ + + unsigned int vxsGrm; /* Guest mapping remove requests */ + unsigned int vxsGrmMiss; /* Remove misses in hash table */ + unsigned int vxsGrmActive; /* Remove hits that are active */ + + unsigned int vxsGra; /* Guest remove all mappings requests */ + unsigned int vxsGraHits; /* Remove hits in hash table */ + unsigned int vxsGraActive; /* Remove hits that are active */ + + unsigned int vxsGrl; /* Guest remove local mappings requests */ + unsigned int vxsGrlActive; /* Active mappings removed */ + + unsigned int vxsGrs; /* Guest mapping resumes */ + unsigned int vxsGrsHitAct; /* Resume hits active entry */ + unsigned int vxsGrsHitSusp; /* Resume hits suspended entry */ + unsigned int vxsGrsMissGV; /* Resume misses on guest virtual */ + unsigned int vxsGrsHitPE; /* Resume hits on host virtual */ + unsigned int vxsGrsMissPE; /* Resume misses on host virtual */ + + unsigned int vxsGad; /* Guest mapping adds */ + unsigned int vxsGadHit; /* Add hits entry (active or dormant) */ + unsigned int vxsGadFree; /* Add takes free entry in group */ + unsigned int vxsGadDormant; /* Add steals dormant entry in group */ + unsigned int vxsGadSteal; /* Add steals active entry in group */ -/* PPC line boundary here - 1A0 */ - struct pmap_statistics stats; /* statistics */ - decl_simple_lock_data(,lock) /* lock on map */ + unsigned int vxsGsu; /* Guest mapping suspends */ + unsigned int vxsGsuHit; /* Suspend hits entry (active only) */ + unsigned int vxsGsuMiss; /* Suspend misses entry */ + + unsigned int vxsGtd; /* Guest test ref&chg */ + unsigned int vxsGtdHit; /* Test r&c hits entry (active only) */ + unsigned int vxsGtdMiss; /* Test r&c misses entry */ +}; +#pragma pack() +typedef struct pmap_vmm_stats pmap_vmm_stats; + +/* Not wanting to tax all of our customers for the sins of those that use virtual operating + systems, we've built the hash table from its own primitive virtual memory. We first + allocate a pmap_vmm_ext with sufficient space following to accomodate the hash table + index (one 64-bit physical address per 4k-byte page of hash table). The allocation + must not cross a 4k-byte page boundary (we'll be accessing the block with relocation + off), so we'll try a couple of times, then just burn a whole page. We stuff the effective + address of the cache-aligned index into hIdxBase; the physical-mode code locates the index + by adding the size of a pmap_vmm_extension to its translated physical address, then rounding + up to the next 32-byte boundary. Now we grab enough virtual pages to contain the hash table, + and fill in the index with the page's physical addresses. For the final touch that's sure + to please, we initialize the hash table. Mmmmm, golden brown perfection. + */ + +#pragma pack(4) +struct pmap_vmm_ext { + addr64_t vmxSalt; /* This block's virt<->real conversion salt */ + addr64_t vmxHostPmapPhys; /* Host pmap physical address */ + struct pmap *vmxHostPmap; /* Host pmap effective address */ + addr64_t *vmxHashPgIdx; /* Hash table physical index base address */ + vm_offset_t *vmxHashPgList; /* List of virtual pages comprising the hash table */ + unsigned int *vmxActiveBitmap; /* Bitmap of active mappings in hash table */ + pmap_vmm_stats vmxStats; /* Stats for VMM assists */ +#define VMX_HPIDX_OFFSET ((sizeof(pmap_vmm_ext) + 127) & ~127) + /* The hash table physical index begins at the first + 128-byte boundary after the pmap_vmm_ext struct */ +#define VMX_HPLIST_OFFSET (VMX_HPIDX_OFFSET + (GV_HPAGES * sizeof(addr64_t))) +#define VMX_ACTMAP_OFFSET (VMX_HPLIST_OFFSET + (GV_HPAGES * sizeof(vm_offset_t))) +}; +#pragma pack() +typedef struct pmap_vmm_ext pmap_vmm_ext; + +#pragma pack(4) /* Make sure the structure stays as we defined it */ +struct pmap { + queue_head_t pmap_link; /* MUST BE FIRST */ + addr64_t pmapvr; /* Virtual to real conversion mask */ + shexlock pmapSXlk; /* Shared/Exclusive lock for mapping changes */ + unsigned int space; /* space for this pmap */ +#define invalSpace 0x00000001 /* Predefined always invalid space */ + int ref_count; /* reference count */ + unsigned int pmapFlags; /* Flags */ +#define pmapKeys 0x00000007 /* Keys and no execute bit to use with this pmap */ +#define pmapKeyDef 0x00000006 /* Default keys - Sup = 1, user = 1, no ex = 0 */ +#define pmapVMhost 0x00000010 /* pmap with Virtual Machines attached to it */ +#define pmapVMgsaa 0x00000020 /* Guest shadow assist active */ +#define pmapNXdisabled 0x00000040 /* no-execute disabled for this pmap */ + unsigned int spaceNum; /* Space number */ + unsigned int pmapCCtl; /* Cache control */ +#define pmapCCtlVal 0xFFFF0000 /* Valid entries */ +#define pmapCCtlLck 0x00008000 /* Lock bit */ +#define pmapCCtlLckb 16 /* Lock bit */ +#define pmapCCtlGen 0x00007FFF /* Generation number */ + +#define pmapSegCacheCnt 16 /* Maximum number of cache entries */ +#define pmapSegCacheUse 16 /* Number of cache entries to use */ + + struct pmap *freepmap; /* Free pmaps */ + pmap_vmm_ext *pmapVmmExt; /* VMM extension block, for VMM host and guest pmaps */ + addr64_t pmapVmmExtPhys; /* VMM extension block physical address */ +/* 0x038 */ + uint64_t pmapSCSubTag; /* Segment cache sub-tags. This is a 16 entry 4 bit array */ +/* 0x040 */ + sgc pmapSegCache[pmapSegCacheCnt]; /* SLD values cached for quick load */ + +/* 0x140 */ +/* if fanout is 4, then shift is 1, if fanout is 8 shift is 2, etc */ +#define kSkipListFanoutShift 1 +/* with n lists, we can handle (fanout**n) pages optimally */ +#define kSkipListMaxLists 12 + unsigned char pmapCurLists; /* 0x140 - max #lists any mapping in this pmap currently has */ + unsigned char pmapRsv2[3]; + uint32_t pmapRandNum; /* 0x144 - used by mapSetLists() as a random number generator */ + addr64_t pmapSkipLists[kSkipListMaxLists]; /* 0x148 - the list headers */ +/* following statistics conditionally gathered */ + uint64_t pmapSearchVisits; /* 0x1A8 - nodes visited searching pmaps */ + uint32_t pmapSearchCnt; /* 0x1B0 - number of calls to mapSearch or mapSearchFull */ + + unsigned int pmapRsv3[3]; + +/* 0x1C0 */ + + struct pmap_statistics stats; /* statistics */ /* Need to pad out to a power of 2 - right now it is 512 bytes */ #define pmapSize 512 }; +#pragma pack() + +#pragma pack(4) +struct pmapTransTab { + addr64_t pmapPAddr; /* Physcial address of pmap */ + unsigned int pmapVAddr; /* Virtual address of pmap */ +}; +#pragma pack() /* Make sure the structure stays as we defined it */ + +typedef struct pmapTransTab pmapTransTab; + +/* + * Address Chunk IDentified Table + */ + +struct acidTabEnt { + unsigned int acidVAddr; /* Virtual address of pmap or pointer to next free entry */ + unsigned int acidGas; /* reserved */ + addr64_t acidPAddr; /* Physcial address of pmap */ +}; + +typedef struct acidTabEnt acidTabEnt; + +extern acidTabEnt *acidTab; /* Pointer to acid table */ +extern acidTabEnt *acidFree; /* List of free acid entries */ #define PMAP_NULL ((pmap_t) 0) -extern pmap_t kernel_pmap; /* The kernel's map */ extern pmap_t cursor_pmap; /* The pmap to start allocations with */ - +extern pmap_t sharedPmap; +extern unsigned int sharedPage; +extern int ppc_max_adrsp; /* Maximum number of concurrent address spaces allowed. */ +extern addr64_t vm_max_address; /* Maximum effective address supported */ +extern addr64_t vm_max_physical; /* Maximum physical address supported */ +extern pmapTransTab *pmapTrans; /* Space to pmap translate table */ #define PMAP_SWITCH_USER(th, map, my_cpu) th->map = map; -#define PMAP_ACTIVATE(pmap, th, cpu) -#define PMAP_DEACTIVATE(pmap, th, cpu) #define PMAP_CONTEXT(pmap,th) #define pmap_kernel_va(VA) \ - (((VA) >= VM_MIN_KERNEL_ADDRESS) && ((VA) <= VM_MAX_KERNEL_ADDRESS)) + (((VA) >= VM_MIN_KERNEL_ADDRESS) && ((VA) <= vm_last_addr)) #define PPC_SID_KERNEL 0 /* Must change KERNEL_SEG_REG0_VALUE if !0 */ -#define SID_MAX ((1<<20) - 1) /* Space ID=20 bits, segment_id=SID + 4 bits */ + +#define maxAdrSp 16384 +#define maxAdrSpb 14 +#define USER_MEM_WINDOW_VADDR 0x00000000E0000000ULL +#define PHYS_MEM_WINDOW_VADDR 0x0000000100000000ULL +#define IO_MEM_WINDOW_VADDR 0x0000000080000000ULL +#define IO_MEM_WINDOW_SIZE 0x0000000080000000ULL +#define pmapSmallBlock 65536 #define pmap_kernel() (kernel_pmap) #define pmap_resident_count(pmap) ((pmap)->stats.resident_count) @@ -113,9 +265,6 @@ extern pmap_t cursor_pmap; /* The pmap to start allocations with */ #define pmap_copy(dpmap,spmap,da,len,sa) #define pmap_update() -#define pmap_phys_address(x) ((x) << PPC_PGSHIFT) -#define pmap_phys_to_frame(x) ((x) >> PPC_PGSHIFT) - #define PMAP_DEFAULT_CACHE 0 #define PMAP_INHIBIT_CACHE 1 #define PMAP_GUARDED_CACHE 2 @@ -123,60 +272,66 @@ extern pmap_t cursor_pmap; /* The pmap to start allocations with */ #define PMAP_NO_GUARD_CACHE 8 /* corresponds to cached, coherent, not writethru, not guarded */ -#define VM_WIMG_DEFAULT VM_MEM_COHERENT -#define VM_WIMG_IO VM_MEM_COHERENT | \ - VM_MEM_NOT_CACHEABLE | VM_MEM_GUARDED +#define VM_WIMG_DEFAULT (VM_MEM_COHERENT) +#define VM_WIMG_COPYBACK (VM_MEM_COHERENT) +#define VM_WIMG_IO (VM_MEM_COHERENT | \ + VM_MEM_NOT_CACHEABLE | VM_MEM_GUARDED) +#define VM_WIMG_WTHRU (VM_MEM_WRITE_THROUGH | VM_MEM_COHERENT | VM_MEM_GUARDED) +/* write combining mode, aka store gather */ +#define VM_WIMG_WCOMB (VM_MEM_NOT_CACHEABLE | VM_MEM_COHERENT) /* * prototypes. */ -extern void ppc_protection_init(void); -extern vm_offset_t phystokv(vm_offset_t pa); /* Get kernel virtual address from physical */ -extern vm_offset_t kvtophys(vm_offset_t va); /* Get physical address from kernel virtual */ +extern addr64_t kvtophys(vm_offset_t va); /* Get physical address from kernel virtual */ extern vm_offset_t pmap_map(vm_offset_t va, vm_offset_t spa, vm_offset_t epa, - vm_prot_t prot); + vm_prot_t prot, + unsigned int flags); extern kern_return_t pmap_add_physical_memory(vm_offset_t spa, vm_offset_t epa, boolean_t available, unsigned int attr); -extern vm_offset_t pmap_map_bd(vm_offset_t va, - vm_offset_t spa, - vm_offset_t epa, - vm_prot_t prot); -extern void pmap_bootstrap(unsigned int mem_size, +extern void pmap_bootstrap(uint64_t msize, vm_offset_t *first_avail, - vm_offset_t *first_phys_avail, unsigned int kmapsize); -extern void pmap_block_map(vm_offset_t pa, - vm_size_t size, - vm_prot_t prot, - int entry, - int dtlb); -extern void pmap_switch(pmap_t); - -extern vm_offset_t pmap_extract(pmap_t pmap, - vm_offset_t va); + unsigned int kmapsize); -extern void pmap_remove_all(vm_offset_t pa); +extern vm_offset_t pmap_boot_map(vm_size_t size); -extern boolean_t pmap_verify_free(vm_offset_t pa); -extern void sync_cache(vm_offset_t pa, unsigned length); +extern void sync_cache64(addr64_t pa, unsigned length); +extern void sync_ppage(ppnum_t pa); +extern void sync_cache_virtual(vm_offset_t va, unsigned length); extern void flush_dcache(vm_offset_t va, unsigned length, boolean_t phys); +extern void flush_dcache64(addr64_t va, unsigned length, boolean_t phys); extern void invalidate_dcache(vm_offset_t va, unsigned length, boolean_t phys); +extern void invalidate_dcache64(addr64_t va, unsigned length, boolean_t phys); extern void invalidate_icache(vm_offset_t va, unsigned length, boolean_t phys); -extern void pmap_sync_caches_phys(vm_offset_t pa); -extern void invalidate_cache_for_io(vm_offset_t va, unsigned length, boolean_t phys); -extern void pmap_map_block(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_size_t size, - vm_prot_t prot, int attr, unsigned int flags); /* Map a block */ -extern kern_return_t pmap_map_block_opt(vm_map_t map, vm_offset_t *va, - vm_offset_t pa, vm_size_t size, vm_prot_t prot, int attr); /* Map a block allocating an optimal virtual address */ -extern kern_return_t vm_map_block(vm_map_t map, vm_offset_t *va, vm_offset_t *bnd, vm_offset_t pa, - vm_size_t size, vm_prot_t prot); - -extern kern_return_t pmap_nest(pmap_t grand, pmap_t subord, vm_offset_t vaddr, vm_size_t size); - -extern void pmap_ver(pmap_t pmap, vm_offset_t sva, vm_offset_t eva); +extern void invalidate_icache64(addr64_t va, unsigned length, boolean_t phys); +extern void pmap_sync_page_data_phys(ppnum_t pa); +extern void pmap_sync_page_attributes_phys(ppnum_t pa); +extern void pmap_map_block(pmap_t pmap, addr64_t va, ppnum_t pa, uint32_t size, vm_prot_t prot, int attr, unsigned int flags); +extern int pmap_map_block_rc(pmap_t pmap, addr64_t va, ppnum_t pa, uint32_t size, vm_prot_t prot, int attr, unsigned int flags); + +extern kern_return_t pmap_nest(pmap_t grand, pmap_t subord, addr64_t vstart, addr64_t nstart, uint64_t size); +extern kern_return_t pmap_unnest(pmap_t grand, addr64_t vaddr); +extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); +extern void MapUserMemoryWindowInit(void); +extern addr64_t MapUserMemoryWindow(vm_map_t map, addr64_t va); +extern boolean_t pmap_eligible_for_execute(ppnum_t pa); +extern int pmap_list_resident_pages( + struct pmap *pmap, + vm_offset_t *listp, + int space); +extern void pmap_init_sharedpage(vm_offset_t cpg); +extern void pmap_map_sharedpage(task_t task, pmap_t pmap); +extern void pmap_unmap_sharedpage(pmap_t pmap); +extern void pmap_disable_NX(pmap_t pmap); +/* Not required for ppc: */ +static inline void pmap_set_4GB_pagezero(__unused pmap_t pmap) {} +static inline void pmap_clear_4GB_pagezero(__unused pmap_t pmap) {} + + #endif /* _PPC_PMAP_H_ */