Home | History | Annotate | Line # | Download | only in include
pmap_private.h revision 1.2
      1 /*	$NetBSD: pmap_private.h,v 1.2 2022/08/20 23:49:31 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 Charles D. Cranor and Washington University.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 /*
     29  * Copyright (c) 2001 Wasabi Systems, Inc.
     30  * All rights reserved.
     31  *
     32  * Written by Frank van der Linden for Wasabi Systems, Inc.
     33  *
     34  * Redistribution and use in source and binary forms, with or without
     35  * modification, are permitted provided that the following conditions
     36  * are met:
     37  * 1. Redistributions of source code must retain the above copyright
     38  *    notice, this list of conditions and the following disclaimer.
     39  * 2. Redistributions in binary form must reproduce the above copyright
     40  *    notice, this list of conditions and the following disclaimer in the
     41  *    documentation and/or other materials provided with the distribution.
     42  * 3. All advertising materials mentioning features or use of this software
     43  *    must display the following acknowledgement:
     44  *      This product includes software developed for the NetBSD Project by
     45  *      Wasabi Systems, Inc.
     46  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     47  *    or promote products derived from this software without specific prior
     48  *    written permission.
     49  *
     50  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     52  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     53  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     54  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     55  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     56  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     57  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     58  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     59  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     60  * POSSIBILITY OF SUCH DAMAGE.
     61  */
     62 
     63 #ifndef	_X86_PMAP_PRIVATE_H_
     64 #define	_X86_PMAP_PRIVATE_H_
     65 
     66 #ifndef	_MACHINE_PMAP_PRIVATE_H_X86
     67 #error Include machine/pmap_private.h, not x86/pmap_private.h.
     68 #endif
     69 
     70 #ifdef _KERNEL_OPT
     71 #include "opt_svs.h"
     72 #endif
     73 
     74 #include <sys/param.h>
     75 #include <sys/types.h>
     76 
     77 #include <sys/kcpuset.h>
     78 #include <sys/mutex.h>
     79 #include <sys/pool.h>
     80 #include <sys/queue.h>
     81 #include <sys/rwlock.h>
     82 
     83 #include <machine/pte.h>
     84 #include <machine/vmparam.h>
     85 
     86 #include <uvm/uvm_object.h>
     87 #include <uvm/uvm_pmap.h>
     88 
     89 struct pmap;
     90 
     91 #define SLAREA_USER	0
     92 #define SLAREA_PTE	1
     93 #define SLAREA_MAIN	2
     94 #define SLAREA_PCPU	3
     95 #define SLAREA_DMAP	4
     96 #define SLAREA_HYPV	5
     97 #define SLAREA_ASAN	6
     98 #define SLAREA_MSAN	7
     99 #define SLAREA_KERN	8
    100 #define SLSPACE_NAREAS	9
    101 
    102 struct slotspace {
    103 	struct {
    104 		size_t sslot; /* start slot */
    105 		size_t nslot; /* # of slots */
    106 		bool active;  /* area is active */
    107 	} area[SLSPACE_NAREAS];
    108 };
    109 
    110 extern struct slotspace slotspace;
    111 
    112 #include <x86/gdt.h>
    113 
    114 struct pcpu_entry {
    115 	uint8_t gdt[MAXGDTSIZ];
    116 	uint8_t ldt[MAX_USERLDT_SIZE];
    117 	uint8_t idt[PAGE_SIZE];
    118 	uint8_t tss[PAGE_SIZE];
    119 	uint8_t ist0[PAGE_SIZE];
    120 	uint8_t ist1[PAGE_SIZE];
    121 	uint8_t ist2[PAGE_SIZE];
    122 	uint8_t ist3[PAGE_SIZE];
    123 	uint8_t rsp0[2 * PAGE_SIZE];
    124 } __packed;
    125 
    126 struct pcpu_area {
    127 #ifdef SVS
    128 	uint8_t utls[PAGE_SIZE];
    129 #endif
    130 	uint8_t ldt[PAGE_SIZE];
    131 	struct pcpu_entry ent[MAXCPUS];
    132 } __packed;
    133 
    134 extern struct pcpu_area *pcpuarea;
    135 
    136 #define PMAP_PCID_KERN	0
    137 #define PMAP_PCID_USER	1
    138 
    139 /*
    140  * pmap data structures: see pmap.c for details of locking.
    141  */
    142 
    143 /*
    144  * we maintain a list of all non-kernel pmaps
    145  */
    146 
    147 LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */
    148 
    149 /*
    150  * linked list of all non-kernel pmaps
    151  */
    152 extern struct pmap_head pmaps;
    153 extern kmutex_t pmaps_lock;    /* protects pmaps */
    154 
    155 /*
    156  * pool_cache(9) that pmaps are allocated from
    157  */
    158 extern struct pool_cache pmap_cache;
    159 
    160 /*
    161  * the pmap structure
    162  *
    163  * note that the pm_obj contains the lock pointer, the reference count,
    164  * page list, and number of PTPs within the pmap.
    165  *
    166  * pm_lock is the same as the lock for vm object 0.  Changes to
    167  * the other objects may only be made if that lock has been taken
    168  * (the other object locks are only used when uvm_pagealloc is called)
    169  */
    170 
    171 struct pv_page;
    172 
    173 struct pmap {
    174 	struct uvm_object pm_obj[PTP_LEVELS-1];/* objects for lvl >= 1) */
    175 	LIST_ENTRY(pmap) pm_list;	/* list of all pmaps */
    176 	pd_entry_t *pm_pdir;		/* VA of PD */
    177 	paddr_t pm_pdirpa[PDP_SIZE];	/* PA of PDs (read-only after create) */
    178 	struct vm_page *pm_ptphint[PTP_LEVELS-1];
    179 					/* pointer to a PTP in our pmap */
    180 	struct pmap_statistics pm_stats;  /* pmap stats */
    181 	struct pv_entry *pm_pve;	/* spare pv_entry */
    182 	LIST_HEAD(, pv_page) pm_pvp_part;
    183 	LIST_HEAD(, pv_page) pm_pvp_empty;
    184 	LIST_HEAD(, pv_page) pm_pvp_full;
    185 
    186 #if !defined(__x86_64__)
    187 	vaddr_t pm_hiexec;		/* highest executable mapping */
    188 #endif /* !defined(__x86_64__) */
    189 
    190 	union descriptor *pm_ldt;	/* user-set LDT */
    191 	size_t pm_ldt_len;		/* XXX unused, remove */
    192 	int pm_ldt_sel;			/* LDT selector */
    193 
    194 	kcpuset_t *pm_cpus;		/* mask of CPUs using pmap */
    195 	kcpuset_t *pm_kernel_cpus;	/* mask of CPUs using kernel part
    196 					 of pmap */
    197 	kcpuset_t *pm_xen_ptp_cpus;	/* mask of CPUs which have this pmap's
    198 					 ptp mapped */
    199 	uint64_t pm_ncsw;		/* for assertions */
    200 	LIST_HEAD(,vm_page) pm_gc_ptp;	/* PTPs queued for free */
    201 
    202 	/* Used by NVMM and Xen */
    203 	int (*pm_enter)(struct pmap *, vaddr_t, paddr_t, vm_prot_t, u_int);
    204 	bool (*pm_extract)(struct pmap *, vaddr_t, paddr_t *);
    205 	void (*pm_remove)(struct pmap *, vaddr_t, vaddr_t);
    206 	int (*pm_sync_pv)(struct vm_page *, vaddr_t, paddr_t, int, uint8_t *,
    207 	    pt_entry_t *);
    208 	void (*pm_pp_remove_ent)(struct pmap *, struct vm_page *, pt_entry_t,
    209 	    vaddr_t);
    210 	void (*pm_write_protect)(struct pmap *, vaddr_t, vaddr_t, vm_prot_t);
    211 	void (*pm_unwire)(struct pmap *, vaddr_t);
    212 
    213 	void (*pm_tlb_flush)(struct pmap *);
    214 	void *pm_data;
    215 
    216 	kmutex_t pm_lock		/* locks for pm_objs */
    217 	    __aligned(64);		/* give lock own cache line */
    218 	krwlock_t pm_dummy_lock;	/* ugly hack for abusing uvm_object */
    219 };
    220 
    221 /* macro to access pm_pdirpa slots */
    222 #ifdef PAE
    223 #define pmap_pdirpa(pmap, index) \
    224 	((pmap)->pm_pdirpa[l2tol3(index)] + l2tol2(index) * sizeof(pd_entry_t))
    225 #else
    226 #define pmap_pdirpa(pmap, index) \
    227 	((pmap)->pm_pdirpa[0] + (index) * sizeof(pd_entry_t))
    228 #endif
    229 
    230 /*
    231  * global kernel variables
    232  */
    233 
    234 /*
    235  * PDPpaddr is the physical address of the kernel's PDP.
    236  * - i386 non-PAE and amd64: PDPpaddr corresponds directly to the %cr3
    237  * value associated to the kernel process, proc0.
    238  * - i386 PAE: it still represents the PA of the kernel's PDP (L2). Due to
    239  * the L3 PD, it cannot be considered as the equivalent of a %cr3 any more.
    240  * - Xen: it corresponds to the PFN of the kernel's PDP.
    241  */
    242 extern u_long PDPpaddr;
    243 
    244 extern pd_entry_t pmap_pg_g;			/* do we support PTE_G? */
    245 extern pd_entry_t pmap_pg_nx;			/* do we support PTE_NX? */
    246 extern int pmap_largepages;
    247 extern long nkptp[PTP_LEVELS];
    248 
    249 #define pmap_valid_entry(E) 		((E) & PTE_P) /* is PDE or PTE valid? */
    250 
    251 void		pmap_map_ptes(struct pmap *, struct pmap **, pd_entry_t **,
    252 		    pd_entry_t * const **);
    253 void		pmap_unmap_ptes(struct pmap *, struct pmap *);
    254 
    255 bool		pmap_pdes_valid(vaddr_t, pd_entry_t * const *, pd_entry_t *,
    256 		    int *lastlvl);
    257 
    258 bool		pmap_is_curpmap(struct pmap *);
    259 
    260 void		pmap_ept_transform(struct pmap *);
    261 
    262 #ifndef __HAVE_DIRECT_MAP
    263 void		pmap_vpage_cpu_init(struct cpu_info *);
    264 #endif
    265 vaddr_t		slotspace_rand(int, size_t, size_t, size_t, vaddr_t);
    266 
    267 vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */
    268 
    269 typedef enum tlbwhy {
    270 	TLBSHOOT_REMOVE_ALL,
    271 	TLBSHOOT_KENTER,
    272 	TLBSHOOT_KREMOVE,
    273 	TLBSHOOT_FREE_PTP,
    274 	TLBSHOOT_REMOVE_PTE,
    275 	TLBSHOOT_SYNC_PV,
    276 	TLBSHOOT_WRITE_PROTECT,
    277 	TLBSHOOT_ENTER,
    278 	TLBSHOOT_NVMM,
    279 	TLBSHOOT_BUS_DMA,
    280 	TLBSHOOT_BUS_SPACE,
    281 	TLBSHOOT__MAX,
    282 } tlbwhy_t;
    283 
    284 void		pmap_tlb_init(void);
    285 void		pmap_tlb_cpu_init(struct cpu_info *);
    286 void		pmap_tlb_shootdown(pmap_t, vaddr_t, pt_entry_t, tlbwhy_t);
    287 void		pmap_tlb_shootnow(void);
    288 void		pmap_tlb_intr(void);
    289 
    290 /*
    291  * inline functions
    292  */
    293 
    294 /*
    295  * pmap_update_pg: flush one page from the TLB (or flush the whole thing
    296  *	if hardware doesn't support one-page flushing)
    297  */
    298 
    299 __inline static void __unused
    300 pmap_update_pg(vaddr_t va)
    301 {
    302 	invlpg(va);
    303 }
    304 
    305 /*
    306  * various address inlines
    307  *
    308  *  vtopte: return a pointer to the PTE mapping a VA, works only for
    309  *  user and PT addresses
    310  *
    311  *  kvtopte: return a pointer to the PTE mapping a kernel VA
    312  */
    313 
    314 #include <lib/libkern/libkern.h>
    315 
    316 static __inline pt_entry_t * __unused
    317 vtopte(vaddr_t va)
    318 {
    319 
    320 	KASSERT(va < VM_MIN_KERNEL_ADDRESS);
    321 
    322 	return (PTE_BASE + pl1_i(va));
    323 }
    324 
    325 static __inline pt_entry_t * __unused
    326 kvtopte(vaddr_t va)
    327 {
    328 	pd_entry_t *pde;
    329 
    330 	KASSERT(va >= VM_MIN_KERNEL_ADDRESS);
    331 
    332 	pde = L2_BASE + pl2_i(va);
    333 	if (*pde & PTE_PS)
    334 		return ((pt_entry_t *)pde);
    335 
    336 	return (PTE_BASE + pl1_i(va));
    337 }
    338 
    339 #ifdef XENPV
    340 #include <sys/bitops.h>
    341 
    342 #define XPTE_MASK	L1_FRAME
    343 /* Selects the index of a PTE in (A)PTE_BASE */
    344 #define XPTE_SHIFT	(L1_SHIFT - ilog2(sizeof(pt_entry_t)))
    345 
    346 /* PTE access inline functions */
    347 
    348 /*
    349  * Get the machine address of the pointed pte
    350  * We use hardware MMU to get value so works only for levels 1-3
    351  */
    352 
    353 static __inline paddr_t
    354 xpmap_ptetomach(pt_entry_t *pte)
    355 {
    356 	pt_entry_t *up_pte;
    357 	vaddr_t va = (vaddr_t) pte;
    358 
    359 	va = ((va & XPTE_MASK) >> XPTE_SHIFT) | (vaddr_t) PTE_BASE;
    360 	up_pte = (pt_entry_t *) va;
    361 
    362 	return (paddr_t) (((*up_pte) & PTE_FRAME) + (((vaddr_t) pte) & (~PTE_FRAME & ~VA_SIGN_MASK)));
    363 }
    364 
    365 /* Xen helpers to change bits of a pte */
    366 #define XPMAP_UPDATE_DIRECT	1	/* Update direct map entry flags too */
    367 
    368 paddr_t	vtomach(vaddr_t);
    369 #define vtomfn(va) (vtomach(va) >> PAGE_SHIFT)
    370 #endif	/* XENPV */
    371 
    372 #ifdef __HAVE_PCPU_AREA
    373 extern struct pcpu_area *pcpuarea;
    374 #define PDIR_SLOT_PCPU		510
    375 #define PMAP_PCPU_BASE		(VA_SIGN_NEG((PDIR_SLOT_PCPU * NBPD_L4)))
    376 #endif
    377 
    378 void	svs_quad_copy(void *, void *, long);
    379 
    380 #endif	/* _X86_PMAP_PRIVATE_H_ */
    381