2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Header files for the hardware virtual memory mapping stuff
25 #ifndef _PPC_MAPPINGS_H_
26 #define _PPC_MAPPINGS_H_
30 #include <mach/mach_types.h>
31 #include <mach/vm_types.h>
32 #include <mach/machine/vm_types.h>
33 #include <mach/vm_prot.h>
34 #include <mach/vm_statistics.h>
35 #include <kern/assert.h>
36 #include <kern/cpu_number.h>
37 #include <kern/lock.h>
38 #include <kern/queue.h>
39 #include <ppc/proc_reg.h>
42 * Don't change these structures unless you change the assembly code
46 * This control block serves as anchor for all virtual mappings of the same physical
47 * page, i.e., aliases. There is a table for each bank (mem_region). All tables
48 * must reside in V=R storage and within the first 2GB of memory. Also, the
49 * mappings to which it points must be on at least a 64-byte boundary. These
50 * requirements allow a total of 2 bits for status and flags, and allow all address
51 * calculations to be 32-bit.
54 #pragma pack(4) /* Make sure the structure stays as we defined it */
55 typedef struct phys_entry
{
56 addr64_t ppLink
; /* Physical pointer to aliased mappings and flags */
57 #define ppLock 0x8000000000000000LL /* Lock for alias chain */
58 #define ppN 0x4000000000000000LL /* Not executable */
59 #define ppFlags 0x000000000000003FLL /* Status and flags */
60 #define ppI 0x0000000000000020LL /* Cache inhibited */
61 #define ppIb 58 /* Cache inhibited */
62 #define ppG 0x0000000000000010LL /* Guarded */
63 #define ppGb 59 /* Guarded */
64 #define ppR 0x0000000000000008LL /* Referenced */
65 #define ppRb 60 /* Referenced */
66 #define ppC 0x0000000000000004LL /* Changed */
67 #define ppCb 61 /* Changed */
68 #define ppPP 0x0000000000000003LL /* Protection */
69 #define ppPPb 62 /* Protection begin */
70 #define ppPPe 63 /* Protection end */
74 /* Memory may be non-contiguous. This data structure contains info
75 * for mapping this non-contiguous space into the contiguous
76 * physical->virtual mapping tables. An array of this type is
77 * provided to the pmap system at bootstrap by ppc_vm_init.
81 #pragma pack(4) /* Make sure the structure stays as we defined it */
82 typedef struct mem_region
{
83 phys_entry
*mrPhysTab
; /* Base of region table */
84 ppnum_t mrStart
; /* Start of region */
85 ppnum_t mrEnd
; /* Last page in region */
86 ppnum_t mrAStart
; /* Next page in region to allocate */
87 ppnum_t mrAEnd
; /* Last page in region to allocate */
91 #define mrSize sizeof(mem_region_t)
92 #define PMAP_MEM_REGION_MAX 26
94 extern mem_region_t pmap_mem_regions
[PMAP_MEM_REGION_MAX
+ 1];
95 extern int pmap_mem_regions_count
;
100 #pragma pack(4) /* Make sure the structure stays as we defined it */
101 typedef struct PCA
{ /* PTEG Control Area */
103 unsigned int PCAallo
; /* Allocation controls */
104 struct PCAalflgs
{ /* Keep these in order!!! */
105 unsigned char PCAfree
; /* Indicates the slot is free */
106 unsigned char PCAsteal
; /* Steal scan start position */
107 unsigned char PCAauto
; /* Indicates that the PTE was autogenned */
108 unsigned char PCAmisc
; /* Misc. flags */
109 #define PCAlock 1 /* This locks up the associated PTEG */
116 /* Mappings currently come in two sizes: 64 and 128 bytes. The only difference is the
117 * number of skiplists (ie, mpLists): 64-byte mappings have 1-4 lists and 128-byte mappings
118 * have from 5-12. Only 1 in 256 mappings is large, so an average mapping is 64.25 bytes.
119 * All mappings are 64-byte aligned.
121 * Special note on mpFIP and mpRIP:
122 * These flags are manipulated under various locks. RIP is always set under an
123 * exclusive lock while FIP is shared. The only worry is that there is a possibility that
124 * FIP could be attempted by more than 1 processor at a time. Obviously, one will win.
125 * The other(s) bail all the way to user state and may refault (or not). There are only
126 * a few things in mpFlags that are not static, mpFIP, mpRIP, mpRemovable, and mpBusy.
128 * We organize these so that mpFIP is in a byte with static data and mpRIP and mpRemovable
129 * is in another. That means that we can use a store byte to update the guys without
130 * worrying about load and reserve. Note that mpFIP must be set atomically because it is
131 * under a share lock, but it may be clear with a simple store byte. So far as mpRIP
132 * goes, it is in the same byte as mpRemovable. However, mpRemovable is set atomically
133 * but never cleared, and mpRIP will not ever be set until after mpRemovable. Note that
134 * mpRIP is never cleared either.
137 #pragma pack(4) /* Make sure the structure stays as we defined it */
138 typedef struct mapping
{
139 unsigned int mpFlags
; /* 0x000 - Various flags, lock bit. These are static except for lock */
140 #define mpBusy 0xFF000000 /* Busy count */
141 #define mpPIndex 0x00FF0000 /* Index into physical table (in words) */
142 #define mpSpecial 0x00008000 /* Special mapping - processor specific. */
143 #define mpSpecialb 16 /* Special mapping - processor specific. */
144 #define mpFIP 0x00004000 /* Fault in progress */
145 #define mpFIPb 17 /* Fault in progress */
146 #define mpNest 0x00001000 /* Mapping describes nested pmap */
147 #define mpNestb 19 /* Mapping describes nested pmap */
148 #define mpPerm 0x00000800 /* Mapping is permanent */
149 #define mpPermb 20 /* Mapping is permanent */
150 #define mpBlock 0x00000400 /* Mapping is a block map - used for V=F or I/O */
151 #define mpBlockb 21 /* Mapping is a block map - used for V=F or I/O */
152 #define mpRIP 0x00000080 /* Remove in progress - DO NOT MOVE */
153 #define mpRIPb 24 /* Remove in progress */
154 #define mpRemovable 0x00000040 /* Mapping is removable - DO NOT MOVE */
155 #define mpRemovableb 25 /* Mapping is removable */
156 #define mpRSVD1 0x00002330 /* Reserved for future use */
157 #define mpLists 0x0000001F /* Number of skip lists mapping is on, max of 27 */
158 #define mpListsb 27 /* Number of skip lists mapping is on, max of 27 */
160 unsigned short mpSpace
; /* 0x004 - Address space hash */
161 unsigned short mpBSize
; /* 0x006 - Block size - 1 in pages - max block size 256MB */
162 unsigned int mpPte
; /* 0x008 - Offset to PTEG in hash table. Offset to exact PTE if mpHValid set - NOTE: this MUST be 0 for block mappings */
163 #define mpHValid 0x00000001 /* PTE is entered in hash table */
164 #define mpHValidb 31 /* PTE is entered in hash table */
165 ppnum_t mpPAddr
; /* 0x00C - Physical page number */
166 addr64_t mpVAddr
; /* 0x010 - Starting virtual address */
167 #define mpHWFlags 0x0000000000000FFFULL /* Reference/Change, WIMG, AC, N, protection flags from PTE */
168 #define mpPP 0x0000000000000007ULL /* Protection flags */
170 #define mpKKN 0x0000000000000007ULL /* Segment key and no execute flag (nested pmap) */
172 #define mpWIMG 0x0000000000000078ULL /* Attribute bits */
174 #define mpW 0x0000000000000040ULL
176 #define mpI 0x0000000000000020ULL
178 #define mpM 0x0000000000000010ULL
180 #define mpG 0x0000000000000008ULL
183 #define mpC 0x0000000000000080ULL /* Change bit */
185 #define mpR 0x0000000000000100ULL /* Reference bit */
187 addr64_t mpAlias
; /* 0x018 - Pointer to alias mappings of physical page */
188 #define mpNestReloc mpAlias /* 0x018 - Redefines mpAlias relocation value of vaddr to nested pmap value */
189 #define mpBlkRemCur mpAlias /* 0x018 - Next offset in block map to remove (this is 4 bytes) */
190 addr64_t mpList0
; /* 0x020 - Forward chain of mappings. This one is always used */
191 addr64_t mpList
[3]; /* 0x028 - Forward chain of mappings. Next higher order */
192 /* 0x040 - End of basic mapping */
193 #define mpBasicSize 64
194 #define mpBasicLists 4
195 /* note the dependence on kSkipListMaxLists, which must be <= #lists in a 256-byte mapping (ie, <=28) */
196 /* addr64_t mpList4[8]; 0x040 - First extended list entries */
197 /* 0x080 - End of first extended mapping */
198 /* addr64_t mpList12[8]; 0x080 - Second extended list entries */
199 /* 0x0C0 - End of second extended mapping */
200 /* addr64_t mpList20[8]; 0x0C0 - Third extended list entries */
201 /* 0x100 - End of third extended mapping */
206 #define MAPPING_NULL ((struct mapping *) 0)
208 #define mapDirect 0x08
209 #define mapRWNA 0x00000000
210 #define mapRWRO 0x00000001
211 #define mapRWRW 0x00000002
212 #define mapRORO 0x00000003
214 /* All counts are in units of basic 64-byte mappings. A 128-byte mapping is
215 * just two adjacent 64-byte entries.
217 #pragma pack(4) /* Make sure the structure stays as we defined it */
219 typedef struct mappingflush
{
220 addr64_t addr
; /* Start address to search mapping */
221 unsigned int spacenum
; /* Last space num to search pmap */
222 unsigned int mapfgas
[1]; /* Pad to 64 bytes */
225 typedef struct mappingctl
{
226 unsigned int mapclock
; /* Mapping allocation lock */
227 unsigned int mapcrecurse
; /* Mapping allocation recursion control */
228 struct mappingblok
*mapcnext
; /* First mapping block with free entries */
229 struct mappingblok
*mapclast
; /* Last mapping block with free entries */
230 struct mappingblok
*mapcrel
; /* List of deferred block releases */
231 unsigned int mapcfree
; /* Total free entries on list */
232 unsigned int mapcinuse
; /* Total entries in use */
233 unsigned int mapcreln
; /* Total blocks on pending release list */
234 int mapcholdoff
; /* Hold off clearing release list */
235 unsigned int mapcfreec
; /* Total calls to mapping free */
236 unsigned int mapcallocc
; /* Total calls to mapping alloc */
237 unsigned int mapcbig
; /* Count times a big mapping was requested of mapping_alloc */
238 unsigned int mapcbigfails
; /* Times caller asked for a big one but we gave 'em a small one */
239 unsigned int mapcmin
; /* Minimum free mappings to keep */
240 unsigned int mapcmaxalloc
; /* Maximum number of mappings allocated at one time */
241 unsigned int mapcgas
[1]; /* Pad to 64 bytes */
242 struct mappingflush mapcflush
;
246 /* MAPPERBLOK is the number of basic 64-byte mappings per block (ie, per page.) */
247 #define MAPPERBLOK 63
248 #define MAPALTHRSH (4*MAPPERBLOK)
249 #define MAPFRTHRSH (2 * ((MAPALTHRSH + MAPPERBLOK - 1) / MAPPERBLOK))
250 typedef struct mappingblok
{
251 unsigned int mapblokfree
[2]; /* Bit map of free mapping entrys */
252 addr64_t mapblokvrswap
; /* Virtual address XORed with physical address */
253 unsigned int mapblokflags
; /* Various flags */
254 #define mbPerm 0x80000000 /* Block is permanent */
255 struct mappingblok
*nextblok
; /* Pointer to the next mapping block */
258 #define mapRemChunk 128
260 #define mapRetCode 0xF
264 #define mapRtNotFnd 3
267 #define mapRtRemove 6
268 #define mapRtMapDup 7
270 extern mappingctl mapCtl
; /* Mapping allocation control */
272 extern addr64_t
mapping_remove(pmap_t pmap
, addr64_t va
); /* Remove a single mapping for this VADDR */
273 extern mapping
*mapping_find(pmap_t pmap
, addr64_t va
, addr64_t
*nextva
, int full
); /* Finds a mapping */
274 extern void mapping_free_init(vm_offset_t mbl
, int perm
, boolean_t locked
); /* Sets start and end of a block of mappings */
275 extern void mapping_adjust(void); /* Adjust free mapping count */
276 extern void mapping_free_prime(void); /* Primes the mapping block release list */
277 extern void mapping_prealloc(unsigned int); /* Preallocate mappings for large use */
278 extern void mapping_relpre(void); /* Releases preallocate request */
279 extern void mapping_init(void); /* Do initial stuff */
280 extern mapping
*mapping_alloc(int lists
); /* Obtain a mapping */
281 extern void mapping_free(struct mapping
*mp
); /* Release a mapping */
282 extern boolean_t
mapping_tst_ref(ppnum_t pa
); /* Tests the reference bit of a physical page */
283 extern boolean_t
mapping_tst_mod(ppnum_t pa
); /* Tests the change bit of a physical page */
284 extern void mapping_set_ref(ppnum_t pa
); /* Sets the reference bit of a physical page */
285 extern void mapping_clr_ref(ppnum_t pa
); /* Clears the reference bit of a physical page */
286 extern void mapping_set_mod(ppnum_t pa
); /* Sets the change bit of a physical page */
287 extern void mapping_clr_mod(ppnum_t pa
); /* Clears the change bit of a physical page */
288 extern void mapping_protect_phys(ppnum_t pa
, vm_prot_t prot
); /* Change protection of all mappings to page */
289 extern int mapping_protect(pmap_t pmap
, addr64_t va
, vm_prot_t prot
, addr64_t
*nextva
); /* Change protection of a single mapping to page */
290 extern addr64_t
mapping_make(pmap_t pmap
, addr64_t va
, ppnum_t pa
, unsigned int flags
, unsigned int size
, vm_prot_t prot
); /* Make a mapping */
291 /* Flags for mapping_make */
292 #define mmFlgBlock 0x80000000 /* This is a block map, use size for number of pages covered */
293 #define mmFlgUseAttr 0x40000000 /* Use specified attributes */
294 #define mmFlgPerm 0x20000000 /* Mapping is permanant */
295 #define mmFlgCInhib 0x00000002 /* Cahching inhibited - use if mapFlgUseAttr set or block */
296 #define mmFlgGuarded 0x00000001 /* Access guarded - use if mapFlgUseAttr set or block */
297 extern void mapping_purge(ppnum_t pa
); /* Remove all mappings for this physent */
298 extern addr64_t
mapping_p2v(pmap_t pmap
, ppnum_t pa
); /* Finds first virtual mapping of a physical page in a space */
299 extern void mapping_drop_busy(struct mapping
*mapping
); /* Drops busy count on mapping */
300 extern phys_entry
*mapping_phys_lookup(ppnum_t pp
, unsigned int *pindex
); /* Finds the physical entry for the page */
301 extern int mapalc1(struct mappingblok
*mb
); /* Finds and allcates a 1-bit mapping entry */
302 extern int mapalc2(struct mappingblok
*mb
); /* Finds and allcates a 2-bit mapping entry */
303 extern void ignore_zero_fault(boolean_t type
); /* Sets up to ignore or honor any fault on page 0 access for the current thread */
306 extern mapping
*hw_rem_map(pmap_t pmap
, addr64_t va
, addr64_t
*next
); /* Remove a mapping from the system */
307 extern mapping
*hw_purge_map(pmap_t pmap
, addr64_t va
, addr64_t
*next
); /* Remove a regular mapping from the system */
308 extern mapping
*hw_purge_space(struct phys_entry
*pp
, pmap_t pmap
); /* Remove the first mapping for a specific pmap from physentry */
309 extern mapping
*hw_purge_phys(struct phys_entry
*pp
); /* Remove the first mapping for a physentry */
310 extern mapping
*hw_find_map(pmap_t pmap
, addr64_t va
, addr64_t
*nextva
); /* Finds a mapping */
311 extern addr64_t
hw_add_map(pmap_t pmap
, struct mapping
*mp
); /* Add a mapping to a pmap */
312 extern int hw_protect(pmap_t pmap
, addr64_t va
, vm_prot_t prot
, addr64_t
*nextva
); /* Change the protection of a virtual page */
313 extern unsigned int hw_test_rc(pmap_t pmap
, addr64_t va
, boolean_t reset
); /* Test and optionally reset the RC bit of specific mapping */
315 extern unsigned int hw_phys_walk(struct phys_entry
*pp
, unsigned int preop
, unsigned int op
, /* Perform function on all mappings on a physical page */
316 unsigned int postop
, unsigned int parm
);
317 #define hwpNoop 0 /* No operation */
318 #define hwpSPrtPhy 1 /* Sets protection in physent */
319 #define hwpSPrtMap 2 /* Sets protection in mapping */
320 #define hwpSAtrPhy 3 /* Sets attributes in physent */
321 #define hwpSAtrMap 4 /* Sets attributes in mapping */
322 #define hwpCRefPhy 5 /* Clears reference in physent */
323 #define hwpCRefMap 6 /* Clears reference in mapping */
324 #define hwpCCngPhy 7 /* Clears change in physent */
325 #define hwpCCngMap 8 /* Clears change in mapping */
326 #define hwpSRefPhy 9 /* Sets reference in physent */
327 #define hwpSRefMap 10 /* Sets reference in mapping */
328 #define hwpSCngPhy 11 /* Sets change in physent */
329 #define hwpSCngMap 12 /* Sets change in mapping */
330 #define hwpTRefPhy 13 /* Tests reference in physent */
331 #define hwpTRefMap 14 /* Tests reference in mapping */
332 #define hwpTCngPhy 15 /* Tests change in physent */
333 #define hwpTCngMap 16 /* Tests change in mapping */
335 extern boolean_t
hw_tst_mod(struct phys_entry
*pp
); /* Tests change bit */
336 extern void hw_set_mod(struct phys_entry
*pp
); /* Set change bit */
337 extern void hw_clr_mod(struct phys_entry
*pp
); /* Clear change bit */
339 extern boolean_t
hw_tst_ref(struct phys_entry
*pp
); /* Tests reference bit */
340 extern void hw_set_ref(struct phys_entry
*pp
); /* Set reference bit */
341 extern void hw_clr_ref(struct phys_entry
*pp
); /* Clear reference bit */
343 extern void hw_set_user_space(pmap_t pmap
); /* Indicate we need a space switch */
344 extern void hw_set_user_space_dis(pmap_t pmap
); /* Indicate we need a space switch (already disabled) */
345 extern void hw_setup_trans(void); /* Setup hardware for translation */
346 extern void hw_start_trans(void); /* Start translation for the first time */
347 extern void hw_map_seg(pmap_t pmap
, addr64_t seg
, addr64_t va
); /* Validate a segment */
348 extern void hw_blow_seg(addr64_t seg
); /* Invalidate a segment */
349 extern void invalidateSegs(pmap_t pmap
); /* Invalidate the segment cache */
350 extern struct phys_entry
*pmap_find_physentry(ppnum_t pa
);
351 extern void mapLog(unsigned int laddr
, unsigned int type
, addr64_t va
);
352 extern unsigned int mapSkipListVerifyC(pmap_t pmap
, unsigned long long *dumpa
);
353 extern void fillPage(ppnum_t pa
, unsigned int fill
);
355 extern unsigned int mappingdeb0
; /* (TEST/DEBUG) */
356 extern unsigned int incrVSID
; /* VSID increment value */
358 #endif /* _PPC_MAPPINGS_H_ */