Annotation of sys/arch/amd64/include/pmap.h, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pmap.h,v 1.16 2007/07/06 11:46:48 art Exp $ */
2: /* $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */
3:
4: /*
5: *
6: * Copyright (c) 1997 Charles D. Cranor and Washington University.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgment:
19: * This product includes software developed by Charles D. Cranor and
20: * Washington University.
21: * 4. The name of the author may not be used to endorse or promote products
22: * derived from this software without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: /*
37: * Copyright (c) 2001 Wasabi Systems, Inc.
38: * All rights reserved.
39: *
40: * Written by Frank van der Linden for Wasabi Systems, Inc.
41: *
42: * Redistribution and use in source and binary forms, with or without
43: * modification, are permitted provided that the following conditions
44: * are met:
45: * 1. Redistributions of source code must retain the above copyright
46: * notice, this list of conditions and the following disclaimer.
47: * 2. Redistributions in binary form must reproduce the above copyright
48: * notice, this list of conditions and the following disclaimer in the
49: * documentation and/or other materials provided with the distribution.
50: * 3. All advertising materials mentioning features or use of this software
51: * must display the following acknowledgement:
52: * This product includes software developed for the NetBSD Project by
53: * Wasabi Systems, Inc.
54: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
55: * or promote products derived from this software without specific prior
56: * written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
59: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
60: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
61: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
62: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
63: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
64: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
65: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
66: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68: * POSSIBILITY OF SUCH DAMAGE.
69: */
70:
71: /*
72: * pmap.h: see pmap.c for the history of this pmap module.
73: */
74:
75: #ifndef _AMD64_PMAP_H_
76: #define _AMD64_PMAP_H_
77:
78: #ifndef _LOCORE
79: #include <machine/cpufunc.h>
80: #include <machine/pte.h>
81: #include <machine/segments.h>
82: #include <uvm/uvm_object.h>
83: #endif
84:
85: /*
86: * The x86_64 pmap module closely resembles the i386 one. It uses
87: * the same recursive entry scheme, and the same alternate area
88: * trick for accessing non-current pmaps. See the i386 pmap.h
89: * for a description. The obvious difference is that 3 extra
90: * levels of page table need to be dealt with. The level 1 page
91: * table pages are at:
92: *
93: * l1: 0x00007f8000000000 - 0x00007fffffffffff (39 bits, needs PML4 entry)
94: *
95: * The alternate space is at:
96: *
97: * l1: 0xffffff8000000000 - 0xffffffffffffffff (39 bits, needs PML4 entry)
98: *
99: * The rest is kept as physical pages in 3 UVM objects, and is
100: * temporarily mapped for virtual access when needed.
101: *
102: * Note that address space is signed, so the layout for 48 bits is:
103: *
104: * +---------------------------------+ 0xffffffffffffffff
105: * | |
106: * | alt.L1 table (PTE pages) |
107: * | |
108: * +---------------------------------+ 0xffffff8000000000
109: * ~ ~
110: * | |
111: * | Kernel Space |
112: * | |
113: * | |
114: * +---------------------------------+ 0xffff800000000000 = 0x0000800000000000
115: * | |
116: * | L1 table (PTE pages) |
117: * | |
118: * +---------------------------------+ 0x00007f8000000000
119: * ~ ~
120: * | |
121: * | User Space |
122: * | |
123: * | |
124: * +---------------------------------+ 0x0000000000000000
125: *
126: * In other words, there is a 'VA hole' at 0x0000800000000000 -
127: * 0xffff800000000000 which will trap, just as on, for example,
128: * sparcv9.
129: *
130: * The unused space can be used if needed, but it adds a little more
131: * complexity to the calculations.
132: */
133:
134: /*
135: * The first generation of Hammer processors can use 48 bits of
136: * virtual memory, and 40 bits of physical memory. This will be
137: * more for later generations. These defines can be changed to
138: * variable names containing the # of bits, extracted from an
139: * extended cpuid instruction (variables are harder to use during
140: * bootstrap, though)
141: */
142: #define VIRT_BITS 48
143: #define PHYS_BITS 40
144:
145: /*
146: * Mask to get rid of the sign-extended part of addresses.
147: */
148: #define VA_SIGN_MASK 0xffff000000000000
149: #define VA_SIGN_NEG(va) ((va) | VA_SIGN_MASK)
150: /*
151: * XXXfvdl this one's not right.
152: */
153: #define VA_SIGN_POS(va) ((va) & ~VA_SIGN_MASK)
154:
155: #define L4_SLOT_PTE 255
156: #define L4_SLOT_KERN 256
157: #define L4_SLOT_KERNBASE 511
158: #define L4_SLOT_APTE 510
159: #define L4_SLOT_DIRECT 509
160: #define L4_SLOT_DIRECT_NC 508
161:
162: #define PDIR_SLOT_KERN L4_SLOT_KERN
163: #define PDIR_SLOT_PTE L4_SLOT_PTE
164: #define PDIR_SLOT_APTE L4_SLOT_APTE
165: #define PDIR_SLOT_DIRECT L4_SLOT_DIRECT
166: #define PDIR_SLOT_DIRECT_NC L4_SLOT_DIRECT_NC
167:
168: /*
169: * the following defines give the virtual addresses of various MMU
170: * data structures:
171: * PTE_BASE and APTE_BASE: the base VA of the linear PTE mappings
172: * PTD_BASE and APTD_BASE: the base VA of the recursive mapping of the PTD
173: * PDP_PDE and APDP_PDE: the VA of the PDE that points back to the PDP/APDP
174: *
175: */
176:
177: #define PTE_BASE ((pt_entry_t *) (L4_SLOT_PTE * NBPD_L4))
178: #define APTE_BASE ((pt_entry_t *) (VA_SIGN_NEG((L4_SLOT_APTE * NBPD_L4))))
179: #define PMAP_DIRECT_BASE (VA_SIGN_NEG((L4_SLOT_DIRECT * NBPD_L4)))
180: #define PMAP_DIRECT_END (VA_SIGN_NEG(((L4_SLOT_DIRECT + 1) * NBPD_L4)))
181: #define PMAP_DIRECT_BASE_NC (VA_SIGN_NEG((L4_SLOT_DIRECT_NC * NBPD_L4)))
182: #define PMAP_DIRECT_END_NC (VA_SIGN_NEG(((L4_SLOT_DIRECT_NC + 1) * NBPD_L4)))
183:
184: #define L1_BASE PTE_BASE
185: #define AL1_BASE APTE_BASE
186:
187: #define L2_BASE ((pd_entry_t *)((char *)L1_BASE + L4_SLOT_PTE * NBPD_L3))
188: #define L3_BASE ((pd_entry_t *)((char *)L2_BASE + L4_SLOT_PTE * NBPD_L2))
189: #define L4_BASE ((pd_entry_t *)((char *)L3_BASE + L4_SLOT_PTE * NBPD_L1))
190:
191: #define AL2_BASE ((pd_entry_t *)((char *)AL1_BASE + L4_SLOT_PTE * NBPD_L3))
192: #define AL3_BASE ((pd_entry_t *)((char *)AL2_BASE + L4_SLOT_PTE * NBPD_L2))
193: #define AL4_BASE ((pd_entry_t *)((char *)AL3_BASE + L4_SLOT_PTE * NBPD_L1))
194:
195: #define PDP_PDE (L4_BASE + PDIR_SLOT_PTE)
196: #define APDP_PDE (L4_BASE + PDIR_SLOT_APTE)
197:
198: #define PDP_BASE L4_BASE
199: #define APDP_BASE AL4_BASE
200:
201: #define NKL4_MAX_ENTRIES (unsigned long)1
202: #define NKL3_MAX_ENTRIES (unsigned long)(NKL4_MAX_ENTRIES * 512)
203: #define NKL2_MAX_ENTRIES (unsigned long)(NKL3_MAX_ENTRIES * 512)
204: #define NKL1_MAX_ENTRIES (unsigned long)(NKL2_MAX_ENTRIES * 512)
205:
206: #define NKL4_KIMG_ENTRIES 1
207: #define NKL3_KIMG_ENTRIES 1
208: #define NKL2_KIMG_ENTRIES 8
209:
210: #define NDML4_ENTRIES 1
211: #define NDML3_ENTRIES 1
212: #define NDML2_ENTRIES 4 /* 4GB */
213:
214: /*
215: * Since kva space is below the kernel in its entirety, we start off
216: * with zero entries on each level.
217: */
218: #define NKL4_START_ENTRIES 0
219: #define NKL3_START_ENTRIES 0
220: #define NKL2_START_ENTRIES 0
221: #define NKL1_START_ENTRIES 0 /* XXX */
222:
223: #define NTOPLEVEL_PDES (PAGE_SIZE / (sizeof (pd_entry_t)))
224:
225: #define KERNSPACE (NKL4_ENTRIES * NBPD_L4)
226:
227: #define NPDPG (PAGE_SIZE / sizeof (pd_entry_t))
228:
229: #define ptei(VA) (((VA_SIGN_POS(VA)) & L1_MASK) >> L1_SHIFT)
230:
231: /*
232: * pl*_pi: index in the ptp page for a pde mapping a VA.
233: * (pl*_i below is the index in the virtual array of all pdes per level)
234: */
235: #define pl1_pi(VA) (((VA_SIGN_POS(VA)) & L1_MASK) >> L1_SHIFT)
236: #define pl2_pi(VA) (((VA_SIGN_POS(VA)) & L2_MASK) >> L2_SHIFT)
237: #define pl3_pi(VA) (((VA_SIGN_POS(VA)) & L3_MASK) >> L3_SHIFT)
238: #define pl4_pi(VA) (((VA_SIGN_POS(VA)) & L4_MASK) >> L4_SHIFT)
239:
240: /*
241: * pl*_i: generate index into pde/pte arrays in virtual space
242: */
243: #define pl1_i(VA) (((VA_SIGN_POS(VA)) & L1_FRAME) >> L1_SHIFT)
244: #define pl2_i(VA) (((VA_SIGN_POS(VA)) & L2_FRAME) >> L2_SHIFT)
245: #define pl3_i(VA) (((VA_SIGN_POS(VA)) & L3_FRAME) >> L3_SHIFT)
246: #define pl4_i(VA) (((VA_SIGN_POS(VA)) & L4_FRAME) >> L4_SHIFT)
247: #define pl_i(va, lvl) \
248: (((VA_SIGN_POS(va)) & ptp_masks[(lvl)-1]) >> ptp_shifts[(lvl)-1])
249:
250: #define PTP_MASK_INITIALIZER { L1_FRAME, L2_FRAME, L3_FRAME, L4_FRAME }
251: #define PTP_SHIFT_INITIALIZER { L1_SHIFT, L2_SHIFT, L3_SHIFT, L4_SHIFT }
252: #define NKPTP_INITIALIZER { NKL1_START_ENTRIES, NKL2_START_ENTRIES, \
253: NKL3_START_ENTRIES, NKL4_START_ENTRIES }
254: #define NKPTPMAX_INITIALIZER { NKL1_MAX_ENTRIES, NKL2_MAX_ENTRIES, \
255: NKL3_MAX_ENTRIES, NKL4_MAX_ENTRIES }
256: #define NBPD_INITIALIZER { NBPD_L1, NBPD_L2, NBPD_L3, NBPD_L4 }
257: #define PDES_INITIALIZER { L2_BASE, L3_BASE, L4_BASE }
258: #define APDES_INITIALIZER { AL2_BASE, AL3_BASE, AL4_BASE }
259:
260: /*
261: * PTP macros:
262: * a PTP's index is the PD index of the PDE that points to it
263: * a PTP's offset is the byte-offset in the PTE space that this PTP is at
264: * a PTP's VA is the first VA mapped by that PTP
265: *
266: * note that PAGE_SIZE == number of bytes in a PTP (4096 bytes == 1024 entries)
267: * NBPD == number of bytes a PTP can map (4MB)
268: */
269:
270: #define ptp_va2o(va, lvl) (pl_i(va, (lvl)+1) * PAGE_SIZE)
271:
272: #define PTP_LEVELS 4
273:
274: /*
275: * PG_AVAIL usage: we make use of the ignored bits of the PTE
276: */
277:
278: #define PG_W PG_AVAIL1 /* "wired" mapping */
279: #define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */
280: /* PG_AVAIL3 not used */
281:
282: /*
283: * Number of PTE's per cache line. 8 byte pte, 64-byte cache line
284: * Used to avoid false sharing of cache lines.
285: */
286: #define NPTECL 8
287:
288:
289: #if defined(_KERNEL) && !defined(_LOCORE)
290: /*
291: * pmap data structures: see pmap.c for details of locking.
292: */
293:
294: struct pmap;
295: typedef struct pmap *pmap_t;
296:
297: /*
298: * we maintain a list of all non-kernel pmaps
299: */
300:
301: LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */
302:
303: /*
304: * the pmap structure
305: *
306: * note that the pm_obj contains the simple_lock, the reference count,
307: * page list, and number of PTPs within the pmap.
308: *
309: * pm_lock is the same as the spinlock for vm object 0. Changes to
310: * the other objects may only be made if that lock has been taken
311: * (the other object locks are only used when uvm_pagealloc is called)
312: */
313:
314: struct pmap {
315: struct uvm_object pm_obj[PTP_LEVELS-1]; /* objects for lvl >= 1) */
316: #define pm_lock pm_obj[0].vmobjlock
317: #define pm_obj_l1 pm_obj[0]
318: #define pm_obj_l2 pm_obj[1]
319: #define pm_obj_l3 pm_obj[2]
320: LIST_ENTRY(pmap) pm_list; /* list (lck by pm_list lock) */
321: pd_entry_t *pm_pdir; /* VA of PD (lck by object lock) */
322: paddr_t pm_pdirpa; /* PA of PD (read-only after create) */
323: struct vm_page *pm_ptphint[PTP_LEVELS-1];
324: /* pointer to a PTP in our pmap */
325: struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */
326:
327: int pm_flags; /* see below */
328:
329: union descriptor *pm_ldt; /* user-set LDT */
330: int pm_ldt_len; /* number of LDT entries */
331: int pm_ldt_sel; /* LDT selector */
332: u_int32_t pm_cpus; /* mask of CPUs using pmap */
333: };
334:
335: /* pm_flags */
336: #define PMF_USER_LDT 0x01 /* pmap has user-set LDT */
337:
338: /*
339: * We keep mod/ref flags in struct vm_page->pg_flags.
340: */
341: #define PG_PMAP_MOD PG_PMAP0
342: #define PG_PMAP_REF PG_PMAP1
343:
344: /*
345: * for each managed physical page we maintain a list of <PMAP,VA>'s
346: * which it is mapped at.
347: */
348: struct pv_entry { /* locked by its list's pvh_lock */
349: struct pv_entry *pv_next; /* next entry */
350: struct pmap *pv_pmap; /* the pmap */
351: vaddr_t pv_va; /* the virtual address */
352: struct vm_page *pv_ptp; /* the vm_page of the PTP */
353: };
354:
355: /*
356: * pmap_remove_record: a record of VAs that have been unmapped, used to
357: * flush TLB. if we have more than PMAP_RR_MAX then we stop recording.
358: */
359:
360: #define PMAP_RR_MAX 16 /* max of 16 pages (64K) */
361:
362: struct pmap_remove_record {
363: int prr_npages;
364: vaddr_t prr_vas[PMAP_RR_MAX];
365: };
366:
367: /*
368: * global kernel variables
369: */
370:
371: /* PTDpaddr: is the physical address of the kernel's PDP */
372: extern u_long PTDpaddr;
373:
374: extern struct pmap kernel_pmap_store; /* kernel pmap */
375: extern int pmap_pg_g; /* do we support PG_G? */
376:
377: extern paddr_t ptp_masks[];
378: extern int ptp_shifts[];
379: extern long nkptp[], nbpd[], nkptpmax[];
380: extern pd_entry_t *pdes[];
381:
382: /*
383: * macros
384: */
385:
386: #define pmap_kernel() (&kernel_pmap_store)
387: #define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
388: #define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count)
389: #define pmap_update(pmap) /* nothing (yet) */
390:
391: #define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M)
392: #define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U)
393: #define pmap_copy(DP,SP,D,L,S)
394: #define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M)
395: #define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U)
396: #define pmap_move(DP,SP,D,L,S)
397: #define pmap_phys_address(ppn) ptoa(ppn)
398: #define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */
399:
400: #define pmap_proc_iflush(p,va,len) /* nothing */
401: #define pmap_unuse_final(p) /* nothing */
402:
403:
404: /*
405: * prototypes
406: */
407:
408: void pmap_bootstrap(vaddr_t, paddr_t);
409: boolean_t pmap_clear_attrs(struct vm_page *, unsigned long);
410: static void pmap_page_protect(struct vm_page *, vm_prot_t);
411: void pmap_page_remove (struct vm_page *);
412: static void pmap_protect(struct pmap *, vaddr_t,
413: vaddr_t, vm_prot_t);
414: void pmap_remove(struct pmap *, vaddr_t, vaddr_t);
415: boolean_t pmap_test_attrs(struct vm_page *, unsigned);
416: static void pmap_update_pg(vaddr_t);
417: static void pmap_update_2pg(vaddr_t,vaddr_t);
418: void pmap_write_protect(struct pmap *, vaddr_t,
419: vaddr_t, vm_prot_t);
420:
421: vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */
422:
423: void pmap_tlb_shootpage(struct pmap *, vaddr_t);
424: void pmap_tlb_shootrange(struct pmap *, vaddr_t, vaddr_t);
425: void pmap_tlb_shoottlb(void);
426: #ifdef MULTIPROCESSOR
427: void pmap_tlb_shootwait(void);
428: #else
429: #define pmap_tlb_shootwait()
430: #endif
431:
432: void pmap_prealloc_lowmem_ptps(void);
433:
434: void pagezero(vaddr_t);
435:
436: #define PMAP_STEAL_MEMORY /* enable pmap_steal_memory() */
437: #define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */
438:
439: /*
440: * Do idle page zero'ing uncached to avoid polluting the cache.
441: */
442: boolean_t pmap_pageidlezero(struct vm_page *);
443: #define PMAP_PAGEIDLEZERO(pg) pmap_pageidlezero((pg))
444:
445: /*
446: * inline functions
447: */
448:
449: static __inline void
450: pmap_remove_all(struct pmap *pmap)
451: {
452: /* Nothing. */
453: }
454:
455: /*
456: * pmap_update_pg: flush one page from the TLB (or flush the whole thing
457: * if hardware doesn't support one-page flushing)
458: */
459:
460: __inline static void
461: pmap_update_pg(va)
462: vaddr_t va;
463: {
464: invlpg(va);
465: }
466:
467: /*
468: * pmap_update_2pg: flush two pages from the TLB
469: */
470:
471: __inline static void
472: pmap_update_2pg(va, vb)
473: vaddr_t va, vb;
474: {
475: invlpg(va);
476: invlpg(vb);
477: }
478:
479: /*
480: * pmap_page_protect: change the protection of all recorded mappings
481: * of a managed page
482: *
483: * => this function is a frontend for pmap_page_remove/pmap_clear_attrs
484: * => we only have to worry about making the page more protected.
485: * unprotecting a page is done on-demand at fault time.
486: */
487:
488: __inline static void
489: pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
490: {
491: if ((prot & VM_PROT_WRITE) == 0) {
492: if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
493: (void) pmap_clear_attrs(pg, PG_RW);
494: } else {
495: pmap_page_remove(pg);
496: }
497: }
498: }
499:
500: /*
501: * pmap_protect: change the protection of pages in a pmap
502: *
503: * => this function is a frontend for pmap_remove/pmap_write_protect
504: * => we only have to worry about making the page more protected.
505: * unprotecting a page is done on-demand at fault time.
506: */
507:
508: __inline static void
509: pmap_protect(pmap, sva, eva, prot)
510: struct pmap *pmap;
511: vaddr_t sva, eva;
512: vm_prot_t prot;
513: {
514: if ((prot & VM_PROT_WRITE) == 0) {
515: if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
516: pmap_write_protect(pmap, sva, eva, prot);
517: } else {
518: pmap_remove(pmap, sva, eva);
519: }
520: }
521: }
522:
523: /*
524: * various address inlines
525: *
526: * vtopte: return a pointer to the PTE mapping a VA, works only for
527: * user and PT addresses
528: *
529: * kvtopte: return a pointer to the PTE mapping a kernel VA
530: */
531:
532: static __inline pt_entry_t *
533: vtopte(vaddr_t va)
534: {
535: return (PTE_BASE + pl1_i(va));
536: }
537:
538: static __inline pt_entry_t *
539: kvtopte(vaddr_t va)
540: {
541: #ifdef LARGEPAGES
542: {
543: pd_entry_t *pde;
544:
545: pde = L1_BASE + pl2_i(va);
546: if (*pde & PG_PS)
547: return ((pt_entry_t *)pde);
548: }
549: #endif
550:
551: return (PTE_BASE + pl1_i(va));
552: }
553:
554: #define pmap_pte_set(p, n) x86_atomic_testset_u64(p, n)
555: #define pmap_pte_clearbits(p, b) x86_atomic_clearbits_u64(p, b)
556: #define pmap_pte_setbits(p, b) x86_atomic_setbits_u64(p, b)
557: #define pmap_cpu_has_pg_n() (1)
558: #define pmap_cpu_has_invlpg (1)
559:
560: vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t);
561:
562: #if 0 /* XXXfvdl was USER_LDT, need to check if that can be supported */
563: void pmap_ldt_cleanup(struct proc *);
564: #define PMAP_FORK
565: #endif /* USER_LDT */
566:
567: #define PMAP_DIRECT_MAP(pa) ((vaddr_t)PMAP_DIRECT_BASE + pa)
568: #define PMAP_DIRECT_UNMAP(va) ((paddr_t)va - PMAP_DIRECT_BASE)
569: #define pmap_map_direct(pg) PMAP_DIRECT_MAP(VM_PAGE_TO_PHYS(pg))
570: #define pmap_unmap_direct(va) PHYS_TO_VM_PAGE(PMAP_DIRECT_UNMAP(va))
571:
572: #define PMAP_DIRECT_NC_MAP(pa) ((vaddr_t)PMAP_DIRECT_BASE_NC + pa)
573: #define PMAP_DIRECT_NC_UNMAP(va) ((paddr_t)va - PMAP_DIRECT_BASE_NC)
574: #define pmap_map_nc_direct(pg) PMAP_DIRECT_NC_MAP(VM_PAGE_TO_PHYS(pg))
575: #define pmap_unmap_nc_direct(va) PHYS_TO_VM_PAGE(PMAP_DIRECT_NC_UNMAP(va))
576:
577: #define __HAVE_PMAP_DIRECT
578:
579: #endif /* _KERNEL && !_LOCORE */
580: #endif /* _AMD64_PMAP_H_ */
CVSweb