xref: /illumos-gate/usr/src/uts/intel/io/vmm/sys/vmm_gpt.h (revision f1ff157950b3591080b56622b1ee870b0ad89f31)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 /* This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE */
12 
13 /*
14  * Copyright 2019 Joyent, Inc.
15  * Copyright 2025 Oxide Computer Company
16  */
17 
18 #ifndef _VMM_GPT_H
19 #define	_VMM_GPT_H
20 
21 #include <sys/types.h>
22 
23 /*
24  * Constants for the nodes in the GPT radix tree.  Note
25  * that, in accordance with hardware page table descriptions,
26  * the root of the tree is referred to as "LEVEL4" while the
27  * leaf level is "LEVEL1".
28  */
29 typedef enum vmm_gpt_node_level {
30 	LEVEL4 = 0,
31 	LEVEL3,
32 	LEVEL2,
33 	LEVEL1,
34 	MAX_GPT_LEVEL,
35 } vmm_gpt_node_level_t;
36 
37 typedef enum vmm_gpt_query {
38 	VGQ_ACCESSED,
39 	VGQ_DIRTY,
40 } vmm_gpt_query_t;
41 
42 /*
43  * The vmm_pte_ops structure contains function pointers for format-specific
44  * operations on page table entries.  The operations are as follows:
45  *
46  * vpeo_map_table: Creates a PTE that maps an inner node in the page table.
47  * vpeo_map_page: Creates a leaf entry PTE that maps a page of physical memory.
48  * vpeo_pte_pfn: Returns the PFN contained in the given PTE.
49  * vpeo_pte_is_present: Returns true IFF the PTE maps a present page.
50  * vpeo_pte_prot: Returns a bitmask of protection bits for the PTE.
51  *   The bits correspond to the standard mmap(2) bits: PROT_READ, PROT_WRITE,
52  *   PROT_EXEC.
53  * vpeo_reset_dirty: Resets the dirty bit on the given PTE.  If the second
54  *   argument is `true`, the bit will be set, otherwise it will be cleared.
55  *   Returns non-zero if the previous value of the bit was set.
56  * vpeo_reset_accessed: Resets the accessed bit on the given PTE.  If the
57  *   second argument is `true`, the bit will be set, otherwise it will be
58  *   cleared.  Returns non-zero if the previous value of the bit was set.
59  * vpeo_get_pmtp: Generate a properly formatted PML4 (EPTP/nCR3), given the root
60  *   PFN for the GPT.
61  * vpeo_hw_ad_supported: Returns true IFF hardware A/D tracking is supported.
62  */
63 typedef struct vmm_pte_ops vmm_pte_ops_t;
64 struct vmm_pte_ops {
65 	uint64_t	(*vpeo_map_table)(pfn_t);
66 	uint64_t	(*vpeo_map_page)(pfn_t, uint_t, uint8_t);
67 	pfn_t		(*vpeo_pte_pfn)(uint64_t);
68 	bool		(*vpeo_pte_is_present)(uint64_t);
69 	uint_t		(*vpeo_pte_prot)(uint64_t);
70 	uint_t		(*vpeo_reset_dirty)(uint64_t *, bool);
71 	uint_t		(*vpeo_reset_accessed)(uint64_t *, bool);
72 	uint64_t	(*vpeo_get_pmtp)(pfn_t, bool);
73 	bool		(*vpeo_hw_ad_supported)(void);
74 	bool		(*vpeo_query)(uint64_t *, vmm_gpt_query_t);
75 };
76 
77 extern vmm_pte_ops_t ept_pte_ops;
78 extern vmm_pte_ops_t rvi_pte_ops;
79 
80 struct vmm_gpt;
81 typedef struct vmm_gpt vmm_gpt_t;
82 
83 /* PTEs get a defined type to distinguish them from other uint64_t variables */
84 typedef uint64_t vmm_gpt_entry_t;
85 
86 typedef struct vmm_gpt_iter {
87 	vmm_gpt_t *vgi_gpt;
88 	uint64_t vgi_addr;
89 	uint64_t vgi_end;
90 	uint64_t vgi_current;
91 	vmm_gpt_entry_t *vgi_entries[MAX_GPT_LEVEL];
92 } vmm_gpt_iter_t;
93 
94 typedef struct vmm_gpt_iter_entry {
95 	uint64_t vgie_gpa;
96 	vmm_gpt_entry_t *vgie_ptep;
97 } vmm_gpt_iter_entry_t;
98 
99 vmm_gpt_t *vmm_gpt_alloc(vmm_pte_ops_t *);
100 void vmm_gpt_free(vmm_gpt_t *);
101 
102 uint64_t vmm_gpt_walk(vmm_gpt_t *, uint64_t, vmm_gpt_entry_t **,
103     vmm_gpt_node_level_t);
104 void vmm_gpt_iter_init(vmm_gpt_iter_t *, vmm_gpt_t *, uint64_t, uint64_t);
105 bool vmm_gpt_iter_next(vmm_gpt_iter_t *, vmm_gpt_iter_entry_t *);
106 void vmm_gpt_populate_region(vmm_gpt_t *, uint64_t, uint64_t);
107 bool vmm_gpt_map_at(vmm_gpt_t *, vmm_gpt_entry_t *, pfn_t, uint_t, uint8_t);
108 void vmm_gpt_vacate_region(vmm_gpt_t *, uint64_t, uint64_t);
109 bool vmm_gpt_unmap(vmm_gpt_t *, uint64_t);
110 size_t vmm_gpt_unmap_region(vmm_gpt_t *, uint64_t, uint64_t);
111 uint64_t vmm_gpt_get_pmtp(vmm_gpt_t *, bool);
112 
113 bool vmm_gpt_is_mapped(vmm_gpt_t *, vmm_gpt_entry_t *, pfn_t *, uint_t *);
114 uint_t vmm_gpt_reset_accessed(vmm_gpt_t *, vmm_gpt_entry_t *, bool);
115 uint_t vmm_gpt_reset_dirty(vmm_gpt_t *, vmm_gpt_entry_t *, bool);
116 bool vmm_gpt_query(vmm_gpt_t *, vmm_gpt_entry_t *, vmm_gpt_query_t);
117 bool vmm_gpt_can_track_dirty(vmm_gpt_t *);
118 
119 #endif /* _VMM_GPT_H */
120