diff options
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 03b29aca6e7f..33476eb152ea 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -158,12 +158,150 @@ struct shared_msr_entry { | |||
158 | * machines (necessary for live migration). | 158 | * machines (necessary for live migration). |
159 | * If there are changes in this struct, VMCS12_REVISION must be changed. | 159 | * If there are changes in this struct, VMCS12_REVISION must be changed. |
160 | */ | 160 | */ |
161 | typedef u64 natural_width; | ||
161 | struct __packed vmcs12 { | 162 | struct __packed vmcs12 { |
162 | /* According to the Intel spec, a VMCS region must start with the | 163 | /* According to the Intel spec, a VMCS region must start with the |
163 | * following two fields. Then follow implementation-specific data. | 164 | * following two fields. Then follow implementation-specific data. |
164 | */ | 165 | */ |
165 | u32 revision_id; | 166 | u32 revision_id; |
166 | u32 abort; | 167 | u32 abort; |
168 | |||
169 | u64 io_bitmap_a; | ||
170 | u64 io_bitmap_b; | ||
171 | u64 msr_bitmap; | ||
172 | u64 vm_exit_msr_store_addr; | ||
173 | u64 vm_exit_msr_load_addr; | ||
174 | u64 vm_entry_msr_load_addr; | ||
175 | u64 tsc_offset; | ||
176 | u64 virtual_apic_page_addr; | ||
177 | u64 apic_access_addr; | ||
178 | u64 ept_pointer; | ||
179 | u64 guest_physical_address; | ||
180 | u64 vmcs_link_pointer; | ||
181 | u64 guest_ia32_debugctl; | ||
182 | u64 guest_ia32_pat; | ||
183 | u64 guest_ia32_efer; | ||
184 | u64 guest_ia32_perf_global_ctrl; | ||
185 | u64 guest_pdptr0; | ||
186 | u64 guest_pdptr1; | ||
187 | u64 guest_pdptr2; | ||
188 | u64 guest_pdptr3; | ||
189 | u64 host_ia32_pat; | ||
190 | u64 host_ia32_efer; | ||
191 | u64 host_ia32_perf_global_ctrl; | ||
192 | u64 padding64[8]; /* room for future expansion */ | ||
193 | /* | ||
194 | * To allow migration of L1 (complete with its L2 guests) between | ||
195 | * machines of different natural widths (32 or 64 bit), we cannot have | ||
196 | * unsigned long fields with no explict size. We use u64 (aliased | ||
197 | * natural_width) instead. Luckily, x86 is little-endian. | ||
198 | */ | ||
199 | natural_width cr0_guest_host_mask; | ||
200 | natural_width cr4_guest_host_mask; | ||
201 | natural_width cr0_read_shadow; | ||
202 | natural_width cr4_read_shadow; | ||
203 | natural_width cr3_target_value0; | ||
204 | natural_width cr3_target_value1; | ||
205 | natural_width cr3_target_value2; | ||
206 | natural_width cr3_target_value3; | ||
207 | natural_width exit_qualification; | ||
208 | natural_width guest_linear_address; | ||
209 | natural_width guest_cr0; | ||
210 | natural_width guest_cr3; | ||
211 | natural_width guest_cr4; | ||
212 | natural_width guest_es_base; | ||
213 | natural_width guest_cs_base; | ||
214 | natural_width guest_ss_base; | ||
215 | natural_width guest_ds_base; | ||
216 | natural_width guest_fs_base; | ||
217 | natural_width guest_gs_base; | ||
218 | natural_width guest_ldtr_base; | ||
219 | natural_width guest_tr_base; | ||
220 | natural_width guest_gdtr_base; | ||
221 | natural_width guest_idtr_base; | ||
222 | natural_width guest_dr7; | ||
223 | natural_width guest_rsp; | ||
224 | natural_width guest_rip; | ||
225 | natural_width guest_rflags; | ||
226 | natural_width guest_pending_dbg_exceptions; | ||
227 | natural_width guest_sysenter_esp; | ||
228 | natural_width guest_sysenter_eip; | ||
229 | natural_width host_cr0; | ||
230 | natural_width host_cr3; | ||
231 | natural_width host_cr4; | ||
232 | natural_width host_fs_base; | ||
233 | natural_width host_gs_base; | ||
234 | natural_width host_tr_base; | ||
235 | natural_width host_gdtr_base; | ||
236 | natural_width host_idtr_base; | ||
237 | natural_width host_ia32_sysenter_esp; | ||
238 | natural_width host_ia32_sysenter_eip; | ||
239 | natural_width host_rsp; | ||
240 | natural_width host_rip; | ||
241 | natural_width paddingl[8]; /* room for future expansion */ | ||
242 | u32 pin_based_vm_exec_control; | ||
243 | u32 cpu_based_vm_exec_control; | ||
244 | u32 exception_bitmap; | ||
245 | u32 page_fault_error_code_mask; | ||
246 | u32 page_fault_error_code_match; | ||
247 | u32 cr3_target_count; | ||
248 | u32 vm_exit_controls; | ||
249 | u32 vm_exit_msr_store_count; | ||
250 | u32 vm_exit_msr_load_count; | ||
251 | u32 vm_entry_controls; | ||
252 | u32 vm_entry_msr_load_count; | ||
253 | u32 vm_entry_intr_info_field; | ||
254 | u32 vm_entry_exception_error_code; | ||
255 | u32 vm_entry_instruction_len; | ||
256 | u32 tpr_threshold; | ||
257 | u32 secondary_vm_exec_control; | ||
258 | u32 vm_instruction_error; | ||
259 | u32 vm_exit_reason; | ||
260 | u32 vm_exit_intr_info; | ||
261 | u32 vm_exit_intr_error_code; | ||
262 | u32 idt_vectoring_info_field; | ||
263 | u32 idt_vectoring_error_code; | ||
264 | u32 vm_exit_instruction_len; | ||
265 | u32 vmx_instruction_info; | ||
266 | u32 guest_es_limit; | ||
267 | u32 guest_cs_limit; | ||
268 | u32 guest_ss_limit; | ||
269 | u32 guest_ds_limit; | ||
270 | u32 guest_fs_limit; | ||
271 | u32 guest_gs_limit; | ||
272 | u32 guest_ldtr_limit; | ||
273 | u32 guest_tr_limit; | ||
274 | u32 guest_gdtr_limit; | ||
275 | u32 guest_idtr_limit; | ||
276 | u32 guest_es_ar_bytes; | ||
277 | u32 guest_cs_ar_bytes; | ||
278 | u32 guest_ss_ar_bytes; | ||
279 | u32 guest_ds_ar_bytes; | ||
280 | u32 guest_fs_ar_bytes; | ||
281 | u32 guest_gs_ar_bytes; | ||
282 | u32 guest_ldtr_ar_bytes; | ||
283 | u32 guest_tr_ar_bytes; | ||
284 | u32 guest_interruptibility_info; | ||
285 | u32 guest_activity_state; | ||
286 | u32 guest_sysenter_cs; | ||
287 | u32 host_ia32_sysenter_cs; | ||
288 | u32 padding32[8]; /* room for future expansion */ | ||
289 | u16 virtual_processor_id; | ||
290 | u16 guest_es_selector; | ||
291 | u16 guest_cs_selector; | ||
292 | u16 guest_ss_selector; | ||
293 | u16 guest_ds_selector; | ||
294 | u16 guest_fs_selector; | ||
295 | u16 guest_gs_selector; | ||
296 | u16 guest_ldtr_selector; | ||
297 | u16 guest_tr_selector; | ||
298 | u16 host_es_selector; | ||
299 | u16 host_cs_selector; | ||
300 | u16 host_ss_selector; | ||
301 | u16 host_ds_selector; | ||
302 | u16 host_fs_selector; | ||
303 | u16 host_gs_selector; | ||
304 | u16 host_tr_selector; | ||
167 | }; | 305 | }; |
168 | 306 | ||
169 | /* | 307 | /* |
@@ -284,6 +422,149 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu) | |||
284 | return container_of(vcpu, struct vcpu_vmx, vcpu); | 422 | return container_of(vcpu, struct vcpu_vmx, vcpu); |
285 | } | 423 | } |
286 | 424 | ||
425 | #define VMCS12_OFFSET(x) offsetof(struct vmcs12, x) | ||
426 | #define FIELD(number, name) [number] = VMCS12_OFFSET(name) | ||
427 | #define FIELD64(number, name) [number] = VMCS12_OFFSET(name), \ | ||
428 | [number##_HIGH] = VMCS12_OFFSET(name)+4 | ||
429 | |||
430 | static unsigned short vmcs_field_to_offset_table[] = { | ||
431 | FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id), | ||
432 | FIELD(GUEST_ES_SELECTOR, guest_es_selector), | ||
433 | FIELD(GUEST_CS_SELECTOR, guest_cs_selector), | ||
434 | FIELD(GUEST_SS_SELECTOR, guest_ss_selector), | ||
435 | FIELD(GUEST_DS_SELECTOR, guest_ds_selector), | ||
436 | FIELD(GUEST_FS_SELECTOR, guest_fs_selector), | ||
437 | FIELD(GUEST_GS_SELECTOR, guest_gs_selector), | ||
438 | FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector), | ||
439 | FIELD(GUEST_TR_SELECTOR, guest_tr_selector), | ||
440 | FIELD(HOST_ES_SELECTOR, host_es_selector), | ||
441 | FIELD(HOST_CS_SELECTOR, host_cs_selector), | ||
442 | FIELD(HOST_SS_SELECTOR, host_ss_selector), | ||
443 | FIELD(HOST_DS_SELECTOR, host_ds_selector), | ||
444 | FIELD(HOST_FS_SELECTOR, host_fs_selector), | ||
445 | FIELD(HOST_GS_SELECTOR, host_gs_selector), | ||
446 | FIELD(HOST_TR_SELECTOR, host_tr_selector), | ||
447 | FIELD64(IO_BITMAP_A, io_bitmap_a), | ||
448 | FIELD64(IO_BITMAP_B, io_bitmap_b), | ||
449 | FIELD64(MSR_BITMAP, msr_bitmap), | ||
450 | FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr), | ||
451 | FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr), | ||
452 | FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr), | ||
453 | FIELD64(TSC_OFFSET, tsc_offset), | ||
454 | FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr), | ||
455 | FIELD64(APIC_ACCESS_ADDR, apic_access_addr), | ||
456 | FIELD64(EPT_POINTER, ept_pointer), | ||
457 | FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address), | ||
458 | FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer), | ||
459 | FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl), | ||
460 | FIELD64(GUEST_IA32_PAT, guest_ia32_pat), | ||
461 | FIELD64(GUEST_IA32_EFER, guest_ia32_efer), | ||
462 | FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl), | ||
463 | FIELD64(GUEST_PDPTR0, guest_pdptr0), | ||
464 | FIELD64(GUEST_PDPTR1, guest_pdptr1), | ||
465 | FIELD64(GUEST_PDPTR2, guest_pdptr2), | ||
466 | FIELD64(GUEST_PDPTR3, guest_pdptr3), | ||
467 | FIELD64(HOST_IA32_PAT, host_ia32_pat), | ||
468 | FIELD64(HOST_IA32_EFER, host_ia32_efer), | ||
469 | FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl), | ||
470 | FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control), | ||
471 | FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control), | ||
472 | FIELD(EXCEPTION_BITMAP, exception_bitmap), | ||
473 | FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask), | ||
474 | FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match), | ||
475 | FIELD(CR3_TARGET_COUNT, cr3_target_count), | ||
476 | FIELD(VM_EXIT_CONTROLS, vm_exit_controls), | ||
477 | FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count), | ||
478 | FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count), | ||
479 | FIELD(VM_ENTRY_CONTROLS, vm_entry_controls), | ||
480 | FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count), | ||
481 | FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field), | ||
482 | FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE, vm_entry_exception_error_code), | ||
483 | FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len), | ||
484 | FIELD(TPR_THRESHOLD, tpr_threshold), | ||
485 | FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control), | ||
486 | FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error), | ||
487 | FIELD(VM_EXIT_REASON, vm_exit_reason), | ||
488 | FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info), | ||
489 | FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code), | ||
490 | FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field), | ||
491 | FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code), | ||
492 | FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len), | ||
493 | FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info), | ||
494 | FIELD(GUEST_ES_LIMIT, guest_es_limit), | ||
495 | FIELD(GUEST_CS_LIMIT, guest_cs_limit), | ||
496 | FIELD(GUEST_SS_LIMIT, guest_ss_limit), | ||
497 | FIELD(GUEST_DS_LIMIT, guest_ds_limit), | ||
498 | FIELD(GUEST_FS_LIMIT, guest_fs_limit), | ||
499 | FIELD(GUEST_GS_LIMIT, guest_gs_limit), | ||
500 | FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit), | ||
501 | FIELD(GUEST_TR_LIMIT, guest_tr_limit), | ||
502 | FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit), | ||
503 | FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit), | ||
504 | FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes), | ||
505 | FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes), | ||
506 | FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes), | ||
507 | FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes), | ||
508 | FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes), | ||
509 | FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes), | ||
510 | FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes), | ||
511 | FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes), | ||
512 | FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info), | ||
513 | FIELD(GUEST_ACTIVITY_STATE, guest_activity_state), | ||
514 | FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs), | ||
515 | FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs), | ||
516 | FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask), | ||
517 | FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask), | ||
518 | FIELD(CR0_READ_SHADOW, cr0_read_shadow), | ||
519 | FIELD(CR4_READ_SHADOW, cr4_read_shadow), | ||
520 | FIELD(CR3_TARGET_VALUE0, cr3_target_value0), | ||
521 | FIELD(CR3_TARGET_VALUE1, cr3_target_value1), | ||
522 | FIELD(CR3_TARGET_VALUE2, cr3_target_value2), | ||
523 | FIELD(CR3_TARGET_VALUE3, cr3_target_value3), | ||
524 | FIELD(EXIT_QUALIFICATION, exit_qualification), | ||
525 | FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address), | ||
526 | FIELD(GUEST_CR0, guest_cr0), | ||
527 | FIELD(GUEST_CR3, guest_cr3), | ||
528 | FIELD(GUEST_CR4, guest_cr4), | ||
529 | FIELD(GUEST_ES_BASE, guest_es_base), | ||
530 | FIELD(GUEST_CS_BASE, guest_cs_base), | ||
531 | FIELD(GUEST_SS_BASE, guest_ss_base), | ||
532 | FIELD(GUEST_DS_BASE, guest_ds_base), | ||
533 | FIELD(GUEST_FS_BASE, guest_fs_base), | ||
534 | FIELD(GUEST_GS_BASE, guest_gs_base), | ||
535 | FIELD(GUEST_LDTR_BASE, guest_ldtr_base), | ||
536 | FIELD(GUEST_TR_BASE, guest_tr_base), | ||
537 | FIELD(GUEST_GDTR_BASE, guest_gdtr_base), | ||
538 | FIELD(GUEST_IDTR_BASE, guest_idtr_base), | ||
539 | FIELD(GUEST_DR7, guest_dr7), | ||
540 | FIELD(GUEST_RSP, guest_rsp), | ||
541 | FIELD(GUEST_RIP, guest_rip), | ||
542 | FIELD(GUEST_RFLAGS, guest_rflags), | ||
543 | FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions), | ||
544 | FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp), | ||
545 | FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip), | ||
546 | FIELD(HOST_CR0, host_cr0), | ||
547 | FIELD(HOST_CR3, host_cr3), | ||
548 | FIELD(HOST_CR4, host_cr4), | ||
549 | FIELD(HOST_FS_BASE, host_fs_base), | ||
550 | FIELD(HOST_GS_BASE, host_gs_base), | ||
551 | FIELD(HOST_TR_BASE, host_tr_base), | ||
552 | FIELD(HOST_GDTR_BASE, host_gdtr_base), | ||
553 | FIELD(HOST_IDTR_BASE, host_idtr_base), | ||
554 | FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp), | ||
555 | FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip), | ||
556 | FIELD(HOST_RSP, host_rsp), | ||
557 | FIELD(HOST_RIP, host_rip), | ||
558 | }; | ||
559 | static const int max_vmcs_field = ARRAY_SIZE(vmcs_field_to_offset_table); | ||
560 | |||
561 | static inline short vmcs_field_to_offset(unsigned long field) | ||
562 | { | ||
563 | if (field >= max_vmcs_field || vmcs_field_to_offset_table[field] == 0) | ||
564 | return -1; | ||
565 | return vmcs_field_to_offset_table[field]; | ||
566 | } | ||
567 | |||
287 | static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu) | 568 | static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu) |
288 | { | 569 | { |
289 | return to_vmx(vcpu)->nested.current_vmcs12; | 570 | return to_vmx(vcpu)->nested.current_vmcs12; |