/root/src/xen/xen/include/asm/hvm/vmx/vmx.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * vmx.h: VMX Architecture related definitions |
3 | | * Copyright (c) 2004, Intel Corporation. |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify it |
6 | | * under the terms and conditions of the GNU General Public License, |
7 | | * version 2, as published by the Free Software Foundation. |
8 | | * |
9 | | * This program is distributed in the hope it will be useful, but WITHOUT |
10 | | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
12 | | * more details. |
13 | | * |
14 | | * You should have received a copy of the GNU General Public License along with |
15 | | * this program; If not, see <http://www.gnu.org/licenses/>. |
16 | | * |
17 | | */ |
18 | | #ifndef __ASM_X86_HVM_VMX_VMX_H__ |
19 | | #define __ASM_X86_HVM_VMX_VMX_H__ |
20 | | |
21 | | #include <xen/sched.h> |
22 | | #include <asm/types.h> |
23 | | #include <asm/regs.h> |
24 | | #include <asm/asm_defns.h> |
25 | | #include <asm/processor.h> |
26 | | #include <asm/i387.h> |
27 | | #include <asm/hvm/support.h> |
28 | | #include <asm/hvm/trace.h> |
29 | | #include <asm/hvm/vmx/vmcs.h> |
30 | | |
31 | | typedef union { |
32 | | struct { |
33 | | u64 r : 1, /* bit 0 - Read permission */ |
34 | | w : 1, /* bit 1 - Write permission */ |
35 | | x : 1, /* bit 2 - Execute permission */ |
36 | | emt : 3, /* bits 5:3 - EPT Memory type */ |
37 | | ipat : 1, /* bit 6 - Ignore PAT memory type */ |
38 | | sp : 1, /* bit 7 - Is this a superpage? */ |
39 | | a : 1, /* bit 8 - Access bit */ |
40 | | d : 1, /* bit 9 - Dirty bit */ |
41 | | recalc : 1, /* bit 10 - Software available 1 */ |
42 | | snp : 1, /* bit 11 - VT-d snoop control in shared |
43 | | EPT/VT-d usage */ |
44 | | mfn : 40, /* bits 51:12 - Machine physical frame number */ |
45 | | sa_p2mt : 6, /* bits 57:52 - Software available 2 */ |
46 | | access : 4, /* bits 61:58 - p2m_access_t */ |
47 | | tm : 1, /* bit 62 - VT-d transient-mapping hint in |
48 | | shared EPT/VT-d usage */ |
49 | | suppress_ve : 1; /* bit 63 - suppress #VE */ |
50 | | }; |
51 | | u64 epte; |
52 | | } ept_entry_t; |
53 | | |
54 | | typedef struct { |
55 | | /*use lxe[0] to save result */ |
56 | | ept_entry_t lxe[5]; |
57 | | } ept_walk_t; |
58 | | |
59 | | typedef enum { |
60 | | ept_access_n = 0, /* No access permissions allowed */ |
61 | | ept_access_r = 1, /* Read only */ |
62 | | ept_access_w = 2, /* Write only */ |
63 | | ept_access_rw = 3, /* Read & Write */ |
64 | | ept_access_x = 4, /* Exec Only */ |
65 | | ept_access_rx = 5, /* Read & Exec */ |
66 | | ept_access_wx = 6, /* Write & Exec*/ |
67 | | ept_access_all = 7, /* Full permissions */ |
68 | | } ept_access_t; |
69 | | |
70 | 40.8M | #define EPT_TABLE_ORDER 9 |
71 | 0 | #define EPTE_SUPER_PAGE_MASK 0x80 |
72 | | #define EPTE_MFN_MASK 0xffffffffff000ULL |
73 | | #define EPTE_AVAIL1_MASK 0xF00 |
74 | 0 | #define EPTE_EMT_MASK 0x38 |
75 | 0 | #define EPTE_IGMT_MASK 0x40 |
76 | | #define EPTE_AVAIL1_SHIFT 8 |
77 | | #define EPTE_EMT_SHIFT 3 |
78 | | #define EPTE_IGMT_SHIFT 6 |
79 | 0 | #define EPTE_RWX_MASK 0x7 |
80 | 0 | #define EPTE_FLAG_MASK 0x7f |
81 | | |
82 | | #define EPT_EMT_UC 0 |
83 | | #define EPT_EMT_WC 1 |
84 | 0 | #define EPT_EMT_RSV0 2 |
85 | 0 | #define EPT_EMT_RSV1 3 |
86 | | #define EPT_EMT_WT 4 |
87 | | #define EPT_EMT_WP 5 |
88 | | #define EPT_EMT_WB 6 |
89 | 0 | #define EPT_EMT_RSV2 7 |
90 | | |
91 | | #define PI_xAPIC_NDST_MASK 0xFF00 |
92 | | |
93 | | void vmx_asm_vmexit_handler(struct cpu_user_regs); |
94 | | void vmx_asm_do_vmentry(void); |
95 | | void vmx_intr_assist(void); |
96 | | void noreturn vmx_do_resume(struct vcpu *); |
97 | | void vmx_vlapic_msr_changed(struct vcpu *v); |
98 | | void vmx_realmode_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt); |
99 | | void vmx_realmode(struct cpu_user_regs *regs); |
100 | | void vmx_update_debug_state(struct vcpu *v); |
101 | | void vmx_update_exception_bitmap(struct vcpu *v); |
102 | | void vmx_update_cpu_exec_control(struct vcpu *v); |
103 | | void vmx_update_secondary_exec_control(struct vcpu *v); |
104 | | |
105 | 8.28k | #define POSTED_INTR_ON 0 |
106 | 4.14k | #define POSTED_INTR_SN 1 |
107 | | static inline int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc) |
108 | 4.14k | { |
109 | 4.14k | return test_and_set_bit(vector, pi_desc->pir); |
110 | 4.14k | } Unexecuted instantiation: iommu.c:pi_test_and_set_pir Unexecuted instantiation: p2m-ept.c:pi_test_and_set_pir Unexecuted instantiation: p2m.c:pi_test_and_set_pir Unexecuted instantiation: vvmx.c:pi_test_and_set_pir vmx.c:pi_test_and_set_pir Line | Count | Source | 108 | 4.14k | { | 109 | 4.14k | return test_and_set_bit(vector, pi_desc->pir); | 110 | 4.14k | } |
Unexecuted instantiation: vmcs.c:pi_test_and_set_pir Unexecuted instantiation: realmode.c:pi_test_and_set_pir Unexecuted instantiation: intr.c:pi_test_and_set_pir Unexecuted instantiation: vlapic.c:pi_test_and_set_pir Unexecuted instantiation: ioreq.c:pi_test_and_set_pir Unexecuted instantiation: vpmu_intel.c:pi_test_and_set_pir Unexecuted instantiation: vpmu.c:pi_test_and_set_pir Unexecuted instantiation: nested_ept.c:pi_test_and_set_pir |
111 | | |
112 | | static inline int pi_test_and_set_on(struct pi_desc *pi_desc) |
113 | 0 | { |
114 | 0 | return test_and_set_bit(POSTED_INTR_ON, &pi_desc->control); |
115 | 0 | } Unexecuted instantiation: vpmu.c:pi_test_and_set_on Unexecuted instantiation: vpmu_intel.c:pi_test_and_set_on Unexecuted instantiation: ioreq.c:pi_test_and_set_on Unexecuted instantiation: vlapic.c:pi_test_and_set_on Unexecuted instantiation: intr.c:pi_test_and_set_on Unexecuted instantiation: realmode.c:pi_test_and_set_on Unexecuted instantiation: vmcs.c:pi_test_and_set_on Unexecuted instantiation: vmx.c:pi_test_and_set_on Unexecuted instantiation: vvmx.c:pi_test_and_set_on Unexecuted instantiation: p2m.c:pi_test_and_set_on Unexecuted instantiation: p2m-ept.c:pi_test_and_set_on Unexecuted instantiation: nested_ept.c:pi_test_and_set_on Unexecuted instantiation: iommu.c:pi_test_and_set_on |
116 | | |
117 | | static inline void pi_set_on(struct pi_desc *pi_desc) |
118 | 3 | { |
119 | 3 | set_bit(POSTED_INTR_ON, &pi_desc->control); |
120 | 3 | } Unexecuted instantiation: iommu.c:pi_set_on Unexecuted instantiation: nested_ept.c:pi_set_on Unexecuted instantiation: vpmu.c:pi_set_on Unexecuted instantiation: vpmu_intel.c:pi_set_on Unexecuted instantiation: ioreq.c:pi_set_on Unexecuted instantiation: vlapic.c:pi_set_on Unexecuted instantiation: intr.c:pi_set_on Unexecuted instantiation: realmode.c:pi_set_on Unexecuted instantiation: vmcs.c:pi_set_on Line | Count | Source | 118 | 3 | { | 119 | 3 | set_bit(POSTED_INTR_ON, &pi_desc->control); | 120 | 3 | } |
Unexecuted instantiation: vvmx.c:pi_set_on Unexecuted instantiation: p2m.c:pi_set_on Unexecuted instantiation: p2m-ept.c:pi_set_on |
121 | | |
122 | | static inline int pi_test_and_clear_on(struct pi_desc *pi_desc) |
123 | 7.08M | { |
124 | 7.08M | return test_and_clear_bit(POSTED_INTR_ON, &pi_desc->control); |
125 | 7.08M | } Unexecuted instantiation: p2m-ept.c:pi_test_and_clear_on Unexecuted instantiation: iommu.c:pi_test_and_clear_on Unexecuted instantiation: vpmu.c:pi_test_and_clear_on Unexecuted instantiation: vpmu_intel.c:pi_test_and_clear_on Unexecuted instantiation: ioreq.c:pi_test_and_clear_on Unexecuted instantiation: vlapic.c:pi_test_and_clear_on Unexecuted instantiation: intr.c:pi_test_and_clear_on Unexecuted instantiation: realmode.c:pi_test_and_clear_on Unexecuted instantiation: vmcs.c:pi_test_and_clear_on vmx.c:pi_test_and_clear_on Line | Count | Source | 123 | 7.08M | { | 124 | 7.08M | return test_and_clear_bit(POSTED_INTR_ON, &pi_desc->control); | 125 | 7.08M | } |
Unexecuted instantiation: vvmx.c:pi_test_and_clear_on Unexecuted instantiation: p2m.c:pi_test_and_clear_on Unexecuted instantiation: nested_ept.c:pi_test_and_clear_on |
126 | | |
127 | | static inline int pi_test_on(struct pi_desc *pi_desc) |
128 | 4.14k | { |
129 | 4.14k | return pi_desc->on; |
130 | 4.14k | } Unexecuted instantiation: nested_ept.c:pi_test_on Unexecuted instantiation: p2m-ept.c:pi_test_on Unexecuted instantiation: p2m.c:pi_test_on Unexecuted instantiation: vvmx.c:pi_test_on Line | Count | Source | 128 | 4.14k | { | 129 | 4.14k | return pi_desc->on; | 130 | 4.14k | } |
Unexecuted instantiation: vmcs.c:pi_test_on Unexecuted instantiation: realmode.c:pi_test_on Unexecuted instantiation: intr.c:pi_test_on Unexecuted instantiation: vlapic.c:pi_test_on Unexecuted instantiation: ioreq.c:pi_test_on Unexecuted instantiation: vpmu_intel.c:pi_test_on Unexecuted instantiation: vpmu.c:pi_test_on Unexecuted instantiation: iommu.c:pi_test_on |
131 | | |
132 | | static inline unsigned long pi_get_pir(struct pi_desc *pi_desc, int group) |
133 | 16.2k | { |
134 | 16.2k | return xchg(&pi_desc->pir[group], 0); |
135 | 16.2k | } Unexecuted instantiation: nested_ept.c:pi_get_pir Unexecuted instantiation: p2m-ept.c:pi_get_pir Unexecuted instantiation: p2m.c:pi_get_pir Unexecuted instantiation: vvmx.c:pi_get_pir Line | Count | Source | 133 | 16.2k | { | 134 | 16.2k | return xchg(&pi_desc->pir[group], 0); | 135 | 16.2k | } |
Unexecuted instantiation: vmcs.c:pi_get_pir Unexecuted instantiation: realmode.c:pi_get_pir Unexecuted instantiation: intr.c:pi_get_pir Unexecuted instantiation: vlapic.c:pi_get_pir Unexecuted instantiation: ioreq.c:pi_get_pir Unexecuted instantiation: vpmu_intel.c:pi_get_pir Unexecuted instantiation: vpmu.c:pi_get_pir Unexecuted instantiation: iommu.c:pi_get_pir |
136 | | |
137 | | static inline int pi_test_sn(struct pi_desc *pi_desc) |
138 | 4.14k | { |
139 | 4.14k | return pi_desc->sn; |
140 | 4.14k | } Unexecuted instantiation: nested_ept.c:pi_test_sn Unexecuted instantiation: p2m-ept.c:pi_test_sn Unexecuted instantiation: p2m.c:pi_test_sn Unexecuted instantiation: vvmx.c:pi_test_sn Line | Count | Source | 138 | 4.14k | { | 139 | 4.14k | return pi_desc->sn; | 140 | 4.14k | } |
Unexecuted instantiation: vmcs.c:pi_test_sn Unexecuted instantiation: realmode.c:pi_test_sn Unexecuted instantiation: intr.c:pi_test_sn Unexecuted instantiation: vlapic.c:pi_test_sn Unexecuted instantiation: ioreq.c:pi_test_sn Unexecuted instantiation: vpmu_intel.c:pi_test_sn Unexecuted instantiation: vpmu.c:pi_test_sn Unexecuted instantiation: iommu.c:pi_test_sn |
141 | | |
142 | | static inline void pi_set_sn(struct pi_desc *pi_desc) |
143 | 0 | { |
144 | 0 | set_bit(POSTED_INTR_SN, &pi_desc->control); |
145 | 0 | } Unexecuted instantiation: p2m-ept.c:pi_set_sn Unexecuted instantiation: p2m.c:pi_set_sn Unexecuted instantiation: vvmx.c:pi_set_sn Unexecuted instantiation: vmx.c:pi_set_sn Unexecuted instantiation: vmcs.c:pi_set_sn Unexecuted instantiation: realmode.c:pi_set_sn Unexecuted instantiation: intr.c:pi_set_sn Unexecuted instantiation: vlapic.c:pi_set_sn Unexecuted instantiation: ioreq.c:pi_set_sn Unexecuted instantiation: vpmu_intel.c:pi_set_sn Unexecuted instantiation: vpmu.c:pi_set_sn Unexecuted instantiation: iommu.c:pi_set_sn Unexecuted instantiation: nested_ept.c:pi_set_sn |
146 | | |
147 | | static inline void pi_clear_sn(struct pi_desc *pi_desc) |
148 | 0 | { |
149 | 0 | clear_bit(POSTED_INTR_SN, &pi_desc->control); |
150 | 0 | } Unexecuted instantiation: nested_ept.c:pi_clear_sn Unexecuted instantiation: p2m-ept.c:pi_clear_sn Unexecuted instantiation: p2m.c:pi_clear_sn Unexecuted instantiation: vvmx.c:pi_clear_sn Unexecuted instantiation: vmx.c:pi_clear_sn Unexecuted instantiation: vmcs.c:pi_clear_sn Unexecuted instantiation: realmode.c:pi_clear_sn Unexecuted instantiation: intr.c:pi_clear_sn Unexecuted instantiation: vlapic.c:pi_clear_sn Unexecuted instantiation: ioreq.c:pi_clear_sn Unexecuted instantiation: vpmu_intel.c:pi_clear_sn Unexecuted instantiation: vpmu.c:pi_clear_sn Unexecuted instantiation: iommu.c:pi_clear_sn |
151 | | |
152 | | /* |
153 | | * Exit Reasons |
154 | | */ |
155 | 0 | #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 |
156 | | |
157 | 12 | #define EXIT_REASON_EXCEPTION_NMI 0 |
158 | 35.5k | #define EXIT_REASON_EXTERNAL_INTERRUPT 1 |
159 | 0 | #define EXIT_REASON_TRIPLE_FAULT 2 |
160 | 0 | #define EXIT_REASON_INIT 3 |
161 | 0 | #define EXIT_REASON_SIPI 4 |
162 | | #define EXIT_REASON_IO_SMI 5 |
163 | | #define EXIT_REASON_OTHER_SMI 6 |
164 | 93.3k | #define EXIT_REASON_PENDING_VIRT_INTR 7 |
165 | 0 | #define EXIT_REASON_PENDING_VIRT_NMI 8 |
166 | 5.18M | #define EXIT_REASON_TASK_SWITCH 9 |
167 | 2.66k | #define EXIT_REASON_CPUID 10 |
168 | 0 | #define EXIT_REASON_GETSEC 11 |
169 | 65.4k | #define EXIT_REASON_HLT 12 |
170 | 44 | #define EXIT_REASON_INVD 13 |
171 | 0 | #define EXIT_REASON_INVLPG 14 |
172 | 0 | #define EXIT_REASON_RDPMC 15 |
173 | 0 | #define EXIT_REASON_RDTSC 16 |
174 | | #define EXIT_REASON_RSM 17 |
175 | 304k | #define EXIT_REASON_VMCALL 18 |
176 | 0 | #define EXIT_REASON_VMCLEAR 19 |
177 | 0 | #define EXIT_REASON_VMLAUNCH 20 |
178 | 0 | #define EXIT_REASON_VMPTRLD 21 |
179 | 0 | #define EXIT_REASON_VMPTRST 22 |
180 | 0 | #define EXIT_REASON_VMREAD 23 |
181 | 0 | #define EXIT_REASON_VMRESUME 24 |
182 | 0 | #define EXIT_REASON_VMWRITE 25 |
183 | 0 | #define EXIT_REASON_VMXOFF 26 |
184 | 0 | #define EXIT_REASON_VMXON 27 |
185 | 7.76k | #define EXIT_REASON_CR_ACCESS 28 |
186 | 0 | #define EXIT_REASON_DR_ACCESS 29 |
187 | 20.1k | #define EXIT_REASON_IO_INSTRUCTION 30 |
188 | 271 | #define EXIT_REASON_MSR_READ 31 |
189 | 563 | #define EXIT_REASON_MSR_WRITE 32 |
190 | 0 | #define EXIT_REASON_INVALID_GUEST_STATE 33 |
191 | 0 | #define EXIT_REASON_MSR_LOADING 34 |
192 | 0 | #define EXIT_REASON_MWAIT_INSTRUCTION 36 |
193 | 0 | #define EXIT_REASON_MONITOR_TRAP_FLAG 37 |
194 | 0 | #define EXIT_REASON_MONITOR_INSTRUCTION 39 |
195 | 4.52M | #define EXIT_REASON_PAUSE_INSTRUCTION 40 |
196 | 0 | #define EXIT_REASON_MCE_DURING_VMENTRY 41 |
197 | 0 | #define EXIT_REASON_TPR_BELOW_THRESHOLD 43 |
198 | 0 | #define EXIT_REASON_APIC_ACCESS 44 |
199 | 296 | #define EXIT_REASON_EOI_INDUCED 45 |
200 | 0 | #define EXIT_REASON_ACCESS_GDTR_OR_IDTR 46 |
201 | 0 | #define EXIT_REASON_ACCESS_LDTR_OR_TR 47 |
202 | 60.1k | #define EXIT_REASON_EPT_VIOLATION 48 |
203 | 3.15k | #define EXIT_REASON_EPT_MISCONFIG 49 |
204 | 0 | #define EXIT_REASON_INVEPT 50 |
205 | 0 | #define EXIT_REASON_RDTSCP 51 |
206 | 0 | #define EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED 52 |
207 | 0 | #define EXIT_REASON_INVVPID 53 |
208 | 44 | #define EXIT_REASON_WBINVD 54 |
209 | 11 | #define EXIT_REASON_XSETBV 55 |
210 | 0 | #define EXIT_REASON_APIC_WRITE 56 |
211 | 0 | #define EXIT_REASON_INVPCID 58 |
212 | 0 | #define EXIT_REASON_VMFUNC 59 |
213 | 0 | #define EXIT_REASON_PML_FULL 62 |
214 | 0 | #define EXIT_REASON_XSAVES 63 |
215 | 0 | #define EXIT_REASON_XRSTORS 64 |
216 | | |
217 | | /* |
218 | | * Interruption-information format |
219 | | */ |
220 | 17.8k | #define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */ |
221 | 0 | #define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */ |
222 | 0 | #define INTR_INFO_DELIVER_CODE_MASK 0x800 /* 11 */ |
223 | | #define INTR_INFO_NMI_UNBLOCKED_BY_IRET 0x1000 /* 12 */ |
224 | 41.9k | #define INTR_INFO_VALID_MASK 0x80000000 /* 31 */ |
225 | 0 | #define INTR_INFO_RESVD_BITS_MASK 0x7ffff000 |
226 | | |
227 | | /* |
228 | | * Exit Qualifications for MOV for Control Register Access |
229 | | */ |
230 | | /* 3:0 - control register number (CRn) */ |
231 | 2.93k | #define VMX_CONTROL_REG_ACCESS_NUM(eq) ((eq) & 0xf) |
232 | | /* 5:4 - access type (CR write, CR read, CLTS, LMSW) */ |
233 | 7.76k | #define VMX_CONTROL_REG_ACCESS_TYPE(eq) (((eq) >> 4) & 0x3) |
234 | 2.93k | # define VMX_CONTROL_REG_ACCESS_TYPE_MOV_TO_CR 0 |
235 | 0 | # define VMX_CONTROL_REG_ACCESS_TYPE_MOV_FROM_CR 1 |
236 | 3.79k | # define VMX_CONTROL_REG_ACCESS_TYPE_CLTS 2 |
237 | 1.03k | # define VMX_CONTROL_REG_ACCESS_TYPE_LMSW 3 |
238 | | /* 11:8 - general purpose register operand */ |
239 | 2.93k | #define VMX_CONTROL_REG_ACCESS_GPR(eq) (((eq) >> 8) & 0xf) |
240 | | /* 31:16 - LMSW source data */ |
241 | 1.03k | #define VMX_CONTROL_REG_ACCESS_DATA(eq) ((uint32_t)(eq) >> 16) |
242 | | |
243 | | /* |
244 | | * Access Rights |
245 | | */ |
246 | | #define X86_SEG_AR_SEG_TYPE 0xf /* 3:0, segment type */ |
247 | | #define X86_SEG_AR_DESC_TYPE (1u << 4) /* 4, descriptor type */ |
248 | | #define X86_SEG_AR_DPL 0x60 /* 6:5, descriptor privilege level */ |
249 | | #define X86_SEG_AR_SEG_PRESENT (1u << 7) /* 7, segment present */ |
250 | | #define X86_SEG_AR_AVL (1u << 12) /* 12, available for system software */ |
251 | | #define X86_SEG_AR_CS_LM_ACTIVE (1u << 13) /* 13, long mode active (CS only) */ |
252 | | #define X86_SEG_AR_DEF_OP_SIZE (1u << 14) /* 14, default operation size */ |
253 | | #define X86_SEG_AR_GRANULARITY (1u << 15) /* 15, granularity */ |
254 | | #define X86_SEG_AR_SEG_UNUSABLE (1u << 16) /* 16, segment unusable */ |
255 | | |
256 | | #define VMCALL_OPCODE ".byte 0x0f,0x01,0xc1\n" |
257 | | #define VMCLEAR_OPCODE ".byte 0x66,0x0f,0xc7\n" /* reg/opcode: /6 */ |
258 | | #define VMLAUNCH_OPCODE ".byte 0x0f,0x01,0xc2\n" |
259 | | #define VMPTRLD_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /6 */ |
260 | | #define VMPTRST_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /7 */ |
261 | | #define VMREAD_OPCODE ".byte 0x0f,0x78\n" |
262 | | #define VMRESUME_OPCODE ".byte 0x0f,0x01,0xc3\n" |
263 | | #define VMWRITE_OPCODE ".byte 0x0f,0x79\n" |
264 | | #define INVEPT_OPCODE ".byte 0x66,0x0f,0x38,0x80\n" /* m128,r64/32 */ |
265 | | #define INVVPID_OPCODE ".byte 0x66,0x0f,0x38,0x81\n" /* m128,r64/32 */ |
266 | | #define VMXOFF_OPCODE ".byte 0x0f,0x01,0xc4\n" |
267 | | #define VMXON_OPCODE ".byte 0xf3,0x0f,0xc7\n" |
268 | | |
269 | | #define MODRM_EAX_08 ".byte 0x08\n" /* ECX, [EAX] */ |
270 | | #define MODRM_EAX_06 ".byte 0x30\n" /* [EAX], with reg/opcode: /6 */ |
271 | | #define MODRM_EAX_07 ".byte 0x38\n" /* [EAX], with reg/opcode: /7 */ |
272 | | #define MODRM_EAX_ECX ".byte 0xc1\n" /* EAX, ECX */ |
273 | | |
274 | | extern uint8_t posted_intr_vector; |
275 | | |
276 | | #define cpu_has_vmx_ept_exec_only_supported \ |
277 | 0 | (vmx_ept_vpid_cap & VMX_EPT_EXEC_ONLY_SUPPORTED) |
278 | | |
279 | | #define cpu_has_vmx_ept_wl4_supported \ |
280 | | (vmx_ept_vpid_cap & VMX_EPT_WALK_LENGTH_4_SUPPORTED) |
281 | | #define cpu_has_vmx_ept_mt_uc (vmx_ept_vpid_cap & VMX_EPT_MEMORY_TYPE_UC) |
282 | | #define cpu_has_vmx_ept_mt_wb (vmx_ept_vpid_cap & VMX_EPT_MEMORY_TYPE_WB) |
283 | 1 | #define cpu_has_vmx_ept_2mb (vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_2MB) |
284 | 1 | #define cpu_has_vmx_ept_1gb (vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_1GB) |
285 | 1.43M | #define cpu_has_vmx_ept_ad (vmx_ept_vpid_cap & VMX_EPT_AD_BIT) |
286 | | #define cpu_has_vmx_ept_invept_single_context \ |
287 | 411 | (vmx_ept_vpid_cap & VMX_EPT_INVEPT_SINGLE_CONTEXT) |
288 | | |
289 | 1 | #define EPT_2MB_SHIFT 16 |
290 | 1 | #define EPT_1GB_SHIFT 17 |
291 | 1 | #define ept_has_2mb(c) ((c >> EPT_2MB_SHIFT) & 1) |
292 | 1 | #define ept_has_1gb(c) ((c >> EPT_1GB_SHIFT) & 1) |
293 | | |
294 | 795 | #define INVEPT_SINGLE_CONTEXT 1 |
295 | 12 | #define INVEPT_ALL_CONTEXT 2 |
296 | | |
297 | | #define cpu_has_vmx_vpid_invvpid_individual_addr \ |
298 | | (vmx_ept_vpid_cap & VMX_VPID_INVVPID_INDIVIDUAL_ADDR) |
299 | | #define cpu_has_vmx_vpid_invvpid_single_context \ |
300 | 0 | (vmx_ept_vpid_cap & VMX_VPID_INVVPID_SINGLE_CONTEXT) |
301 | | #define cpu_has_vmx_vpid_invvpid_single_context_retaining_global \ |
302 | | (vmx_ept_vpid_cap & VMX_VPID_INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL) |
303 | | |
304 | 0 | #define INVVPID_INDIVIDUAL_ADDR 0 |
305 | 0 | #define INVVPID_SINGLE_CONTEXT 1 |
306 | 24 | #define INVVPID_ALL_CONTEXT 2 |
307 | | #define INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL 3 |
308 | | |
309 | | #ifdef HAVE_GAS_VMX |
310 | | # define GAS_VMX_OP(yes, no) yes |
311 | | #else |
312 | | # define GAS_VMX_OP(yes, no) no |
313 | | #endif |
314 | | |
315 | | static always_inline void __vmptrld(u64 addr) |
316 | 34.7k | { |
317 | 34.7k | asm volatile ( |
318 | 34.7k | #ifdef HAVE_GAS_VMX |
319 | 34.7k | "vmptrld %0\n" |
320 | 34.7k | #else |
321 | | VMPTRLD_OPCODE MODRM_EAX_06 |
322 | | #endif |
323 | 34.7k | /* CF==1 or ZF==1 --> BUG() */ |
324 | 34.7k | UNLIKELY_START(be, vmptrld) |
325 | 34.7k | _ASM_BUGFRAME_TEXT(0) |
326 | 34.7k | UNLIKELY_END_SECTION |
327 | 34.7k | : |
328 | 34.7k | #ifdef HAVE_GAS_VMX |
329 | 34.7k | : "m" (addr), |
330 | 34.7k | #else |
331 | | : "a" (&addr), |
332 | | #endif |
333 | 34.7k | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) |
334 | 34.7k | : "memory"); |
335 | 34.7k | } Unexecuted instantiation: nested_ept.c:__vmptrld Unexecuted instantiation: vpmu.c:__vmptrld Unexecuted instantiation: vpmu_intel.c:__vmptrld Unexecuted instantiation: ioreq.c:__vmptrld Unexecuted instantiation: vlapic.c:__vmptrld Unexecuted instantiation: intr.c:__vmptrld Unexecuted instantiation: realmode.c:__vmptrld Unexecuted instantiation: iommu.c:__vmptrld Line | Count | Source | 316 | 34.7k | { | 317 | 34.7k | asm volatile ( | 318 | 34.7k | #ifdef HAVE_GAS_VMX | 319 | 34.7k | "vmptrld %0\n" | 320 | 34.7k | #else | 321 | | VMPTRLD_OPCODE MODRM_EAX_06 | 322 | | #endif | 323 | 34.7k | /* CF==1 or ZF==1 --> BUG() */ | 324 | 34.7k | UNLIKELY_START(be, vmptrld) | 325 | 34.7k | _ASM_BUGFRAME_TEXT(0) | 326 | 34.7k | UNLIKELY_END_SECTION | 327 | 34.7k | : | 328 | 34.7k | #ifdef HAVE_GAS_VMX | 329 | 34.7k | : "m" (addr), | 330 | 34.7k | #else | 331 | | : "a" (&addr), | 332 | | #endif | 333 | 34.7k | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 334 | 34.7k | : "memory"); | 335 | 34.7k | } |
Unexecuted instantiation: vmx.c:__vmptrld Unexecuted instantiation: vvmx.c:__vmptrld Unexecuted instantiation: p2m.c:__vmptrld Unexecuted instantiation: p2m-ept.c:__vmptrld |
336 | | |
337 | | static always_inline void __vmpclear(u64 addr) |
338 | 819 | { |
339 | 819 | asm volatile ( |
340 | 819 | #ifdef HAVE_GAS_VMX |
341 | 819 | "vmclear %0\n" |
342 | 819 | #else |
343 | | VMCLEAR_OPCODE MODRM_EAX_06 |
344 | | #endif |
345 | 819 | /* CF==1 or ZF==1 --> BUG() */ |
346 | 819 | UNLIKELY_START(be, vmclear) |
347 | 819 | _ASM_BUGFRAME_TEXT(0) |
348 | 819 | UNLIKELY_END_SECTION |
349 | 819 | : |
350 | 819 | #ifdef HAVE_GAS_VMX |
351 | 819 | : "m" (addr), |
352 | 819 | #else |
353 | | : "a" (&addr), |
354 | | #endif |
355 | 819 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) |
356 | 819 | : "memory"); |
357 | 819 | } Unexecuted instantiation: iommu.c:__vmpclear Unexecuted instantiation: vpmu.c:__vmpclear Unexecuted instantiation: vpmu_intel.c:__vmpclear Unexecuted instantiation: ioreq.c:__vmpclear Unexecuted instantiation: vlapic.c:__vmpclear Unexecuted instantiation: intr.c:__vmpclear Line | Count | Source | 338 | 819 | { | 339 | 819 | asm volatile ( | 340 | 819 | #ifdef HAVE_GAS_VMX | 341 | 819 | "vmclear %0\n" | 342 | 819 | #else | 343 | | VMCLEAR_OPCODE MODRM_EAX_06 | 344 | | #endif | 345 | 819 | /* CF==1 or ZF==1 --> BUG() */ | 346 | 819 | UNLIKELY_START(be, vmclear) | 347 | 819 | _ASM_BUGFRAME_TEXT(0) | 348 | 819 | UNLIKELY_END_SECTION | 349 | 819 | : | 350 | 819 | #ifdef HAVE_GAS_VMX | 351 | 819 | : "m" (addr), | 352 | 819 | #else | 353 | | : "a" (&addr), | 354 | | #endif | 355 | 819 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 356 | 819 | : "memory"); | 357 | 819 | } |
Unexecuted instantiation: vmx.c:__vmpclear Unexecuted instantiation: vvmx.c:__vmpclear Unexecuted instantiation: p2m.c:__vmpclear Unexecuted instantiation: p2m-ept.c:__vmpclear Unexecuted instantiation: nested_ept.c:__vmpclear Unexecuted instantiation: realmode.c:__vmpclear |
358 | | |
359 | | static always_inline void __vmread(unsigned long field, unsigned long *value) |
360 | 37.0M | { |
361 | 37.0M | asm volatile ( |
362 | 37.0M | #ifdef HAVE_GAS_VMX |
363 | 37.0M | "vmread %1, %0\n\t" |
364 | 37.0M | #else |
365 | | VMREAD_OPCODE MODRM_EAX_ECX |
366 | | #endif |
367 | 37.0M | /* CF==1 or ZF==1 --> BUG() */ |
368 | 37.0M | UNLIKELY_START(be, vmread) |
369 | 37.0M | _ASM_BUGFRAME_TEXT(0) |
370 | 37.0M | UNLIKELY_END_SECTION |
371 | 37.0M | #ifdef HAVE_GAS_VMX |
372 | 37.0M | : "=rm" (*value) |
373 | 37.0M | : "r" (field), |
374 | 37.0M | #else |
375 | | : "=c" (*value) |
376 | | : "a" (field), |
377 | | #endif |
378 | 37.0M | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) |
379 | 37.0M | ); |
380 | 37.0M | } Unexecuted instantiation: iommu.c:__vmread Unexecuted instantiation: vpmu.c:__vmread Unexecuted instantiation: vpmu_intel.c:__vmread Unexecuted instantiation: ioreq.c:__vmread Unexecuted instantiation: vlapic.c:__vmread Line | Count | Source | 360 | 150k | { | 361 | 150k | asm volatile ( | 362 | 150k | #ifdef HAVE_GAS_VMX | 363 | 150k | "vmread %1, %0\n\t" | 364 | 150k | #else | 365 | | VMREAD_OPCODE MODRM_EAX_ECX | 366 | | #endif | 367 | 150k | /* CF==1 or ZF==1 --> BUG() */ | 368 | 150k | UNLIKELY_START(be, vmread) | 369 | 150k | _ASM_BUGFRAME_TEXT(0) | 370 | 150k | UNLIKELY_END_SECTION | 371 | 150k | #ifdef HAVE_GAS_VMX | 372 | 150k | : "=rm" (*value) | 373 | 150k | : "r" (field), | 374 | 150k | #else | 375 | | : "=c" (*value) | 376 | | : "a" (field), | 377 | | #endif | 378 | 150k | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 379 | 150k | ); | 380 | 150k | } |
Unexecuted instantiation: realmode.c:__vmread Unexecuted instantiation: vmcs.c:__vmread Line | Count | Source | 360 | 36.8M | { | 361 | 36.8M | asm volatile ( | 362 | 36.8M | #ifdef HAVE_GAS_VMX | 363 | 36.8M | "vmread %1, %0\n\t" | 364 | 36.8M | #else | 365 | | VMREAD_OPCODE MODRM_EAX_ECX | 366 | | #endif | 367 | 36.8M | /* CF==1 or ZF==1 --> BUG() */ | 368 | 36.8M | UNLIKELY_START(be, vmread) | 369 | 36.8M | _ASM_BUGFRAME_TEXT(0) | 370 | 36.8M | UNLIKELY_END_SECTION | 371 | 36.8M | #ifdef HAVE_GAS_VMX | 372 | 36.8M | : "=rm" (*value) | 373 | 36.8M | : "r" (field), | 374 | 36.8M | #else | 375 | | : "=c" (*value) | 376 | | : "a" (field), | 377 | | #endif | 378 | 36.8M | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 379 | 36.8M | ); | 380 | 36.8M | } |
Unexecuted instantiation: vvmx.c:__vmread Unexecuted instantiation: p2m.c:__vmread Unexecuted instantiation: p2m-ept.c:__vmread Unexecuted instantiation: nested_ept.c:__vmread |
381 | | |
382 | | static always_inline void __vmwrite(unsigned long field, unsigned long value) |
383 | 16.0M | { |
384 | 16.0M | asm volatile ( |
385 | 16.0M | #ifdef HAVE_GAS_VMX |
386 | 16.0M | "vmwrite %1, %0\n" |
387 | 16.0M | #else |
388 | | VMWRITE_OPCODE MODRM_EAX_ECX |
389 | | #endif |
390 | 16.0M | /* CF==1 or ZF==1 --> BUG() */ |
391 | 16.0M | UNLIKELY_START(be, vmwrite) |
392 | 16.0M | _ASM_BUGFRAME_TEXT(0) |
393 | 16.0M | UNLIKELY_END_SECTION |
394 | 16.0M | : |
395 | 16.0M | #ifdef HAVE_GAS_VMX |
396 | 16.0M | : "r" (field) , "rm" (value), |
397 | 16.0M | #else |
398 | | : "a" (field) , "c" (value), |
399 | | #endif |
400 | 16.0M | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) |
401 | 16.0M | ); |
402 | 16.0M | } Unexecuted instantiation: vpmu.c:__vmwrite Unexecuted instantiation: vpmu_intel.c:__vmwrite Unexecuted instantiation: ioreq.c:__vmwrite Unexecuted instantiation: vlapic.c:__vmwrite Line | Count | Source | 383 | 4.21k | { | 384 | 4.21k | asm volatile ( | 385 | 4.21k | #ifdef HAVE_GAS_VMX | 386 | 4.21k | "vmwrite %1, %0\n" | 387 | 4.21k | #else | 388 | | VMWRITE_OPCODE MODRM_EAX_ECX | 389 | | #endif | 390 | 4.21k | /* CF==1 or ZF==1 --> BUG() */ | 391 | 4.21k | UNLIKELY_START(be, vmwrite) | 392 | 4.21k | _ASM_BUGFRAME_TEXT(0) | 393 | 4.21k | UNLIKELY_END_SECTION | 394 | 4.21k | : | 395 | 4.21k | #ifdef HAVE_GAS_VMX | 396 | 4.21k | : "r" (field) , "rm" (value), | 397 | 4.21k | #else | 398 | | : "a" (field) , "c" (value), | 399 | | #endif | 400 | 4.21k | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 401 | 4.21k | ); | 402 | 4.21k | } |
Unexecuted instantiation: realmode.c:__vmwrite Line | Count | Source | 383 | 4.20k | { | 384 | 4.20k | asm volatile ( | 385 | 4.20k | #ifdef HAVE_GAS_VMX | 386 | 4.20k | "vmwrite %1, %0\n" | 387 | 4.20k | #else | 388 | | VMWRITE_OPCODE MODRM_EAX_ECX | 389 | | #endif | 390 | 4.20k | /* CF==1 or ZF==1 --> BUG() */ | 391 | 4.20k | UNLIKELY_START(be, vmwrite) | 392 | 4.20k | _ASM_BUGFRAME_TEXT(0) | 393 | 4.20k | UNLIKELY_END_SECTION | 394 | 4.20k | : | 395 | 4.20k | #ifdef HAVE_GAS_VMX | 396 | 4.20k | : "r" (field) , "rm" (value), | 397 | 4.20k | #else | 398 | | : "a" (field) , "c" (value), | 399 | | #endif | 400 | 4.20k | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 401 | 4.20k | ); | 402 | 4.20k | } |
Line | Count | Source | 383 | 15.9M | { | 384 | 15.9M | asm volatile ( | 385 | 15.9M | #ifdef HAVE_GAS_VMX | 386 | 15.9M | "vmwrite %1, %0\n" | 387 | 15.9M | #else | 388 | | VMWRITE_OPCODE MODRM_EAX_ECX | 389 | | #endif | 390 | 15.9M | /* CF==1 or ZF==1 --> BUG() */ | 391 | 15.9M | UNLIKELY_START(be, vmwrite) | 392 | 15.9M | _ASM_BUGFRAME_TEXT(0) | 393 | 15.9M | UNLIKELY_END_SECTION | 394 | 15.9M | : | 395 | 15.9M | #ifdef HAVE_GAS_VMX | 396 | 15.9M | : "r" (field) , "rm" (value), | 397 | 15.9M | #else | 398 | | : "a" (field) , "c" (value), | 399 | | #endif | 400 | 15.9M | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 401 | 15.9M | ); | 402 | 15.9M | } |
Unexecuted instantiation: vvmx.c:__vmwrite Unexecuted instantiation: p2m.c:__vmwrite Unexecuted instantiation: p2m-ept.c:__vmwrite Unexecuted instantiation: nested_ept.c:__vmwrite Unexecuted instantiation: iommu.c:__vmwrite |
403 | | |
404 | | static inline enum vmx_insn_errno vmread_safe(unsigned long field, |
405 | | unsigned long *value) |
406 | 0 | { |
407 | 0 | unsigned long ret = VMX_INSN_SUCCEED; |
408 | 0 | bool fail_invalid, fail_valid; |
409 | 0 |
|
410 | 0 | asm volatile ( GAS_VMX_OP("vmread %[field], %[value]\n\t", |
411 | 0 | VMREAD_OPCODE MODRM_EAX_ECX) |
412 | 0 | ASM_FLAG_OUT(, "setc %[invalid]\n\t") |
413 | 0 | ASM_FLAG_OUT(, "setz %[valid]\n\t") |
414 | 0 | : ASM_FLAG_OUT("=@ccc", [invalid] "=rm") (fail_invalid), |
415 | 0 | ASM_FLAG_OUT("=@ccz", [valid] "=rm") (fail_valid), |
416 | 0 | [value] GAS_VMX_OP("=rm", "=c") (*value) |
417 | 0 | : [field] GAS_VMX_OP("r", "a") (field)); |
418 | 0 |
|
419 | 0 | if ( unlikely(fail_invalid) ) |
420 | 0 | ret = VMX_INSN_FAIL_INVALID; |
421 | 0 | else if ( unlikely(fail_valid) ) |
422 | 0 | __vmread(VM_INSTRUCTION_ERROR, &ret); |
423 | 0 |
|
424 | 0 | return ret; |
425 | 0 | } Unexecuted instantiation: vpmu.c:vmread_safe Unexecuted instantiation: vpmu_intel.c:vmread_safe Unexecuted instantiation: ioreq.c:vmread_safe Unexecuted instantiation: vlapic.c:vmread_safe Unexecuted instantiation: intr.c:vmread_safe Unexecuted instantiation: realmode.c:vmread_safe Unexecuted instantiation: vmcs.c:vmread_safe Unexecuted instantiation: vmx.c:vmread_safe Unexecuted instantiation: vvmx.c:vmread_safe Unexecuted instantiation: p2m.c:vmread_safe Unexecuted instantiation: p2m-ept.c:vmread_safe Unexecuted instantiation: nested_ept.c:vmread_safe Unexecuted instantiation: iommu.c:vmread_safe |
426 | | |
427 | | static inline enum vmx_insn_errno vmwrite_safe(unsigned long field, |
428 | | unsigned long value) |
429 | 0 | { |
430 | 0 | unsigned long ret = VMX_INSN_SUCCEED; |
431 | 0 | bool fail_invalid, fail_valid; |
432 | 0 |
|
433 | 0 | asm volatile ( GAS_VMX_OP("vmwrite %[value], %[field]\n\t", |
434 | 0 | VMWRITE_OPCODE MODRM_EAX_ECX) |
435 | 0 | ASM_FLAG_OUT(, "setc %[invalid]\n\t") |
436 | 0 | ASM_FLAG_OUT(, "setz %[valid]\n\t") |
437 | 0 | : ASM_FLAG_OUT("=@ccc", [invalid] "=rm") (fail_invalid), |
438 | 0 | ASM_FLAG_OUT("=@ccz", [valid] "=rm") (fail_valid) |
439 | 0 | : [field] GAS_VMX_OP("r", "a") (field), |
440 | 0 | [value] GAS_VMX_OP("rm", "c") (value)); |
441 | 0 |
|
442 | 0 | if ( unlikely(fail_invalid) ) |
443 | 0 | ret = VMX_INSN_FAIL_INVALID; |
444 | 0 | else if ( unlikely(fail_valid) ) |
445 | 0 | __vmread(VM_INSTRUCTION_ERROR, &ret); |
446 | 0 |
|
447 | 0 | return ret; |
448 | 0 | } Unexecuted instantiation: nested_ept.c:vmwrite_safe Unexecuted instantiation: iommu.c:vmwrite_safe Unexecuted instantiation: p2m-ept.c:vmwrite_safe Unexecuted instantiation: p2m.c:vmwrite_safe Unexecuted instantiation: vvmx.c:vmwrite_safe Unexecuted instantiation: vmx.c:vmwrite_safe Unexecuted instantiation: vmcs.c:vmwrite_safe Unexecuted instantiation: realmode.c:vmwrite_safe Unexecuted instantiation: intr.c:vmwrite_safe Unexecuted instantiation: vlapic.c:vmwrite_safe Unexecuted instantiation: ioreq.c:vmwrite_safe Unexecuted instantiation: vpmu_intel.c:vmwrite_safe Unexecuted instantiation: vpmu.c:vmwrite_safe |
449 | | |
450 | | static always_inline void __invept(unsigned long type, u64 eptp, u64 gpa) |
451 | 423 | { |
452 | 423 | struct { |
453 | 423 | u64 eptp, gpa; |
454 | 423 | } operand = {eptp, gpa}; |
455 | 423 | |
456 | 423 | /* |
457 | 423 | * If single context invalidation is not supported, we escalate to |
458 | 423 | * use all context invalidation. |
459 | 423 | */ |
460 | 423 | if ( (type == INVEPT_SINGLE_CONTEXT) && |
461 | 411 | !cpu_has_vmx_ept_invept_single_context ) |
462 | 0 | type = INVEPT_ALL_CONTEXT; |
463 | 423 | |
464 | 423 | asm volatile ( |
465 | 423 | #ifdef HAVE_GAS_EPT |
466 | 423 | "invept %0, %1\n" |
467 | 423 | #else |
468 | | INVEPT_OPCODE MODRM_EAX_08 |
469 | | #endif |
470 | 423 | /* CF==1 or ZF==1 --> BUG() */ |
471 | 423 | UNLIKELY_START(be, invept) |
472 | 423 | _ASM_BUGFRAME_TEXT(0) |
473 | 423 | UNLIKELY_END_SECTION |
474 | 423 | : |
475 | 423 | #ifdef HAVE_GAS_EPT |
476 | 423 | : "m" (operand), "r" (type), |
477 | 423 | #else |
478 | | : "a" (&operand), "c" (type), |
479 | | #endif |
480 | 423 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) |
481 | 423 | : "memory" ); |
482 | 423 | } Unexecuted instantiation: realmode.c:__invept Unexecuted instantiation: iommu.c:__invept Unexecuted instantiation: vpmu.c:__invept Unexecuted instantiation: vpmu_intel.c:__invept Unexecuted instantiation: ioreq.c:__invept Unexecuted instantiation: vlapic.c:__invept Unexecuted instantiation: intr.c:__invept Unexecuted instantiation: nested_ept.c:__invept Line | Count | Source | 451 | 12 | { | 452 | 12 | struct { | 453 | 12 | u64 eptp, gpa; | 454 | 12 | } operand = {eptp, gpa}; | 455 | 12 | | 456 | 12 | /* | 457 | 12 | * If single context invalidation is not supported, we escalate to | 458 | 12 | * use all context invalidation. | 459 | 12 | */ | 460 | 12 | if ( (type == INVEPT_SINGLE_CONTEXT) && | 461 | 0 | !cpu_has_vmx_ept_invept_single_context ) | 462 | 0 | type = INVEPT_ALL_CONTEXT; | 463 | 12 | | 464 | 12 | asm volatile ( | 465 | 12 | #ifdef HAVE_GAS_EPT | 466 | 12 | "invept %0, %1\n" | 467 | 12 | #else | 468 | | INVEPT_OPCODE MODRM_EAX_08 | 469 | | #endif | 470 | 12 | /* CF==1 or ZF==1 --> BUG() */ | 471 | 12 | UNLIKELY_START(be, invept) | 472 | 12 | _ASM_BUGFRAME_TEXT(0) | 473 | 12 | UNLIKELY_END_SECTION | 474 | 12 | : | 475 | 12 | #ifdef HAVE_GAS_EPT | 476 | 12 | : "m" (operand), "r" (type), | 477 | 12 | #else | 478 | | : "a" (&operand), "c" (type), | 479 | | #endif | 480 | 12 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 481 | 12 | : "memory" ); | 482 | 12 | } |
Line | Count | Source | 451 | 411 | { | 452 | 411 | struct { | 453 | 411 | u64 eptp, gpa; | 454 | 411 | } operand = {eptp, gpa}; | 455 | 411 | | 456 | 411 | /* | 457 | 411 | * If single context invalidation is not supported, we escalate to | 458 | 411 | * use all context invalidation. | 459 | 411 | */ | 460 | 411 | if ( (type == INVEPT_SINGLE_CONTEXT) && | 461 | 411 | !cpu_has_vmx_ept_invept_single_context ) | 462 | 0 | type = INVEPT_ALL_CONTEXT; | 463 | 411 | | 464 | 411 | asm volatile ( | 465 | 411 | #ifdef HAVE_GAS_EPT | 466 | 411 | "invept %0, %1\n" | 467 | 411 | #else | 468 | | INVEPT_OPCODE MODRM_EAX_08 | 469 | | #endif | 470 | 411 | /* CF==1 or ZF==1 --> BUG() */ | 471 | 411 | UNLIKELY_START(be, invept) | 472 | 411 | _ASM_BUGFRAME_TEXT(0) | 473 | 411 | UNLIKELY_END_SECTION | 474 | 411 | : | 475 | 411 | #ifdef HAVE_GAS_EPT | 476 | 411 | : "m" (operand), "r" (type), | 477 | 411 | #else | 478 | | : "a" (&operand), "c" (type), | 479 | | #endif | 480 | 411 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 481 | 411 | : "memory" ); | 482 | 411 | } |
Unexecuted instantiation: vvmx.c:__invept Unexecuted instantiation: p2m.c:__invept Unexecuted instantiation: p2m-ept.c:__invept |
483 | | |
484 | | static always_inline void __invvpid(unsigned long type, u16 vpid, u64 gva) |
485 | 24 | { |
486 | 24 | struct __packed { |
487 | 24 | u64 vpid:16; |
488 | 24 | u64 rsvd:48; |
489 | 24 | u64 gva; |
490 | 24 | } operand = {vpid, 0, gva}; |
491 | 24 | |
492 | 24 | /* Fix up #UD exceptions which occur when TLBs are flushed before VMXON. */ |
493 | 24 | asm volatile ( "1: " |
494 | 24 | #ifdef HAVE_GAS_EPT |
495 | 24 | "invvpid %0, %1\n" |
496 | 24 | #else |
497 | | INVVPID_OPCODE MODRM_EAX_08 |
498 | | #endif |
499 | 24 | /* CF==1 or ZF==1 --> BUG() */ |
500 | 24 | UNLIKELY_START(be, invvpid) |
501 | 24 | _ASM_BUGFRAME_TEXT(0) |
502 | 24 | UNLIKELY_END_SECTION "\n" |
503 | 24 | "2:" |
504 | 24 | _ASM_EXTABLE(1b, 2b) |
505 | 24 | : |
506 | 24 | #ifdef HAVE_GAS_EPT |
507 | 24 | : "m" (operand), "r" (type), |
508 | 24 | #else |
509 | | : "a" (&operand), "c" (type), |
510 | | #endif |
511 | 24 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) |
512 | 24 | : "memory" ); |
513 | 24 | } Unexecuted instantiation: iommu.c:__invvpid Unexecuted instantiation: vpmu.c:__invvpid Unexecuted instantiation: vpmu_intel.c:__invvpid Unexecuted instantiation: ioreq.c:__invvpid Unexecuted instantiation: vlapic.c:__invvpid Unexecuted instantiation: intr.c:__invvpid Unexecuted instantiation: realmode.c:__invvpid Line | Count | Source | 485 | 12 | { | 486 | 12 | struct __packed { | 487 | 12 | u64 vpid:16; | 488 | 12 | u64 rsvd:48; | 489 | 12 | u64 gva; | 490 | 12 | } operand = {vpid, 0, gva}; | 491 | 12 | | 492 | 12 | /* Fix up #UD exceptions which occur when TLBs are flushed before VMXON. */ | 493 | 12 | asm volatile ( "1: " | 494 | 12 | #ifdef HAVE_GAS_EPT | 495 | 12 | "invvpid %0, %1\n" | 496 | 12 | #else | 497 | | INVVPID_OPCODE MODRM_EAX_08 | 498 | | #endif | 499 | 12 | /* CF==1 or ZF==1 --> BUG() */ | 500 | 12 | UNLIKELY_START(be, invvpid) | 501 | 12 | _ASM_BUGFRAME_TEXT(0) | 502 | 12 | UNLIKELY_END_SECTION "\n" | 503 | 12 | "2:" | 504 | 12 | _ASM_EXTABLE(1b, 2b) | 505 | 12 | : | 506 | 12 | #ifdef HAVE_GAS_EPT | 507 | 12 | : "m" (operand), "r" (type), | 508 | 12 | #else | 509 | | : "a" (&operand), "c" (type), | 510 | | #endif | 511 | 12 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 512 | 12 | : "memory" ); | 513 | 12 | } |
Line | Count | Source | 485 | 12 | { | 486 | 12 | struct __packed { | 487 | 12 | u64 vpid:16; | 488 | 12 | u64 rsvd:48; | 489 | 12 | u64 gva; | 490 | 12 | } operand = {vpid, 0, gva}; | 491 | 12 | | 492 | 12 | /* Fix up #UD exceptions which occur when TLBs are flushed before VMXON. */ | 493 | 12 | asm volatile ( "1: " | 494 | 12 | #ifdef HAVE_GAS_EPT | 495 | 12 | "invvpid %0, %1\n" | 496 | 12 | #else | 497 | | INVVPID_OPCODE MODRM_EAX_08 | 498 | | #endif | 499 | 12 | /* CF==1 or ZF==1 --> BUG() */ | 500 | 12 | UNLIKELY_START(be, invvpid) | 501 | 12 | _ASM_BUGFRAME_TEXT(0) | 502 | 12 | UNLIKELY_END_SECTION "\n" | 503 | 12 | "2:" | 504 | 12 | _ASM_EXTABLE(1b, 2b) | 505 | 12 | : | 506 | 12 | #ifdef HAVE_GAS_EPT | 507 | 12 | : "m" (operand), "r" (type), | 508 | 12 | #else | 509 | | : "a" (&operand), "c" (type), | 510 | | #endif | 511 | 12 | _ASM_BUGFRAME_INFO(BUGFRAME_bug, __LINE__, __FILE__, 0) | 512 | 12 | : "memory" ); | 513 | 12 | } |
Unexecuted instantiation: vvmx.c:__invvpid Unexecuted instantiation: p2m.c:__invvpid Unexecuted instantiation: p2m-ept.c:__invvpid Unexecuted instantiation: nested_ept.c:__invvpid |
514 | | |
515 | | static inline void ept_sync_all(void) |
516 | 12 | { |
517 | 12 | __invept(INVEPT_ALL_CONTEXT, 0, 0); |
518 | 12 | } Unexecuted instantiation: iommu.c:ept_sync_all Unexecuted instantiation: nested_ept.c:ept_sync_all Unexecuted instantiation: p2m-ept.c:ept_sync_all Unexecuted instantiation: p2m.c:ept_sync_all Unexecuted instantiation: vvmx.c:ept_sync_all Unexecuted instantiation: vmx.c:ept_sync_all Line | Count | Source | 516 | 12 | { | 517 | 12 | __invept(INVEPT_ALL_CONTEXT, 0, 0); | 518 | 12 | } |
Unexecuted instantiation: realmode.c:ept_sync_all Unexecuted instantiation: intr.c:ept_sync_all Unexecuted instantiation: vlapic.c:ept_sync_all Unexecuted instantiation: ioreq.c:ept_sync_all Unexecuted instantiation: vpmu_intel.c:ept_sync_all Unexecuted instantiation: vpmu.c:ept_sync_all |
519 | | |
520 | | void ept_sync_domain(struct p2m_domain *p2m); |
521 | | |
522 | | static inline void vpid_sync_vcpu_gva(struct vcpu *v, unsigned long gva) |
523 | 0 | { |
524 | 0 | int type = INVVPID_INDIVIDUAL_ADDR; |
525 | 0 |
|
526 | 0 | /* |
527 | 0 | * If individual address invalidation is not supported, we escalate to |
528 | 0 | * use single context invalidation. |
529 | 0 | */ |
530 | 0 | if ( likely(cpu_has_vmx_vpid_invvpid_individual_addr) ) |
531 | 0 | goto execute_invvpid; |
532 | 0 |
|
533 | 0 | type = INVVPID_SINGLE_CONTEXT; |
534 | 0 |
|
535 | 0 | /* |
536 | 0 | * If single context invalidation is not supported, we escalate to |
537 | 0 | * use all context invalidation. |
538 | 0 | */ |
539 | 0 | if ( !cpu_has_vmx_vpid_invvpid_single_context ) |
540 | 0 | type = INVVPID_ALL_CONTEXT; |
541 | 0 |
|
542 | 0 | execute_invvpid: |
543 | 0 | __invvpid(type, v->arch.hvm_vcpu.n1asid.asid, (u64)gva); |
544 | 0 | } Unexecuted instantiation: vpmu.c:vpid_sync_vcpu_gva Unexecuted instantiation: p2m-ept.c:vpid_sync_vcpu_gva Unexecuted instantiation: p2m.c:vpid_sync_vcpu_gva Unexecuted instantiation: vvmx.c:vpid_sync_vcpu_gva Unexecuted instantiation: vmx.c:vpid_sync_vcpu_gva Unexecuted instantiation: vmcs.c:vpid_sync_vcpu_gva Unexecuted instantiation: realmode.c:vpid_sync_vcpu_gva Unexecuted instantiation: nested_ept.c:vpid_sync_vcpu_gva Unexecuted instantiation: intr.c:vpid_sync_vcpu_gva Unexecuted instantiation: vlapic.c:vpid_sync_vcpu_gva Unexecuted instantiation: ioreq.c:vpid_sync_vcpu_gva Unexecuted instantiation: vpmu_intel.c:vpid_sync_vcpu_gva Unexecuted instantiation: iommu.c:vpid_sync_vcpu_gva |
545 | | |
546 | | static inline void vpid_sync_all(void) |
547 | 24 | { |
548 | 24 | __invvpid(INVVPID_ALL_CONTEXT, 0, 0); |
549 | 24 | } Unexecuted instantiation: iommu.c:vpid_sync_all Unexecuted instantiation: vpmu.c:vpid_sync_all Unexecuted instantiation: vpmu_intel.c:vpid_sync_all Unexecuted instantiation: ioreq.c:vpid_sync_all Unexecuted instantiation: vlapic.c:vpid_sync_all Unexecuted instantiation: intr.c:vpid_sync_all Line | Count | Source | 547 | 12 | { | 548 | 12 | __invvpid(INVVPID_ALL_CONTEXT, 0, 0); | 549 | 12 | } |
Line | Count | Source | 547 | 12 | { | 548 | 12 | __invvpid(INVVPID_ALL_CONTEXT, 0, 0); | 549 | 12 | } |
Unexecuted instantiation: vvmx.c:vpid_sync_all Unexecuted instantiation: p2m.c:vpid_sync_all Unexecuted instantiation: p2m-ept.c:vpid_sync_all Unexecuted instantiation: nested_ept.c:vpid_sync_all Unexecuted instantiation: realmode.c:vpid_sync_all |
550 | | |
551 | | static inline void __vmxoff(void) |
552 | 0 | { |
553 | 0 | asm volatile ( |
554 | 0 | VMXOFF_OPCODE |
555 | 0 | : : : "memory" ); |
556 | 0 | } Unexecuted instantiation: vpmu.c:__vmxoff Unexecuted instantiation: vpmu_intel.c:__vmxoff Unexecuted instantiation: ioreq.c:__vmxoff Unexecuted instantiation: vlapic.c:__vmxoff Unexecuted instantiation: intr.c:__vmxoff Unexecuted instantiation: realmode.c:__vmxoff Unexecuted instantiation: vmcs.c:__vmxoff Unexecuted instantiation: vmx.c:__vmxoff Unexecuted instantiation: vvmx.c:__vmxoff Unexecuted instantiation: p2m.c:__vmxoff Unexecuted instantiation: p2m-ept.c:__vmxoff Unexecuted instantiation: nested_ept.c:__vmxoff Unexecuted instantiation: iommu.c:__vmxoff |
557 | | |
558 | | static inline int __vmxon(u64 addr) |
559 | 12 | { |
560 | 12 | int rc; |
561 | 12 | |
562 | 12 | asm volatile ( |
563 | 12 | "1: " VMXON_OPCODE MODRM_EAX_06 "\n" |
564 | 12 | " setna %b0 ; neg %0\n" /* CF==1 or ZF==1 --> rc = -1 */ |
565 | 12 | "2:\n" |
566 | 12 | ".section .fixup,\"ax\"\n" |
567 | 12 | "3: sub $2,%0 ; jmp 2b\n" /* #UD or #GP --> rc = -2 */ |
568 | 12 | ".previous\n" |
569 | 12 | _ASM_EXTABLE(1b, 3b) |
570 | 12 | : "=q" (rc) |
571 | 12 | : "0" (0), "a" (&addr) |
572 | 12 | : "memory"); |
573 | 12 | |
574 | 12 | return rc; |
575 | 12 | } Unexecuted instantiation: iommu.c:__vmxon Unexecuted instantiation: nested_ept.c:__vmxon Unexecuted instantiation: p2m-ept.c:__vmxon Unexecuted instantiation: p2m.c:__vmxon Unexecuted instantiation: vvmx.c:__vmxon Unexecuted instantiation: vmx.c:__vmxon Line | Count | Source | 559 | 12 | { | 560 | 12 | int rc; | 561 | 12 | | 562 | 12 | asm volatile ( | 563 | 12 | "1: " VMXON_OPCODE MODRM_EAX_06 "\n" | 564 | 12 | " setna %b0 ; neg %0\n" /* CF==1 or ZF==1 --> rc = -1 */ | 565 | 12 | "2:\n" | 566 | 12 | ".section .fixup,\"ax\"\n" | 567 | 12 | "3: sub $2,%0 ; jmp 2b\n" /* #UD or #GP --> rc = -2 */ | 568 | 12 | ".previous\n" | 569 | 12 | _ASM_EXTABLE(1b, 3b) | 570 | 12 | : "=q" (rc) | 571 | 12 | : "0" (0), "a" (&addr) | 572 | 12 | : "memory"); | 573 | 12 | | 574 | 12 | return rc; | 575 | 12 | } |
Unexecuted instantiation: realmode.c:__vmxon Unexecuted instantiation: intr.c:__vmxon Unexecuted instantiation: vlapic.c:__vmxon Unexecuted instantiation: ioreq.c:__vmxon Unexecuted instantiation: vpmu_intel.c:__vmxon Unexecuted instantiation: vpmu.c:__vmxon |
576 | | |
577 | | int vmx_guest_x86_mode(struct vcpu *v); |
578 | | unsigned int vmx_get_cpl(void); |
579 | | |
580 | | void vmx_inject_extint(int trap, uint8_t source); |
581 | | void vmx_inject_nmi(void); |
582 | | |
583 | | int ept_p2m_init(struct p2m_domain *p2m); |
584 | | void ept_p2m_uninit(struct p2m_domain *p2m); |
585 | | |
586 | | void ept_walk_table(struct domain *d, unsigned long gfn); |
587 | | bool_t ept_handle_misconfig(uint64_t gpa); |
588 | | void setup_ept_dump(void); |
589 | | void p2m_init_altp2m_ept(struct domain *d, unsigned int i); |
590 | | /* Locate an alternate p2m by its EPTP */ |
591 | | unsigned int p2m_find_altp2m_by_eptp(struct domain *d, uint64_t eptp); |
592 | | |
593 | | void update_guest_eip(void); |
594 | | |
595 | | int alloc_p2m_hap_data(struct p2m_domain *p2m); |
596 | | void free_p2m_hap_data(struct p2m_domain *p2m); |
597 | | void p2m_init_hap_data(struct p2m_domain *p2m); |
598 | | |
599 | | void vmx_pi_per_cpu_init(unsigned int cpu); |
600 | | void vmx_pi_desc_fixup(unsigned int cpu); |
601 | | |
602 | | void vmx_pi_hooks_assign(struct domain *d); |
603 | | void vmx_pi_hooks_deassign(struct domain *d); |
604 | | |
605 | 0 | #define APIC_INVALID_DEST 0xffffffff |
606 | | |
607 | | /* EPT violation qualifications definitions */ |
608 | | typedef union ept_qual { |
609 | | unsigned long raw; |
610 | | struct { |
611 | | bool read:1, write:1, fetch:1, |
612 | | eff_read:1, eff_write:1, eff_exec:1, /* eff_user_exec */:1, |
613 | | gla_valid:1, |
614 | | gla_fault:1; /* Valid iff gla_valid. */ |
615 | | unsigned long /* pad */:55; |
616 | | }; |
617 | | } __transparent__ ept_qual_t; |
618 | | |
619 | 0 | #define EPT_L4_PAGETABLE_SHIFT 39 |
620 | 7.01M | #define EPT_PAGETABLE_ENTRIES 512 |
621 | | |
622 | | /* #VE information page */ |
623 | | typedef struct { |
624 | | u32 exit_reason; |
625 | | u32 semaphore; |
626 | | u64 exit_qualification; |
627 | | u64 gla; |
628 | | u64 gpa; |
629 | | u16 eptp_index; |
630 | | } ve_info_t; |
631 | | |
632 | | /* VM-Exit instruction info for LIDT, LGDT, SIDT, SGDT */ |
633 | | typedef union idt_or_gdt_instr_info { |
634 | | unsigned long raw; |
635 | | struct { |
636 | | unsigned long scaling :2, /* bits 0:1 - Scaling */ |
637 | | :5, /* bits 6:2 - Undefined */ |
638 | | addr_size :3, /* bits 9:7 - Address size */ |
639 | | :1, /* bit 10 - Cleared to 0 */ |
640 | | operand_size :1, /* bit 11 - Operand size */ |
641 | | :3, /* bits 14:12 - Undefined */ |
642 | | segment_reg :3, /* bits 17:15 - Segment register */ |
643 | | index_reg :4, /* bits 21:18 - Index register */ |
644 | | index_reg_invalid :1, /* bit 22 - Index register invalid */ |
645 | | base_reg :4, /* bits 26:23 - Base register */ |
646 | | base_reg_invalid :1, /* bit 27 - Base register invalid */ |
647 | | instr_identity :1, /* bit 28 - 0:GDT, 1:IDT */ |
648 | | instr_write :1, /* bit 29 - 0:store, 1:load */ |
649 | | :34; /* bits 30:63 - Undefined */ |
650 | | }; |
651 | | } idt_or_gdt_instr_info_t; |
652 | | |
653 | | /* VM-Exit instruction info for LLDT, LTR, SLDT, STR */ |
654 | | typedef union ldt_or_tr_instr_info { |
655 | | unsigned long raw; |
656 | | struct { |
657 | | unsigned long scaling :2, /* bits 0:1 - Scaling */ |
658 | | :1, /* bit 2 - Undefined */ |
659 | | reg1 :4, /* bits 6:3 - Reg1 */ |
660 | | addr_size :3, /* bits 9:7 - Address size */ |
661 | | mem_reg :1, /* bit 10 - Mem/Reg */ |
662 | | :4, /* bits 14:11 - Undefined */ |
663 | | segment_reg :3, /* bits 17:15 - Segment register */ |
664 | | index_reg :4, /* bits 21:18 - Index register */ |
665 | | index_reg_invalid :1, /* bit 22 - Index register invalid */ |
666 | | base_reg :4, /* bits 26:23 - Base register */ |
667 | | base_reg_invalid :1, /* bit 27 - Base register invalid */ |
668 | | instr_identity :1, /* bit 28 - 0:LDT, 1:TR */ |
669 | | instr_write :1, /* bit 29 - 0:store, 1:load */ |
670 | | :34; /* bits 31:63 - Undefined */ |
671 | | }; |
672 | | } ldt_or_tr_instr_info_t; |
673 | | |
674 | | #endif /* __ASM_X86_HVM_VMX_VMX_H__ */ |