/root/src/xen/xen/include/asm/hvm/vmx/vvmx.h
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /* |
3 | | * vvmx.h: Support virtual VMX for nested virtualization. |
4 | | * |
5 | | * Copyright (c) 2010, Intel Corporation. |
6 | | * Author: Qing He <qing.he@intel.com> |
7 | | * Eddie Dong <eddie.dong@intel.com> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms and conditions of the GNU General Public License, |
11 | | * version 2, as published by the Free Software Foundation. |
12 | | * |
13 | | * This program is distributed in the hope it will be useful, but WITHOUT |
14 | | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
15 | | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
16 | | * more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License along with |
19 | | * this program; If not, see <http://www.gnu.org/licenses/>. |
20 | | * |
21 | | */ |
22 | | #ifndef __ASM_X86_HVM_VVMX_H__ |
23 | | #define __ASM_X86_HVM_VVMX_H__ |
24 | | |
25 | | struct vvmcs_list { |
26 | | unsigned long vvmcs_mfn; |
27 | | struct list_head node; |
28 | | }; |
29 | | |
30 | | struct nestedvmx { |
31 | | /* |
32 | | * vmxon_region_pa is also used to indicate whether a vcpu is in |
33 | | * the VMX operation. When a vcpu is out of the VMX operation, its |
34 | | * vmxon_region_pa is set to an invalid address INVALID_PADDR. We |
35 | | * cannot use 0 for this purpose, because it's a valid VMXON region |
36 | | * address. |
37 | | */ |
38 | | paddr_t vmxon_region_pa; |
39 | | void *iobitmap[2]; /* map (va) of L1 guest I/O bitmap */ |
40 | | void *msrbitmap; /* map (va) of L1 guest MSR bitmap */ |
41 | | /* deferred nested interrupt */ |
42 | | struct { |
43 | | unsigned long intr_info; |
44 | | u32 error_code; |
45 | | u8 source; |
46 | | } intr; |
47 | | struct { |
48 | | bool_t enabled; |
49 | | uint32_t exit_reason; |
50 | | uint32_t exit_qual; |
51 | | } ept; |
52 | | uint32_t guest_vpid; |
53 | | struct list_head launched_list; |
54 | | }; |
55 | | |
56 | 0 | #define vcpu_2_nvmx(v) (vcpu_nestedhvm(v).u.nvmx) |
57 | | |
58 | | /* bit 1, 2, 4 must be 1 */ |
59 | | #define VMX_PINBASED_CTLS_DEFAULT1 0x16 |
60 | | /* bit 1, 4-6,8,13-16,26 must be 1 */ |
61 | 0 | #define VMX_PROCBASED_CTLS_DEFAULT1 0x401e172 |
62 | | /* bit 0-8, 10,11,13,14,16,17 must be 1 */ |
63 | | #define VMX_EXIT_CTLS_DEFAULT1 0x36dff |
64 | | /* bit 0-8, and 12 must be 1 */ |
65 | | #define VMX_ENTRY_CTLS_DEFAULT1 0x11ff |
66 | | |
67 | | /* |
68 | | * Encode of VMX instructions base on Table 24-11 & 24-12 of SDM 3B |
69 | | */ |
70 | | |
71 | | enum vmx_regs_enc { |
72 | | VMX_REG_RAX, |
73 | | VMX_REG_RCX, |
74 | | VMX_REG_RDX, |
75 | | VMX_REG_RBX, |
76 | | VMX_REG_RSP, |
77 | | VMX_REG_RBP, |
78 | | VMX_REG_RSI, |
79 | | VMX_REG_RDI, |
80 | | VMX_REG_R8, |
81 | | VMX_REG_R9, |
82 | | VMX_REG_R10, |
83 | | VMX_REG_R11, |
84 | | VMX_REG_R12, |
85 | | VMX_REG_R13, |
86 | | VMX_REG_R14, |
87 | | VMX_REG_R15, |
88 | | }; |
89 | | |
90 | | union vmx_inst_info { |
91 | | struct { |
92 | | unsigned int scaling :2; /* bit 0-1 */ |
93 | | unsigned int __rsvd0 :1; /* bit 2 */ |
94 | | unsigned int reg1 :4; /* bit 3-6 */ |
95 | | unsigned int addr_size :3; /* bit 7-9 */ |
96 | | unsigned int memreg :1; /* bit 10 */ |
97 | | unsigned int __rsvd1 :4; /* bit 11-14 */ |
98 | | unsigned int segment :3; /* bit 15-17 */ |
99 | | unsigned int index_reg :4; /* bit 18-21 */ |
100 | | unsigned int index_reg_invalid :1; /* bit 22 */ |
101 | | unsigned int base_reg :4; /* bit 23-26 */ |
102 | | unsigned int base_reg_invalid :1; /* bit 27 */ |
103 | | unsigned int reg2 :4; /* bit 28-31 */ |
104 | | } fields; |
105 | | u32 word; |
106 | | }; |
107 | | |
108 | | int nvmx_vcpu_initialise(struct vcpu *v); |
109 | | void nvmx_vcpu_destroy(struct vcpu *v); |
110 | | int nvmx_vcpu_reset(struct vcpu *v); |
111 | | uint64_t nvmx_vcpu_eptp_base(struct vcpu *v); |
112 | | enum hvm_intblk nvmx_intr_blocked(struct vcpu *v); |
113 | | bool_t nvmx_intercepts_exception( |
114 | | struct vcpu *v, unsigned int vector, int error_code); |
115 | | void nvmx_domain_relinquish_resources(struct domain *d); |
116 | | |
117 | | bool_t nvmx_ept_enabled(struct vcpu *v); |
118 | | |
119 | | int nvmx_handle_vmxon(struct cpu_user_regs *regs); |
120 | | int nvmx_handle_vmxoff(struct cpu_user_regs *regs); |
121 | | |
122 | 0 | #define EPT_TRANSLATE_SUCCEED 0 |
123 | 0 | #define EPT_TRANSLATE_VIOLATION 1 |
124 | 0 | #define EPT_TRANSLATE_MISCONFIG 2 |
125 | 0 | #define EPT_TRANSLATE_RETRY 3 |
126 | | |
127 | | int |
128 | | nvmx_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa, |
129 | | unsigned int *page_order, uint8_t *p2m_acc, |
130 | | bool_t access_r, bool_t access_w, bool_t access_x); |
131 | | /* |
132 | | * Virtual VMCS layout |
133 | | * |
134 | | * Since physical VMCS layout is unknown, a custom layout is used |
135 | | * for virtual VMCS seen by guest. It occupies a 4k page, and the |
136 | | * field is offset by an 9-bit offset into u64[], The offset is as |
137 | | * follow, which means every <width, type> pair has a max of 32 |
138 | | * fields available. |
139 | | * |
140 | | * 9 7 5 0 |
141 | | * -------------------------------- |
142 | | * offset: | width | type | index | |
143 | | * -------------------------------- |
144 | | * |
145 | | * Also, since the lower range <width=0, type={0,1}> has only one |
146 | | * field: VPID, it is moved to a higher offset (63), and leaves the |
147 | | * lower range to non-indexed field like VMCS revision. |
148 | | * |
149 | | */ |
150 | | |
151 | | struct vvmcs_header { |
152 | | u32 revision; |
153 | | u32 abort; |
154 | | }; |
155 | | |
156 | | union vmcs_encoding { |
157 | | struct { |
158 | | u32 access_type : 1; |
159 | | u32 index : 9; |
160 | | u32 type : 2; |
161 | | u32 rsv1 : 1; |
162 | | u32 width : 2; |
163 | | u32 rsv2 : 17; |
164 | | }; |
165 | | u32 word; |
166 | | }; |
167 | | |
168 | | enum vvmcs_encoding_width { |
169 | | VVMCS_WIDTH_16 = 0, |
170 | | VVMCS_WIDTH_64, |
171 | | VVMCS_WIDTH_32, |
172 | | VVMCS_WIDTH_NATURAL, |
173 | | }; |
174 | | |
175 | | enum vvmcs_encoding_type { |
176 | | VVMCS_TYPE_CONTROL = 0, |
177 | | VVMCS_TYPE_RO, |
178 | | VVMCS_TYPE_GSTATE, |
179 | | VVMCS_TYPE_HSTATE, |
180 | | }; |
181 | | |
182 | | u64 get_vvmcs_virtual(void *vvmcs, u32 encoding); |
183 | | u64 get_vvmcs_real(const struct vcpu *, u32 encoding); |
184 | | void set_vvmcs_virtual(void *vvmcs, u32 encoding, u64 val); |
185 | | void set_vvmcs_real(const struct vcpu *, u32 encoding, u64 val); |
186 | | enum vmx_insn_errno get_vvmcs_virtual_safe(void *vvmcs, u32 encoding, u64 *val); |
187 | | enum vmx_insn_errno get_vvmcs_real_safe(const struct vcpu *, u32 encoding, |
188 | | u64 *val); |
189 | | enum vmx_insn_errno set_vvmcs_virtual_safe(void *vvmcs, u32 encoding, u64 val); |
190 | | enum vmx_insn_errno set_vvmcs_real_safe(const struct vcpu *, u32 encoding, |
191 | | u64 val); |
192 | | |
193 | | #define get_vvmcs(vcpu, encoding) \ |
194 | 0 | (cpu_has_vmx_vmcs_shadowing ? \ |
195 | 0 | get_vvmcs_real(vcpu, encoding) : \ |
196 | 0 | get_vvmcs_virtual(vcpu_nestedhvm(vcpu).nv_vvmcx, encoding)) |
197 | | |
198 | | #define set_vvmcs(vcpu, encoding, val) \ |
199 | 0 | (cpu_has_vmx_vmcs_shadowing ? \ |
200 | 0 | set_vvmcs_real(vcpu, encoding, val) : \ |
201 | 0 | set_vvmcs_virtual(vcpu_nestedhvm(vcpu).nv_vvmcx, encoding, val)) |
202 | | |
203 | | #define get_vvmcs_safe(vcpu, encoding, val) \ |
204 | 0 | (cpu_has_vmx_vmcs_shadowing ? \ |
205 | 0 | get_vvmcs_real_safe(vcpu, encoding, val) : \ |
206 | 0 | get_vvmcs_virtual_safe(vcpu_nestedhvm(vcpu).nv_vvmcx, encoding, val)) |
207 | | |
208 | | #define set_vvmcs_safe(vcpu, encoding, val) \ |
209 | 0 | (cpu_has_vmx_vmcs_shadowing ? \ |
210 | 0 | set_vvmcs_real_safe(vcpu, encoding, val) : \ |
211 | 0 | set_vvmcs_virtual_safe(vcpu_nestedhvm(vcpu).nv_vvmcx, encoding, val)) |
212 | | |
213 | | uint64_t get_shadow_eptp(struct vcpu *v); |
214 | | |
215 | | void nvmx_destroy_vmcs(struct vcpu *v); |
216 | | int nvmx_handle_vmptrld(struct cpu_user_regs *regs); |
217 | | int nvmx_handle_vmptrst(struct cpu_user_regs *regs); |
218 | | int nvmx_handle_vmclear(struct cpu_user_regs *regs); |
219 | | int nvmx_handle_vmread(struct cpu_user_regs *regs); |
220 | | int nvmx_handle_vmwrite(struct cpu_user_regs *regs); |
221 | | int nvmx_handle_vmresume(struct cpu_user_regs *regs); |
222 | | int nvmx_handle_vmlaunch(struct cpu_user_regs *regs); |
223 | | int nvmx_handle_invept(struct cpu_user_regs *regs); |
224 | | int nvmx_handle_invvpid(struct cpu_user_regs *regs); |
225 | | int nvmx_msr_read_intercept(unsigned int msr, |
226 | | u64 *msr_content); |
227 | | |
228 | | void nvmx_update_exec_control(struct vcpu *v, u32 value); |
229 | | void nvmx_update_secondary_exec_control(struct vcpu *v, |
230 | | unsigned long value); |
231 | | void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value); |
232 | | void nvmx_switch_guest(void); |
233 | | void nvmx_idtv_handling(void); |
234 | | u64 nvmx_get_tsc_offset(struct vcpu *v); |
235 | | int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs, |
236 | | unsigned int exit_reason); |
237 | | void nvmx_set_cr_read_shadow(struct vcpu *v, unsigned int cr); |
238 | | |
239 | | uint64_t nept_get_ept_vpid_cap(void); |
240 | | |
241 | | int nept_translate_l2ga(struct vcpu *v, paddr_t l2ga, |
242 | | unsigned int *page_order, uint32_t rwx_acc, |
243 | | unsigned long *l1gfn, uint8_t *p2m_acc, |
244 | | uint64_t *exit_qual, uint32_t *exit_reason); |
245 | | int nvmx_cpu_up_prepare(unsigned int cpu); |
246 | | void nvmx_cpu_dead(unsigned int cpu); |
247 | | #endif /* __ASM_X86_HVM_VVMX_H__ */ |
248 | | |