xref: /freebsd/sys/amd64/vmm/intel/ept.c (revision bda273f21e52253e1318cb2d9bd9028947f7c5d1)
1366f6083SPeter Grehan /*-
2366f6083SPeter Grehan  * Copyright (c) 2011 NetApp, Inc.
3366f6083SPeter Grehan  * All rights reserved.
4366f6083SPeter Grehan  *
5366f6083SPeter Grehan  * Redistribution and use in source and binary forms, with or without
6366f6083SPeter Grehan  * modification, are permitted provided that the following conditions
7366f6083SPeter Grehan  * are met:
8366f6083SPeter Grehan  * 1. Redistributions of source code must retain the above copyright
9366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer.
10366f6083SPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
11366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
12366f6083SPeter Grehan  *    documentation and/or other materials provided with the distribution.
13366f6083SPeter Grehan  *
14366f6083SPeter Grehan  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15366f6083SPeter Grehan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16366f6083SPeter Grehan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17366f6083SPeter Grehan  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18366f6083SPeter Grehan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19366f6083SPeter Grehan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20366f6083SPeter Grehan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21366f6083SPeter Grehan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22366f6083SPeter Grehan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23366f6083SPeter Grehan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24366f6083SPeter Grehan  * SUCH DAMAGE.
25366f6083SPeter Grehan  *
26366f6083SPeter Grehan  * $FreeBSD$
27366f6083SPeter Grehan  */
28366f6083SPeter Grehan 
29366f6083SPeter Grehan #include <sys/cdefs.h>
30366f6083SPeter Grehan __FBSDID("$FreeBSD$");
31366f6083SPeter Grehan 
32366f6083SPeter Grehan #include <sys/types.h>
33366f6083SPeter Grehan #include <sys/errno.h>
34366f6083SPeter Grehan #include <sys/systm.h>
35366f6083SPeter Grehan #include <sys/malloc.h>
36366f6083SPeter Grehan #include <sys/smp.h>
37366f6083SPeter Grehan 
38366f6083SPeter Grehan #include <vm/vm.h>
39366f6083SPeter Grehan #include <vm/pmap.h>
40366f6083SPeter Grehan 
41366f6083SPeter Grehan #include <machine/param.h>
42366f6083SPeter Grehan #include <machine/cpufunc.h>
43366f6083SPeter Grehan #include <machine/pmap.h>
44366f6083SPeter Grehan #include <machine/vmparam.h>
45366f6083SPeter Grehan 
46366f6083SPeter Grehan #include <machine/vmm.h>
47366f6083SPeter Grehan #include "vmx_cpufunc.h"
48366f6083SPeter Grehan #include "vmx_msr.h"
49366f6083SPeter Grehan #include "vmx.h"
50366f6083SPeter Grehan #include "ept.h"
51366f6083SPeter Grehan 
52366f6083SPeter Grehan #define	EPT_PWL4(cap)			((cap) & (1UL << 6))
53366f6083SPeter Grehan #define	EPT_MEMORY_TYPE_WB(cap)		((cap) & (1UL << 14))
54366f6083SPeter Grehan #define	EPT_PDE_SUPERPAGE(cap)		((cap) & (1UL << 16))	/* 2MB pages */
55366f6083SPeter Grehan #define	EPT_PDPTE_SUPERPAGE(cap)	((cap) & (1UL << 17))	/* 1GB pages */
56366f6083SPeter Grehan #define	INVVPID_SUPPORTED(cap)		((cap) & (1UL << 32))
57366f6083SPeter Grehan #define	INVEPT_SUPPORTED(cap)		((cap) & (1UL << 20))
58366f6083SPeter Grehan 
59366f6083SPeter Grehan #define	INVVPID_ALL_TYPES_MASK		0xF0000000000UL
60366f6083SPeter Grehan #define	INVVPID_ALL_TYPES_SUPPORTED(cap)	\
61366f6083SPeter Grehan 	(((cap) & INVVPID_ALL_TYPES_MASK) == INVVPID_ALL_TYPES_MASK)
62366f6083SPeter Grehan 
63366f6083SPeter Grehan #define	INVEPT_ALL_TYPES_MASK		0x6000000UL
64366f6083SPeter Grehan #define	INVEPT_ALL_TYPES_SUPPORTED(cap)		\
65366f6083SPeter Grehan 	(((cap) & INVEPT_ALL_TYPES_MASK) == INVEPT_ALL_TYPES_MASK)
66366f6083SPeter Grehan 
67366f6083SPeter Grehan #define	EPT_PG_RD			(1 << 0)
68366f6083SPeter Grehan #define	EPT_PG_WR			(1 << 1)
69366f6083SPeter Grehan #define	EPT_PG_EX			(1 << 2)
70366f6083SPeter Grehan #define	EPT_PG_MEMORY_TYPE(x)		((x) << 3)
71366f6083SPeter Grehan #define	EPT_PG_IGNORE_PAT		(1 << 6)
72366f6083SPeter Grehan #define	EPT_PG_SUPERPAGE		(1 << 7)
73366f6083SPeter Grehan 
74366f6083SPeter Grehan #define	EPT_ADDR_MASK			((uint64_t)-1 << 12)
75366f6083SPeter Grehan 
76366f6083SPeter Grehan MALLOC_DECLARE(M_VMX);
77366f6083SPeter Grehan 
78366f6083SPeter Grehan static uint64_t page_sizes_mask;
79366f6083SPeter Grehan 
80366f6083SPeter Grehan int
81366f6083SPeter Grehan ept_init(void)
82366f6083SPeter Grehan {
83366f6083SPeter Grehan 	int page_shift;
84366f6083SPeter Grehan 	uint64_t cap;
85366f6083SPeter Grehan 
86366f6083SPeter Grehan 	cap = rdmsr(MSR_VMX_EPT_VPID_CAP);
87366f6083SPeter Grehan 
88366f6083SPeter Grehan 	/*
89366f6083SPeter Grehan 	 * Verify that:
90366f6083SPeter Grehan 	 * - page walk length is 4 steps
91366f6083SPeter Grehan 	 * - extended page tables can be laid out in write-back memory
92366f6083SPeter Grehan 	 * - invvpid instruction with all possible types is supported
93366f6083SPeter Grehan 	 * - invept instruction with all possible types is supported
94366f6083SPeter Grehan 	 */
95366f6083SPeter Grehan 	if (!EPT_PWL4(cap) ||
96366f6083SPeter Grehan 	    !EPT_MEMORY_TYPE_WB(cap) ||
97366f6083SPeter Grehan 	    !INVVPID_SUPPORTED(cap) ||
98366f6083SPeter Grehan 	    !INVVPID_ALL_TYPES_SUPPORTED(cap) ||
99366f6083SPeter Grehan 	    !INVEPT_SUPPORTED(cap) ||
100366f6083SPeter Grehan 	    !INVEPT_ALL_TYPES_SUPPORTED(cap))
101366f6083SPeter Grehan 		return (EINVAL);
102366f6083SPeter Grehan 
103366f6083SPeter Grehan 	/* Set bits in 'page_sizes_mask' for each valid page size */
104366f6083SPeter Grehan 	page_shift = PAGE_SHIFT;
105366f6083SPeter Grehan 	page_sizes_mask = 1UL << page_shift;		/* 4KB page */
106366f6083SPeter Grehan 
107366f6083SPeter Grehan 	page_shift += 9;
108366f6083SPeter Grehan 	if (EPT_PDE_SUPERPAGE(cap))
109366f6083SPeter Grehan 		page_sizes_mask |= 1UL << page_shift;	/* 2MB superpage */
110366f6083SPeter Grehan 
111366f6083SPeter Grehan 	page_shift += 9;
112366f6083SPeter Grehan 	if (EPT_PDPTE_SUPERPAGE(cap))
113366f6083SPeter Grehan 		page_sizes_mask |= 1UL << page_shift;	/* 1GB superpage */
114366f6083SPeter Grehan 
115366f6083SPeter Grehan 	return (0);
116366f6083SPeter Grehan }
117366f6083SPeter Grehan 
118*bda273f2SNeel Natu #if 0
119*bda273f2SNeel Natu static void
120*bda273f2SNeel Natu ept_dump(uint64_t *ptp, int nlevels)
121*bda273f2SNeel Natu {
122*bda273f2SNeel Natu 	int i, t, tabs;
123*bda273f2SNeel Natu 	uint64_t *ptpnext, ptpval;
124*bda273f2SNeel Natu 
125*bda273f2SNeel Natu 	if (--nlevels < 0)
126*bda273f2SNeel Natu 		return;
127*bda273f2SNeel Natu 
128*bda273f2SNeel Natu 	tabs = 3 - nlevels;
129*bda273f2SNeel Natu 	for (t = 0; t < tabs; t++)
130*bda273f2SNeel Natu 		printf("\t");
131*bda273f2SNeel Natu 	printf("PTP = %p\n", ptp);
132*bda273f2SNeel Natu 
133*bda273f2SNeel Natu 	for (i = 0; i < 512; i++) {
134*bda273f2SNeel Natu 		ptpval = ptp[i];
135*bda273f2SNeel Natu 
136*bda273f2SNeel Natu 		if (ptpval == 0)
137*bda273f2SNeel Natu 			continue;
138*bda273f2SNeel Natu 
139*bda273f2SNeel Natu 		for (t = 0; t < tabs; t++)
140*bda273f2SNeel Natu 			printf("\t");
141*bda273f2SNeel Natu 		printf("%3d 0x%016lx\n", i, ptpval);
142*bda273f2SNeel Natu 
143*bda273f2SNeel Natu 		if (nlevels != 0 && (ptpval & EPT_PG_SUPERPAGE) == 0) {
144*bda273f2SNeel Natu 			ptpnext = (uint64_t *)
145*bda273f2SNeel Natu 				  PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK);
146*bda273f2SNeel Natu 			ept_dump(ptpnext, nlevels);
147*bda273f2SNeel Natu 		}
148*bda273f2SNeel Natu 	}
149*bda273f2SNeel Natu }
150*bda273f2SNeel Natu #endif
151*bda273f2SNeel Natu 
152366f6083SPeter Grehan static size_t
153366f6083SPeter Grehan ept_create_mapping(uint64_t *ptp, vm_paddr_t gpa, vm_paddr_t hpa, size_t length,
154366f6083SPeter Grehan 		   vm_memattr_t attr, vm_prot_t prot, boolean_t spok)
155366f6083SPeter Grehan {
156366f6083SPeter Grehan 	int spshift, ptpshift, ptpindex, nlevels;
157366f6083SPeter Grehan 
158366f6083SPeter Grehan 	/*
159366f6083SPeter Grehan 	 * Compute the size of the mapping that we can accomodate.
160366f6083SPeter Grehan 	 *
161366f6083SPeter Grehan 	 * This is based on three factors:
162366f6083SPeter Grehan 	 * - super page sizes supported by the processor
163366f6083SPeter Grehan 	 * - alignment of the region starting at 'gpa' and 'hpa'
164366f6083SPeter Grehan 	 * - length of the region 'len'
165366f6083SPeter Grehan 	 */
166366f6083SPeter Grehan 	spshift = PAGE_SHIFT;
167366f6083SPeter Grehan 	if (spok)
168366f6083SPeter Grehan 		spshift += (EPT_PWLEVELS - 1) * 9;
169366f6083SPeter Grehan 	while (spshift >= PAGE_SHIFT) {
170366f6083SPeter Grehan 		uint64_t spsize = 1UL << spshift;
171366f6083SPeter Grehan 		if ((page_sizes_mask & spsize) != 0 &&
172366f6083SPeter Grehan 		    (gpa & (spsize - 1)) == 0 &&
173366f6083SPeter Grehan 		    (hpa & (spsize - 1)) == 0 &&
174366f6083SPeter Grehan 		    length >= spsize) {
175366f6083SPeter Grehan 			break;
176366f6083SPeter Grehan 		}
177366f6083SPeter Grehan 		spshift -= 9;
178366f6083SPeter Grehan 	}
179366f6083SPeter Grehan 
180366f6083SPeter Grehan 	if (spshift < PAGE_SHIFT) {
181366f6083SPeter Grehan 		panic("Invalid spshift for gpa 0x%016lx, hpa 0x%016lx, "
182366f6083SPeter Grehan 		      "length 0x%016lx, page_sizes_mask 0x%016lx",
183366f6083SPeter Grehan 		      gpa, hpa, length, page_sizes_mask);
184366f6083SPeter Grehan 	}
185366f6083SPeter Grehan 
186366f6083SPeter Grehan 	nlevels = EPT_PWLEVELS;
187366f6083SPeter Grehan 	while (--nlevels >= 0) {
188366f6083SPeter Grehan 		ptpshift = PAGE_SHIFT + nlevels * 9;
189366f6083SPeter Grehan 		ptpindex = (gpa >> ptpshift) & 0x1FF;
190366f6083SPeter Grehan 
191366f6083SPeter Grehan 		/* We have reached the leaf mapping */
192366f6083SPeter Grehan 		if (spshift >= ptpshift)
193366f6083SPeter Grehan 			break;
194366f6083SPeter Grehan 
195366f6083SPeter Grehan 		/*
196366f6083SPeter Grehan 		 * We are working on a non-leaf page table page.
197366f6083SPeter Grehan 		 *
198366f6083SPeter Grehan 		 * Create the next level page table page if necessary and point
199366f6083SPeter Grehan 		 * to it from the current page table.
200366f6083SPeter Grehan 		 */
201366f6083SPeter Grehan 		if (ptp[ptpindex] == 0) {
202366f6083SPeter Grehan 			void *nlp = malloc(PAGE_SIZE, M_VMX, M_WAITOK | M_ZERO);
203366f6083SPeter Grehan 			ptp[ptpindex] = vtophys(nlp);
204366f6083SPeter Grehan 			ptp[ptpindex] |= EPT_PG_RD | EPT_PG_WR | EPT_PG_EX;
205366f6083SPeter Grehan 		}
206366f6083SPeter Grehan 
207366f6083SPeter Grehan 		/* Work our way down to the next level page table page */
208366f6083SPeter Grehan 		ptp = (uint64_t *)PHYS_TO_DMAP(ptp[ptpindex] & EPT_ADDR_MASK);
209366f6083SPeter Grehan 	}
210366f6083SPeter Grehan 
211366f6083SPeter Grehan 	if ((gpa & ((1UL << ptpshift) - 1)) != 0) {
212366f6083SPeter Grehan 		panic("ept_create_mapping: gpa 0x%016lx and ptpshift %d "
213366f6083SPeter Grehan 		      "mismatch\n", gpa, ptpshift);
214366f6083SPeter Grehan 	}
215366f6083SPeter Grehan 
216*bda273f2SNeel Natu 	if (prot != VM_PROT_NONE) {
217366f6083SPeter Grehan 		/* Do the mapping */
218366f6083SPeter Grehan 		ptp[ptpindex] = hpa;
219366f6083SPeter Grehan 
220366f6083SPeter Grehan 		/* Apply the access controls */
221366f6083SPeter Grehan 		if (prot & VM_PROT_READ)
222366f6083SPeter Grehan 			ptp[ptpindex] |= EPT_PG_RD;
223366f6083SPeter Grehan 		if (prot & VM_PROT_WRITE)
224366f6083SPeter Grehan 			ptp[ptpindex] |= EPT_PG_WR;
225366f6083SPeter Grehan 		if (prot & VM_PROT_EXECUTE)
226366f6083SPeter Grehan 			ptp[ptpindex] |= EPT_PG_EX;
227366f6083SPeter Grehan 
228366f6083SPeter Grehan 		/*
229*bda273f2SNeel Natu 		 * XXX should we enforce this memory type by setting the
230*bda273f2SNeel Natu 		 * ignore PAT bit to 1.
231366f6083SPeter Grehan 		 */
232366f6083SPeter Grehan 		ptp[ptpindex] |= EPT_PG_MEMORY_TYPE(attr);
233366f6083SPeter Grehan 
234366f6083SPeter Grehan 		if (nlevels > 0)
235366f6083SPeter Grehan 			ptp[ptpindex] |= EPT_PG_SUPERPAGE;
236*bda273f2SNeel Natu 	} else {
237*bda273f2SNeel Natu 		/* Remove the mapping */
238*bda273f2SNeel Natu 		ptp[ptpindex] = 0;
239*bda273f2SNeel Natu 	}
240366f6083SPeter Grehan 
241366f6083SPeter Grehan 	return (1UL << ptpshift);
242366f6083SPeter Grehan }
243366f6083SPeter Grehan 
244*bda273f2SNeel Natu static vm_paddr_t
245*bda273f2SNeel Natu ept_lookup_mapping(uint64_t *ptp, vm_paddr_t gpa)
246*bda273f2SNeel Natu {
247*bda273f2SNeel Natu 	int nlevels, ptpshift, ptpindex;
248*bda273f2SNeel Natu 	uint64_t ptpval, hpabase, pgmask;
249*bda273f2SNeel Natu 
250*bda273f2SNeel Natu 	nlevels = EPT_PWLEVELS;
251*bda273f2SNeel Natu 	while (--nlevels >= 0) {
252*bda273f2SNeel Natu 		ptpshift = PAGE_SHIFT + nlevels * 9;
253*bda273f2SNeel Natu 		ptpindex = (gpa >> ptpshift) & 0x1FF;
254*bda273f2SNeel Natu 
255*bda273f2SNeel Natu 		ptpval = ptp[ptpindex];
256*bda273f2SNeel Natu 
257*bda273f2SNeel Natu 		/* Cannot make progress beyond this point */
258*bda273f2SNeel Natu 		if ((ptpval & (EPT_PG_RD | EPT_PG_WR | EPT_PG_EX)) == 0)
259*bda273f2SNeel Natu 			break;
260*bda273f2SNeel Natu 
261*bda273f2SNeel Natu 		if (nlevels == 0 || (ptpval & EPT_PG_SUPERPAGE)) {
262*bda273f2SNeel Natu 			pgmask = (1UL << ptpshift) - 1;
263*bda273f2SNeel Natu 			hpabase = ptpval & ~pgmask;
264*bda273f2SNeel Natu 			return (hpabase | (gpa & pgmask));
265*bda273f2SNeel Natu 		}
266*bda273f2SNeel Natu 
267*bda273f2SNeel Natu 		/* Work our way down to the next level page table page */
268*bda273f2SNeel Natu 		ptp = (uint64_t *)PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK);
269*bda273f2SNeel Natu 	}
270*bda273f2SNeel Natu 
271*bda273f2SNeel Natu 	return ((vm_paddr_t)-1);
272*bda273f2SNeel Natu }
273*bda273f2SNeel Natu 
274366f6083SPeter Grehan static void
275366f6083SPeter Grehan ept_free_pt_entry(pt_entry_t pte)
276366f6083SPeter Grehan {
277366f6083SPeter Grehan 	if (pte == 0)
278366f6083SPeter Grehan 		return;
279366f6083SPeter Grehan 
280366f6083SPeter Grehan 	/* sanity check */
281366f6083SPeter Grehan 	if ((pte & EPT_PG_SUPERPAGE) != 0)
282366f6083SPeter Grehan 		panic("ept_free_pt_entry: pte cannot have superpage bit");
283366f6083SPeter Grehan 
284366f6083SPeter Grehan 	return;
285366f6083SPeter Grehan }
286366f6083SPeter Grehan 
287366f6083SPeter Grehan static void
288366f6083SPeter Grehan ept_free_pd_entry(pd_entry_t pde)
289366f6083SPeter Grehan {
290366f6083SPeter Grehan 	pt_entry_t	*pt;
291366f6083SPeter Grehan 	int		i;
292366f6083SPeter Grehan 
293366f6083SPeter Grehan 	if (pde == 0)
294366f6083SPeter Grehan 		return;
295366f6083SPeter Grehan 
296366f6083SPeter Grehan 	if ((pde & EPT_PG_SUPERPAGE) == 0) {
297366f6083SPeter Grehan 		pt = (pt_entry_t *)PHYS_TO_DMAP(pde & EPT_ADDR_MASK);
298366f6083SPeter Grehan 		for (i = 0; i < NPTEPG; i++)
299366f6083SPeter Grehan 			ept_free_pt_entry(pt[i]);
300366f6083SPeter Grehan 		free(pt, M_VMX);	/* free the page table page */
301366f6083SPeter Grehan 	}
302366f6083SPeter Grehan }
303366f6083SPeter Grehan 
304366f6083SPeter Grehan static void
305366f6083SPeter Grehan ept_free_pdp_entry(pdp_entry_t pdpe)
306366f6083SPeter Grehan {
307366f6083SPeter Grehan 	pd_entry_t 	*pd;
308366f6083SPeter Grehan 	int		 i;
309366f6083SPeter Grehan 
310366f6083SPeter Grehan 	if (pdpe == 0)
311366f6083SPeter Grehan 		return;
312366f6083SPeter Grehan 
313366f6083SPeter Grehan 	if ((pdpe & EPT_PG_SUPERPAGE) == 0) {
314366f6083SPeter Grehan 		pd = (pd_entry_t *)PHYS_TO_DMAP(pdpe & EPT_ADDR_MASK);
315366f6083SPeter Grehan 		for (i = 0; i < NPDEPG; i++)
316366f6083SPeter Grehan 			ept_free_pd_entry(pd[i]);
317366f6083SPeter Grehan 		free(pd, M_VMX);	/* free the page directory page */
318366f6083SPeter Grehan 	}
319366f6083SPeter Grehan }
320366f6083SPeter Grehan 
321366f6083SPeter Grehan static void
322366f6083SPeter Grehan ept_free_pml4_entry(pml4_entry_t pml4e)
323366f6083SPeter Grehan {
324366f6083SPeter Grehan 	pdp_entry_t	*pdp;
325366f6083SPeter Grehan 	int		i;
326366f6083SPeter Grehan 
327366f6083SPeter Grehan 	if (pml4e == 0)
328366f6083SPeter Grehan 		return;
329366f6083SPeter Grehan 
330366f6083SPeter Grehan 	if ((pml4e & EPT_PG_SUPERPAGE) == 0) {
331366f6083SPeter Grehan 		pdp = (pdp_entry_t *)PHYS_TO_DMAP(pml4e & EPT_ADDR_MASK);
332366f6083SPeter Grehan 		for (i = 0; i < NPDPEPG; i++)
333366f6083SPeter Grehan 			ept_free_pdp_entry(pdp[i]);
334366f6083SPeter Grehan 		free(pdp, M_VMX);	/* free the page directory ptr page */
335366f6083SPeter Grehan 	}
336366f6083SPeter Grehan }
337366f6083SPeter Grehan 
338366f6083SPeter Grehan void
339366f6083SPeter Grehan ept_vmcleanup(struct vmx *vmx)
340366f6083SPeter Grehan {
341366f6083SPeter Grehan 	int 		 i;
342366f6083SPeter Grehan 
343366f6083SPeter Grehan 	for (i = 0; i < NPML4EPG; i++)
344366f6083SPeter Grehan 		ept_free_pml4_entry(vmx->pml4ept[i]);
345366f6083SPeter Grehan }
346366f6083SPeter Grehan 
347366f6083SPeter Grehan int
348*bda273f2SNeel Natu ept_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t len,
349366f6083SPeter Grehan 		vm_memattr_t attr, int prot, boolean_t spok)
350366f6083SPeter Grehan {
351366f6083SPeter Grehan 	size_t n;
352366f6083SPeter Grehan 	struct vmx *vmx = arg;
353366f6083SPeter Grehan 
354366f6083SPeter Grehan 	while (len > 0) {
355366f6083SPeter Grehan 		n = ept_create_mapping(vmx->pml4ept, gpa, hpa, len, attr,
356366f6083SPeter Grehan 				       prot, spok);
357366f6083SPeter Grehan 		len -= n;
358366f6083SPeter Grehan 		gpa += n;
359366f6083SPeter Grehan 		hpa += n;
360366f6083SPeter Grehan 	}
361366f6083SPeter Grehan 
362366f6083SPeter Grehan 	return (0);
363366f6083SPeter Grehan }
364366f6083SPeter Grehan 
365*bda273f2SNeel Natu vm_paddr_t
366*bda273f2SNeel Natu ept_vmmmap_get(void *arg, vm_paddr_t gpa)
367*bda273f2SNeel Natu {
368*bda273f2SNeel Natu 	vm_paddr_t hpa;
369*bda273f2SNeel Natu 	struct vmx *vmx;
370*bda273f2SNeel Natu 
371*bda273f2SNeel Natu 	vmx = arg;
372*bda273f2SNeel Natu 	hpa = ept_lookup_mapping(vmx->pml4ept, gpa);
373*bda273f2SNeel Natu 	return (hpa);
374*bda273f2SNeel Natu }
375*bda273f2SNeel Natu 
376366f6083SPeter Grehan static void
377366f6083SPeter Grehan invept_single_context(void *arg)
378366f6083SPeter Grehan {
379366f6083SPeter Grehan 	struct invept_desc desc = *(struct invept_desc *)arg;
380366f6083SPeter Grehan 
381366f6083SPeter Grehan 	invept(INVEPT_TYPE_SINGLE_CONTEXT, desc);
382366f6083SPeter Grehan }
383366f6083SPeter Grehan 
384366f6083SPeter Grehan void
385366f6083SPeter Grehan ept_invalidate_mappings(u_long pml4ept)
386366f6083SPeter Grehan {
387366f6083SPeter Grehan 	struct invept_desc invept_desc = { 0 };
388366f6083SPeter Grehan 
389366f6083SPeter Grehan 	invept_desc.eptp = EPTP(pml4ept);
390366f6083SPeter Grehan 
391366f6083SPeter Grehan 	smp_rendezvous(NULL, invept_single_context, NULL, &invept_desc);
392366f6083SPeter Grehan }
393