diff mbox

[RFC] KVM: nVMX: share definitions of fields in vmcs12

Message ID 20180523172502.GB26021@flask (mailing list archive)
State New, archived
Headers show

Commit Message

Radim Krčmář May 23, 2018, 5:25 p.m. UTC
2018-05-23 18:18+0200, Radim Krčmář:
> Hm, having the list three times makes me thing of adding a header file
> in a format like
> 
>   FIELD32(REVISION_ID, revision_id, 0)
>   ...
>   PADDING(u64 padding64[3])
>   ...
>   FIELD16(GUEST_PML_INDEX, guest_pml_index, 996)
> 
> and including it three times with different definitions of FIELD*, e.g.:
> 
>   #define FIELD16(number, name, offset) \
>       u16 name;
> 
>   #define FIELD16(number, name, offset) \
>       [ROL16(number, 6)] = VMCS12_OFFSET(name),
> 
>   #define FIELD16(number, name, offset) \
>       BUILD_BUG_ON_MSG(VMCS12_OFFSET(name) != (offset), "Offset ...");
> 
> the advantage is that we make sure that there is always a check in
> place, but it never looks great in C ... will post a RFC.

I don't like that it makes the structure definition harder to read, but
it's still ok, IMO:

---8<---
We had three users -- the definition of struct vmcs12, mapping between
VMCS fields and struct vmcs12, and offset checking of struct vmcs12.

This patch adds macro templates to allow just one definition.
We could also extend it to "enum vmcs_field".

Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 arch/x86/kvm/vmcs12.h | 166 ++++++++++++++
 arch/x86/kvm/vmx.c    | 499 ++++--------------------------------------
 2 files changed, 204 insertions(+), 461 deletions(-)
 create mode 100644 arch/x86/kvm/vmcs12.h
diff mbox

Patch

diff --git a/arch/x86/kvm/vmcs12.h b/arch/x86/kvm/vmcs12.h
new file mode 100644
index 000000000000..7ad5162b247a
--- /dev/null
+++ b/arch/x86/kvm/vmcs12.h
@@ -0,0 +1,166 @@ 
+/* According to the Intel spec, a VMCS region must start with the
+ * following two fields. Then follow implementation-specific data.
+ */
+NOFIELD(u32, revision_id,                     0)
+NOFIELD(u32, abort,                           4)
+
+/* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+NOFIELD(u32, launch_state,                    8)
+PADDING(u32, padding, 7,                     12)
+
+FIELD64(IO_BITMAP_A, io_bitmap_a, 40)
+FIELD64(IO_BITMAP_B, io_bitmap_b, 48)
+FIELD64(MSR_BITMAP, msr_bitmap, 56)
+FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr, 64)
+FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr, 72)
+FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr, 80)
+FIELD64(TSC_OFFSET, tsc_offset, 88)
+FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr, 96)
+FIELD64(APIC_ACCESS_ADDR, apic_access_addr, 104)
+FIELD64(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr, 112)
+FIELD64(EPT_POINTER, ept_pointer, 120)
+FIELD64(EOI_EXIT_BITMAP0, eoi_exit_bitmap0, 128)
+FIELD64(EOI_EXIT_BITMAP1, eoi_exit_bitmap1, 136)
+FIELD64(EOI_EXIT_BITMAP2, eoi_exit_bitmap2, 144)
+FIELD64(EOI_EXIT_BITMAP3, eoi_exit_bitmap3, 152)
+FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap, 160)
+FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address, 168)
+FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer, 176)
+FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl, 184)
+FIELD64(GUEST_IA32_PAT, guest_ia32_pat, 192)
+FIELD64(GUEST_IA32_EFER, guest_ia32_efer, 200)
+FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl, 208)
+FIELD64(GUEST_PDPTR0, guest_pdptr0, 216)
+FIELD64(GUEST_PDPTR1, guest_pdptr1, 224)
+FIELD64(GUEST_PDPTR2, guest_pdptr2, 232)
+FIELD64(GUEST_PDPTR3, guest_pdptr3, 240)
+FIELD64(GUEST_BNDCFGS, guest_bndcfgs, 248)
+FIELD64(HOST_IA32_PAT, host_ia32_pat, 256)
+FIELD64(HOST_IA32_EFER, host_ia32_efer, 264)
+FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl, 272)
+FIELD64(VMREAD_BITMAP, vmread_bitmap, 280)
+FIELD64(VMWRITE_BITMAP, vmwrite_bitmap, 288)
+FIELD64(VM_FUNCTION_CONTROL, vm_function_control, 296)
+FIELD64(EPTP_LIST_ADDRESS, eptp_list_address, 304)
+FIELD64(PML_ADDRESS, pml_address, 312)
+PADDING(u64, padding64, 3, 320)
+
+FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask, 344)
+FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask, 352)
+FIELD(CR0_READ_SHADOW, cr0_read_shadow, 360)
+FIELD(CR4_READ_SHADOW, cr4_read_shadow, 368)
+FIELD(CR3_TARGET_VALUE0, cr3_target_value0, 376)
+FIELD(CR3_TARGET_VALUE1, cr3_target_value1, 384)
+FIELD(CR3_TARGET_VALUE2, cr3_target_value2, 392)
+FIELD(CR3_TARGET_VALUE3, cr3_target_value3, 400)
+FIELD(EXIT_QUALIFICATION, exit_qualification, 408)
+FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address, 416)
+FIELD(GUEST_CR0, guest_cr0, 424)
+FIELD(GUEST_CR3, guest_cr3, 432)
+FIELD(GUEST_CR4, guest_cr4, 440)
+FIELD(GUEST_ES_BASE, guest_es_base, 448)
+FIELD(GUEST_CS_BASE, guest_cs_base, 456)
+FIELD(GUEST_SS_BASE, guest_ss_base, 464)
+FIELD(GUEST_DS_BASE, guest_ds_base, 472)
+FIELD(GUEST_FS_BASE, guest_fs_base, 480)
+FIELD(GUEST_GS_BASE, guest_gs_base, 488)
+FIELD(GUEST_LDTR_BASE, guest_ldtr_base, 496)
+FIELD(GUEST_TR_BASE, guest_tr_base, 504)
+FIELD(GUEST_GDTR_BASE, guest_gdtr_base, 512)
+FIELD(GUEST_IDTR_BASE, guest_idtr_base, 520)
+FIELD(GUEST_DR7, guest_dr7, 528)
+FIELD(GUEST_RSP, guest_rsp, 536)
+FIELD(GUEST_RIP, guest_rip, 544)
+FIELD(GUEST_RFLAGS, guest_rflags, 552)
+FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions, 560)
+FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp, 568)
+FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip, 576)
+FIELD(HOST_CR0, host_cr0, 584)
+FIELD(HOST_CR3, host_cr3, 592)
+FIELD(HOST_CR4, host_cr4, 600)
+FIELD(HOST_FS_BASE, host_fs_base, 608)
+FIELD(HOST_GS_BASE, host_gs_base, 616)
+FIELD(HOST_TR_BASE, host_tr_base, 624)
+FIELD(HOST_GDTR_BASE, host_gdtr_base, 632)
+FIELD(HOST_IDTR_BASE, host_idtr_base, 640)
+FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp, 648)
+FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip, 656)
+FIELD(HOST_RSP, host_rsp, 664)
+FIELD(HOST_RIP, host_rip, 672)
+PADDING(natural_width, paddingl, 8, 680)
+
+FIELD32(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control, 744)
+FIELD32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control, 748)
+FIELD32(EXCEPTION_BITMAP, exception_bitmap, 752)
+FIELD32(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask, 756)
+FIELD32(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match, 760)
+FIELD32(CR3_TARGET_COUNT, cr3_target_count, 764)
+FIELD32(VM_EXIT_CONTROLS, vm_exit_controls, 768)
+FIELD32(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count, 772)
+FIELD32(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count, 776)
+FIELD32(VM_ENTRY_CONTROLS, vm_entry_controls, 780)
+FIELD32(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count, 784)
+FIELD32(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field, 788)
+FIELD32(VM_ENTRY_EXCEPTION_ERROR_CODE, vm_entry_exception_error_code, 792)
+FIELD32(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len, 796)
+FIELD32(TPR_THRESHOLD, tpr_threshold, 800)
+FIELD32(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control, 804)
+FIELD32(VM_INSTRUCTION_ERROR, vm_instruction_error, 808)
+FIELD32(VM_EXIT_REASON, vm_exit_reason, 812)
+FIELD32(VM_EXIT_INTR_INFO, vm_exit_intr_info, 816)
+FIELD32(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code, 820)
+FIELD32(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field, 824)
+FIELD32(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code, 828)
+FIELD32(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len, 832)
+FIELD32(VMX_INSTRUCTION_INFO, vmx_instruction_info, 836)
+FIELD32(GUEST_ES_LIMIT, guest_es_limit, 840)
+FIELD32(GUEST_CS_LIMIT, guest_cs_limit, 844)
+FIELD32(GUEST_SS_LIMIT, guest_ss_limit, 848)
+FIELD32(GUEST_DS_LIMIT, guest_ds_limit, 852)
+FIELD32(GUEST_FS_LIMIT, guest_fs_limit, 856)
+FIELD32(GUEST_GS_LIMIT, guest_gs_limit, 860)
+FIELD32(GUEST_LDTR_LIMIT, guest_ldtr_limit, 864)
+FIELD32(GUEST_TR_LIMIT, guest_tr_limit, 868)
+FIELD32(GUEST_GDTR_LIMIT, guest_gdtr_limit, 872)
+FIELD32(GUEST_IDTR_LIMIT, guest_idtr_limit, 876)
+FIELD32(GUEST_ES_AR_BYTES, guest_es_ar_bytes, 880)
+FIELD32(GUEST_CS_AR_BYTES, guest_cs_ar_bytes, 884)
+FIELD32(GUEST_SS_AR_BYTES, guest_ss_ar_bytes, 888)
+FIELD32(GUEST_DS_AR_BYTES, guest_ds_ar_bytes, 892)
+FIELD32(GUEST_FS_AR_BYTES, guest_fs_ar_bytes, 896)
+FIELD32(GUEST_GS_AR_BYTES, guest_gs_ar_bytes, 900)
+FIELD32(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes, 904)
+FIELD32(GUEST_TR_AR_BYTES, guest_tr_ar_bytes, 908)
+FIELD32(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info, 912)
+FIELD32(GUEST_ACTIVITY_STATE, guest_activity_state, 916)
+FIELD32(GUEST_SYSENTER_CS, guest_sysenter_cs, 920)
+FIELD32(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs, 924)
+FIELD32(VMX_PREEMPTION_TIMER_VALUE, vmx_preemption_timer_value, 928)
+PADDING(u32, padding32, 7, 932)
+
+FIELD16(VIRTUAL_PROCESSOR_ID, virtual_processor_id, 960)
+FIELD16(POSTED_INTR_NV, posted_intr_nv, 962)
+FIELD16(GUEST_ES_SELECTOR, guest_es_selector, 964)
+FIELD16(GUEST_CS_SELECTOR, guest_cs_selector, 966)
+FIELD16(GUEST_SS_SELECTOR, guest_ss_selector, 968)
+FIELD16(GUEST_DS_SELECTOR, guest_ds_selector, 970)
+FIELD16(GUEST_FS_SELECTOR, guest_fs_selector, 972)
+FIELD16(GUEST_GS_SELECTOR, guest_gs_selector, 974)
+FIELD16(GUEST_LDTR_SELECTOR, guest_ldtr_selector, 976)
+FIELD16(GUEST_TR_SELECTOR, guest_tr_selector, 978)
+FIELD16(GUEST_INTR_STATUS, guest_intr_status, 980)
+FIELD16(HOST_ES_SELECTOR, host_es_selector, 982)
+FIELD16(HOST_CS_SELECTOR, host_cs_selector, 984)
+FIELD16(HOST_SS_SELECTOR, host_ss_selector, 986)
+FIELD16(HOST_DS_SELECTOR, host_ds_selector, 988)
+FIELD16(HOST_FS_SELECTOR, host_fs_selector, 990)
+FIELD16(HOST_GS_SELECTOR, host_gs_selector, 992)
+FIELD16(HOST_TR_SELECTOR, host_tr_selector, 994)
+FIELD16(GUEST_PML_INDEX, guest_pml_index, 996)
+
+#undef PADDING
+#undef NOFIELD
+#undef FIELD16
+#undef FIELD32
+#undef FIELD64
+#undef FIELD
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index c34437ad5d9c..f3d645cbc4db 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -248,169 +248,23 @@  struct shared_msr_entry {
  * adding new fields, either use space in the reserved padding* arrays
  * or add the new fields to the end of the structure.
  */
+
+#define PADDING(type, name, size, offset) type name[size];
+#define NOFIELD(type, name, offset) type name;
+#define FIELD16(number, name, offset) u16 name;
+#define FIELD32(number, name, offset) u32 name;
+#define FIELD64(number, name, offset) u64 name;
+/*
+ * To allow migration of L1 (complete with its L2 guests) between
+ * machines of different natural widths (32 or 64 bit), we cannot have
+ * unsigned long fields with no explict size. We use u64 (aliased
+ * natural_width) instead.  Luckily, x86 is little-endian.
+ */
 typedef u64 natural_width;
-struct __packed vmcs12 {
-	/* According to the Intel spec, a VMCS region must start with the
-	 * following two fields. Then follow implementation-specific data.
-	 */
-	u32 revision_id;
-	u32 abort;
+#define FIELD(number, name, offset) natural_width name;
 
-	u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
-	u32 padding[7]; /* room for future expansion */
-
-	u64 io_bitmap_a;
-	u64 io_bitmap_b;
-	u64 msr_bitmap;
-	u64 vm_exit_msr_store_addr;
-	u64 vm_exit_msr_load_addr;
-	u64 vm_entry_msr_load_addr;
-	u64 tsc_offset;
-	u64 virtual_apic_page_addr;
-	u64 apic_access_addr;
-	u64 posted_intr_desc_addr;
-	u64 ept_pointer;
-	u64 eoi_exit_bitmap0;
-	u64 eoi_exit_bitmap1;
-	u64 eoi_exit_bitmap2;
-	u64 eoi_exit_bitmap3;
-	u64 xss_exit_bitmap;
-	u64 guest_physical_address;
-	u64 vmcs_link_pointer;
-	u64 guest_ia32_debugctl;
-	u64 guest_ia32_pat;
-	u64 guest_ia32_efer;
-	u64 guest_ia32_perf_global_ctrl;
-	u64 guest_pdptr0;
-	u64 guest_pdptr1;
-	u64 guest_pdptr2;
-	u64 guest_pdptr3;
-	u64 guest_bndcfgs;
-	u64 host_ia32_pat;
-	u64 host_ia32_efer;
-	u64 host_ia32_perf_global_ctrl;
-	u64 vmread_bitmap;
-	u64 vmwrite_bitmap;
-	u64 vm_function_control;
-	u64 eptp_list_address;
-	u64 pml_address;
-	u64 padding64[3]; /* room for future expansion */
-	/*
-	 * To allow migration of L1 (complete with its L2 guests) between
-	 * machines of different natural widths (32 or 64 bit), we cannot have
-	 * unsigned long fields with no explict size. We use u64 (aliased
-	 * natural_width) instead. Luckily, x86 is little-endian.
-	 */
-	natural_width cr0_guest_host_mask;
-	natural_width cr4_guest_host_mask;
-	natural_width cr0_read_shadow;
-	natural_width cr4_read_shadow;
-	natural_width cr3_target_value0;
-	natural_width cr3_target_value1;
-	natural_width cr3_target_value2;
-	natural_width cr3_target_value3;
-	natural_width exit_qualification;
-	natural_width guest_linear_address;
-	natural_width guest_cr0;
-	natural_width guest_cr3;
-	natural_width guest_cr4;
-	natural_width guest_es_base;
-	natural_width guest_cs_base;
-	natural_width guest_ss_base;
-	natural_width guest_ds_base;
-	natural_width guest_fs_base;
-	natural_width guest_gs_base;
-	natural_width guest_ldtr_base;
-	natural_width guest_tr_base;
-	natural_width guest_gdtr_base;
-	natural_width guest_idtr_base;
-	natural_width guest_dr7;
-	natural_width guest_rsp;
-	natural_width guest_rip;
-	natural_width guest_rflags;
-	natural_width guest_pending_dbg_exceptions;
-	natural_width guest_sysenter_esp;
-	natural_width guest_sysenter_eip;
-	natural_width host_cr0;
-	natural_width host_cr3;
-	natural_width host_cr4;
-	natural_width host_fs_base;
-	natural_width host_gs_base;
-	natural_width host_tr_base;
-	natural_width host_gdtr_base;
-	natural_width host_idtr_base;
-	natural_width host_ia32_sysenter_esp;
-	natural_width host_ia32_sysenter_eip;
-	natural_width host_rsp;
-	natural_width host_rip;
-	natural_width paddingl[8]; /* room for future expansion */
-	u32 pin_based_vm_exec_control;
-	u32 cpu_based_vm_exec_control;
-	u32 exception_bitmap;
-	u32 page_fault_error_code_mask;
-	u32 page_fault_error_code_match;
-	u32 cr3_target_count;
-	u32 vm_exit_controls;
-	u32 vm_exit_msr_store_count;
-	u32 vm_exit_msr_load_count;
-	u32 vm_entry_controls;
-	u32 vm_entry_msr_load_count;
-	u32 vm_entry_intr_info_field;
-	u32 vm_entry_exception_error_code;
-	u32 vm_entry_instruction_len;
-	u32 tpr_threshold;
-	u32 secondary_vm_exec_control;
-	u32 vm_instruction_error;
-	u32 vm_exit_reason;
-	u32 vm_exit_intr_info;
-	u32 vm_exit_intr_error_code;
-	u32 idt_vectoring_info_field;
-	u32 idt_vectoring_error_code;
-	u32 vm_exit_instruction_len;
-	u32 vmx_instruction_info;
-	u32 guest_es_limit;
-	u32 guest_cs_limit;
-	u32 guest_ss_limit;
-	u32 guest_ds_limit;
-	u32 guest_fs_limit;
-	u32 guest_gs_limit;
-	u32 guest_ldtr_limit;
-	u32 guest_tr_limit;
-	u32 guest_gdtr_limit;
-	u32 guest_idtr_limit;
-	u32 guest_es_ar_bytes;
-	u32 guest_cs_ar_bytes;
-	u32 guest_ss_ar_bytes;
-	u32 guest_ds_ar_bytes;
-	u32 guest_fs_ar_bytes;
-	u32 guest_gs_ar_bytes;
-	u32 guest_ldtr_ar_bytes;
-	u32 guest_tr_ar_bytes;
-	u32 guest_interruptibility_info;
-	u32 guest_activity_state;
-	u32 guest_sysenter_cs;
-	u32 host_ia32_sysenter_cs;
-	u32 vmx_preemption_timer_value;
-	u32 padding32[7]; /* room for future expansion */
-	u16 virtual_processor_id;
-	u16 posted_intr_nv;
-	u16 guest_es_selector;
-	u16 guest_cs_selector;
-	u16 guest_ss_selector;
-	u16 guest_ds_selector;
-	u16 guest_fs_selector;
-	u16 guest_gs_selector;
-	u16 guest_ldtr_selector;
-	u16 guest_tr_selector;
-	u16 guest_intr_status;
-	u16 host_es_selector;
-	u16 host_cs_selector;
-	u16 host_ss_selector;
-	u16 host_ds_selector;
-	u16 host_fs_selector;
-	u16 host_gs_selector;
-	u16 host_tr_selector;
-	u16 guest_pml_index;
+struct __packed vmcs12 {
+#include "vmcs12.h"
 };
 
 /*
@@ -418,155 +272,17 @@  struct __packed vmcs12 {
  */
 #define CHECK_OFFSET(field, loc)				\
 	BUILD_BUG_ON_MSG(offsetof(struct vmcs12, field) != (loc),	\
-		"Offset of " #field " in struct vmcs12 has changed.")
-
-static inline void vmx_check_vmcs12_offsets(void) {
-	CHECK_OFFSET(revision_id, 0);
-	CHECK_OFFSET(abort, 4);
-	CHECK_OFFSET(launch_state, 8);
-	CHECK_OFFSET(io_bitmap_a, 40);
-	CHECK_OFFSET(io_bitmap_b, 48);
-	CHECK_OFFSET(msr_bitmap, 56);
-	CHECK_OFFSET(vm_exit_msr_store_addr, 64);
-	CHECK_OFFSET(vm_exit_msr_load_addr, 72);
-	CHECK_OFFSET(vm_entry_msr_load_addr, 80);
-	CHECK_OFFSET(tsc_offset, 88);
-	CHECK_OFFSET(virtual_apic_page_addr, 96);
-	CHECK_OFFSET(apic_access_addr, 104);
-	CHECK_OFFSET(posted_intr_desc_addr, 112);
-	CHECK_OFFSET(ept_pointer, 120);
-	CHECK_OFFSET(eoi_exit_bitmap0, 128);
-	CHECK_OFFSET(eoi_exit_bitmap1, 136);
-	CHECK_OFFSET(eoi_exit_bitmap2, 144);
-	CHECK_OFFSET(eoi_exit_bitmap3, 152);
-	CHECK_OFFSET(xss_exit_bitmap, 160);
-	CHECK_OFFSET(guest_physical_address, 168);
-	CHECK_OFFSET(vmcs_link_pointer, 176);
-	CHECK_OFFSET(guest_ia32_debugctl, 184);
-	CHECK_OFFSET(guest_ia32_pat, 192);
-	CHECK_OFFSET(guest_ia32_efer, 200);
-	CHECK_OFFSET(guest_ia32_perf_global_ctrl, 208);
-	CHECK_OFFSET(guest_pdptr0, 216);
-	CHECK_OFFSET(guest_pdptr1, 224);
-	CHECK_OFFSET(guest_pdptr2, 232);
-	CHECK_OFFSET(guest_pdptr3, 240);
-	CHECK_OFFSET(guest_bndcfgs, 248);
-	CHECK_OFFSET(host_ia32_pat, 256);
-	CHECK_OFFSET(host_ia32_efer, 264);
-	CHECK_OFFSET(host_ia32_perf_global_ctrl, 272);
-	CHECK_OFFSET(vmread_bitmap, 280);
-	CHECK_OFFSET(vmwrite_bitmap, 288);
-	CHECK_OFFSET(vm_function_control, 296);
-	CHECK_OFFSET(eptp_list_address, 304);
-	CHECK_OFFSET(pml_address, 312);
-	CHECK_OFFSET(cr0_guest_host_mask, 344);
-	CHECK_OFFSET(cr4_guest_host_mask, 352);
-	CHECK_OFFSET(cr0_read_shadow, 360);
-	CHECK_OFFSET(cr4_read_shadow, 368);
-	CHECK_OFFSET(cr3_target_value0, 376);
-	CHECK_OFFSET(cr3_target_value1, 384);
-	CHECK_OFFSET(cr3_target_value2, 392);
-	CHECK_OFFSET(cr3_target_value3, 400);
-	CHECK_OFFSET(exit_qualification, 408);
-	CHECK_OFFSET(guest_linear_address, 416);
-	CHECK_OFFSET(guest_cr0, 424);
-	CHECK_OFFSET(guest_cr3, 432);
-	CHECK_OFFSET(guest_cr4, 440);
-	CHECK_OFFSET(guest_es_base, 448);
-	CHECK_OFFSET(guest_cs_base, 456);
-	CHECK_OFFSET(guest_ss_base, 464);
-	CHECK_OFFSET(guest_ds_base, 472);
-	CHECK_OFFSET(guest_fs_base, 480);
-	CHECK_OFFSET(guest_gs_base, 488);
-	CHECK_OFFSET(guest_ldtr_base, 496);
-	CHECK_OFFSET(guest_tr_base, 504);
-	CHECK_OFFSET(guest_gdtr_base, 512);
-	CHECK_OFFSET(guest_idtr_base, 520);
-	CHECK_OFFSET(guest_dr7, 528);
-	CHECK_OFFSET(guest_rsp, 536);
-	CHECK_OFFSET(guest_rip, 544);
-	CHECK_OFFSET(guest_rflags, 552);
-	CHECK_OFFSET(guest_pending_dbg_exceptions, 560);
-	CHECK_OFFSET(guest_sysenter_esp, 568);
-	CHECK_OFFSET(guest_sysenter_eip, 576);
-	CHECK_OFFSET(host_cr0, 584);
-	CHECK_OFFSET(host_cr3, 592);
-	CHECK_OFFSET(host_cr4, 600);
-	CHECK_OFFSET(host_fs_base, 608);
-	CHECK_OFFSET(host_gs_base, 616);
-	CHECK_OFFSET(host_tr_base, 624);
-	CHECK_OFFSET(host_gdtr_base, 632);
-	CHECK_OFFSET(host_idtr_base, 640);
-	CHECK_OFFSET(host_ia32_sysenter_esp, 648);
-	CHECK_OFFSET(host_ia32_sysenter_eip, 656);
-	CHECK_OFFSET(host_rsp, 664);
-	CHECK_OFFSET(host_rip, 672);
-	CHECK_OFFSET(pin_based_vm_exec_control, 744);
-	CHECK_OFFSET(cpu_based_vm_exec_control, 748);
-	CHECK_OFFSET(exception_bitmap, 752);
-	CHECK_OFFSET(page_fault_error_code_mask, 756);
-	CHECK_OFFSET(page_fault_error_code_match, 760);
-	CHECK_OFFSET(cr3_target_count, 764);
-	CHECK_OFFSET(vm_exit_controls, 768);
-	CHECK_OFFSET(vm_exit_msr_store_count, 772);
-	CHECK_OFFSET(vm_exit_msr_load_count, 776);
-	CHECK_OFFSET(vm_entry_controls, 780);
-	CHECK_OFFSET(vm_entry_msr_load_count, 784);
-	CHECK_OFFSET(vm_entry_intr_info_field, 788);
-	CHECK_OFFSET(vm_entry_exception_error_code, 792);
-	CHECK_OFFSET(vm_entry_instruction_len, 796);
-	CHECK_OFFSET(tpr_threshold, 800);
-	CHECK_OFFSET(secondary_vm_exec_control, 804);
-	CHECK_OFFSET(vm_instruction_error, 808);
-	CHECK_OFFSET(vm_exit_reason, 812);
-	CHECK_OFFSET(vm_exit_intr_info, 816);
-	CHECK_OFFSET(vm_exit_intr_error_code, 820);
-	CHECK_OFFSET(idt_vectoring_info_field, 824);
-	CHECK_OFFSET(idt_vectoring_error_code, 828);
-	CHECK_OFFSET(vm_exit_instruction_len, 832);
-	CHECK_OFFSET(vmx_instruction_info, 836);
-	CHECK_OFFSET(guest_es_limit, 840);
-	CHECK_OFFSET(guest_cs_limit, 844);
-	CHECK_OFFSET(guest_ss_limit, 848);
-	CHECK_OFFSET(guest_ds_limit, 852);
-	CHECK_OFFSET(guest_fs_limit, 856);
-	CHECK_OFFSET(guest_gs_limit, 860);
-	CHECK_OFFSET(guest_ldtr_limit, 864);
-	CHECK_OFFSET(guest_tr_limit, 868);
-	CHECK_OFFSET(guest_gdtr_limit, 872);
-	CHECK_OFFSET(guest_idtr_limit, 876);
-	CHECK_OFFSET(guest_es_ar_bytes, 880);
-	CHECK_OFFSET(guest_cs_ar_bytes, 884);
-	CHECK_OFFSET(guest_ss_ar_bytes, 888);
-	CHECK_OFFSET(guest_ds_ar_bytes, 892);
-	CHECK_OFFSET(guest_fs_ar_bytes, 896);
-	CHECK_OFFSET(guest_gs_ar_bytes, 900);
-	CHECK_OFFSET(guest_ldtr_ar_bytes, 904);
-	CHECK_OFFSET(guest_tr_ar_bytes, 908);
-	CHECK_OFFSET(guest_interruptibility_info, 912);
-	CHECK_OFFSET(guest_activity_state, 916);
-	CHECK_OFFSET(guest_sysenter_cs, 920);
-	CHECK_OFFSET(host_ia32_sysenter_cs, 924);
-	CHECK_OFFSET(vmx_preemption_timer_value, 928);
-	CHECK_OFFSET(virtual_processor_id, 960);
-	CHECK_OFFSET(posted_intr_nv, 962);
-	CHECK_OFFSET(guest_es_selector, 964);
-	CHECK_OFFSET(guest_cs_selector, 966);
-	CHECK_OFFSET(guest_ss_selector, 968);
-	CHECK_OFFSET(guest_ds_selector, 970);
-	CHECK_OFFSET(guest_fs_selector, 972);
-	CHECK_OFFSET(guest_gs_selector, 974);
-	CHECK_OFFSET(guest_ldtr_selector, 976);
-	CHECK_OFFSET(guest_tr_selector, 978);
-	CHECK_OFFSET(guest_intr_status, 980);
-	CHECK_OFFSET(host_es_selector, 982);
-	CHECK_OFFSET(host_cs_selector, 984);
-	CHECK_OFFSET(host_ss_selector, 986);
-	CHECK_OFFSET(host_ds_selector, 988);
-	CHECK_OFFSET(host_fs_selector, 990);
-	CHECK_OFFSET(host_gs_selector, 992);
-	CHECK_OFFSET(host_tr_selector, 994);
-	CHECK_OFFSET(guest_pml_index, 996);
+		"Offset of " #field " in struct vmcs12 has changed.");
+
+#define PADDING(type, name, size, offset) CHECK_OFFSET(name, offset)
+#define NOFIELD(type, name, offset) CHECK_OFFSET(name, offset)
+#define FIELD16(number, name, offset) CHECK_OFFSET(name, offset)
+#define FIELD32(number, name, offset) CHECK_OFFSET(name, offset)
+#define FIELD64(number, name, offset) CHECK_OFFSET(name, offset)
+#define FIELD(number, name, offset) CHECK_OFFSET(name, offset)
+
+static void vmx_check_vmcs12_offsets(void) {
+#include "vmcs12.h"
 }
 
 /*
@@ -879,14 +595,6 @@  static struct pi_desc *vcpu_to_pi_desc(struct kvm_vcpu *vcpu)
 	return &(to_vmx(vcpu)->pi_desc);
 }
 
-#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
-#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x)
-#define FIELD(number, name)	[ROL16(number, 6)] = VMCS12_OFFSET(name)
-#define FIELD64(number, name)						\
-	FIELD(number, name),						\
-	[ROL16(number##_HIGH, 6)] = VMCS12_OFFSET(name) + sizeof(u32)
-
-
 static u16 shadow_read_only_fields[] = {
 #define SHADOW_FIELD_RO(x) x,
 #include "vmx_shadow_fields.h"
@@ -901,150 +609,19 @@  static u16 shadow_read_write_fields[] = {
 static int max_shadow_read_write_fields =
 	ARRAY_SIZE(shadow_read_write_fields);
 
+#define ROL16(val, n) ((u16)(((u16)(val) << (n)) | ((u16)(val) >> (16 - (n)))))
+#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x)
+#define FIELD(number, name, offset)	[ROL16(number, 6)] = VMCS12_OFFSET(name),
+#define FIELD16(number, name, offset)	FIELD(number, name, offset)
+#define FIELD32(number, name, offset)	FIELD(number, name, offset)
+#define FIELD64(number, name, offset)						\
+		FIELD(number, name, offset)					\
+		[ROL16(number##_HIGH, 6)] = VMCS12_OFFSET(name) + sizeof(u32),
+#define NOFIELD(type, name, offset)
+#define PADDING(type, name, size, offset)
+
 static const unsigned short vmcs_field_to_offset_table[] = {
-	FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id),
-	FIELD(POSTED_INTR_NV, posted_intr_nv),
-	FIELD(GUEST_ES_SELECTOR, guest_es_selector),
-	FIELD(GUEST_CS_SELECTOR, guest_cs_selector),
-	FIELD(GUEST_SS_SELECTOR, guest_ss_selector),
-	FIELD(GUEST_DS_SELECTOR, guest_ds_selector),
-	FIELD(GUEST_FS_SELECTOR, guest_fs_selector),
-	FIELD(GUEST_GS_SELECTOR, guest_gs_selector),
-	FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector),
-	FIELD(GUEST_TR_SELECTOR, guest_tr_selector),
-	FIELD(GUEST_INTR_STATUS, guest_intr_status),
-	FIELD(GUEST_PML_INDEX, guest_pml_index),
-	FIELD(HOST_ES_SELECTOR, host_es_selector),
-	FIELD(HOST_CS_SELECTOR, host_cs_selector),
-	FIELD(HOST_SS_SELECTOR, host_ss_selector),
-	FIELD(HOST_DS_SELECTOR, host_ds_selector),
-	FIELD(HOST_FS_SELECTOR, host_fs_selector),
-	FIELD(HOST_GS_SELECTOR, host_gs_selector),
-	FIELD(HOST_TR_SELECTOR, host_tr_selector),
-	FIELD64(IO_BITMAP_A, io_bitmap_a),
-	FIELD64(IO_BITMAP_B, io_bitmap_b),
-	FIELD64(MSR_BITMAP, msr_bitmap),
-	FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr),
-	FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr),
-	FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr),
-	FIELD64(PML_ADDRESS, pml_address),
-	FIELD64(TSC_OFFSET, tsc_offset),
-	FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr),
-	FIELD64(APIC_ACCESS_ADDR, apic_access_addr),
-	FIELD64(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr),
-	FIELD64(VM_FUNCTION_CONTROL, vm_function_control),
-	FIELD64(EPT_POINTER, ept_pointer),
-	FIELD64(EOI_EXIT_BITMAP0, eoi_exit_bitmap0),
-	FIELD64(EOI_EXIT_BITMAP1, eoi_exit_bitmap1),
-	FIELD64(EOI_EXIT_BITMAP2, eoi_exit_bitmap2),
-	FIELD64(EOI_EXIT_BITMAP3, eoi_exit_bitmap3),
-	FIELD64(EPTP_LIST_ADDRESS, eptp_list_address),
-	FIELD64(VMREAD_BITMAP, vmread_bitmap),
-	FIELD64(VMWRITE_BITMAP, vmwrite_bitmap),
-	FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap),
-	FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address),
-	FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer),
-	FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl),
-	FIELD64(GUEST_IA32_PAT, guest_ia32_pat),
-	FIELD64(GUEST_IA32_EFER, guest_ia32_efer),
-	FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl),
-	FIELD64(GUEST_PDPTR0, guest_pdptr0),
-	FIELD64(GUEST_PDPTR1, guest_pdptr1),
-	FIELD64(GUEST_PDPTR2, guest_pdptr2),
-	FIELD64(GUEST_PDPTR3, guest_pdptr3),
-	FIELD64(GUEST_BNDCFGS, guest_bndcfgs),
-	FIELD64(HOST_IA32_PAT, host_ia32_pat),
-	FIELD64(HOST_IA32_EFER, host_ia32_efer),
-	FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl),
-	FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control),
-	FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control),
-	FIELD(EXCEPTION_BITMAP, exception_bitmap),
-	FIELD(PAGE_FAULT_ERROR_CODE_MASK, page_fault_error_code_mask),
-	FIELD(PAGE_FAULT_ERROR_CODE_MATCH, page_fault_error_code_match),
-	FIELD(CR3_TARGET_COUNT, cr3_target_count),
-	FIELD(VM_EXIT_CONTROLS, vm_exit_controls),
-	FIELD(VM_EXIT_MSR_STORE_COUNT, vm_exit_msr_store_count),
-	FIELD(VM_EXIT_MSR_LOAD_COUNT, vm_exit_msr_load_count),
-	FIELD(VM_ENTRY_CONTROLS, vm_entry_controls),
-	FIELD(VM_ENTRY_MSR_LOAD_COUNT, vm_entry_msr_load_count),
-	FIELD(VM_ENTRY_INTR_INFO_FIELD, vm_entry_intr_info_field),
-	FIELD(VM_ENTRY_EXCEPTION_ERROR_CODE, vm_entry_exception_error_code),
-	FIELD(VM_ENTRY_INSTRUCTION_LEN, vm_entry_instruction_len),
-	FIELD(TPR_THRESHOLD, tpr_threshold),
-	FIELD(SECONDARY_VM_EXEC_CONTROL, secondary_vm_exec_control),
-	FIELD(VM_INSTRUCTION_ERROR, vm_instruction_error),
-	FIELD(VM_EXIT_REASON, vm_exit_reason),
-	FIELD(VM_EXIT_INTR_INFO, vm_exit_intr_info),
-	FIELD(VM_EXIT_INTR_ERROR_CODE, vm_exit_intr_error_code),
-	FIELD(IDT_VECTORING_INFO_FIELD, idt_vectoring_info_field),
-	FIELD(IDT_VECTORING_ERROR_CODE, idt_vectoring_error_code),
-	FIELD(VM_EXIT_INSTRUCTION_LEN, vm_exit_instruction_len),
-	FIELD(VMX_INSTRUCTION_INFO, vmx_instruction_info),
-	FIELD(GUEST_ES_LIMIT, guest_es_limit),
-	FIELD(GUEST_CS_LIMIT, guest_cs_limit),
-	FIELD(GUEST_SS_LIMIT, guest_ss_limit),
-	FIELD(GUEST_DS_LIMIT, guest_ds_limit),
-	FIELD(GUEST_FS_LIMIT, guest_fs_limit),
-	FIELD(GUEST_GS_LIMIT, guest_gs_limit),
-	FIELD(GUEST_LDTR_LIMIT, guest_ldtr_limit),
-	FIELD(GUEST_TR_LIMIT, guest_tr_limit),
-	FIELD(GUEST_GDTR_LIMIT, guest_gdtr_limit),
-	FIELD(GUEST_IDTR_LIMIT, guest_idtr_limit),
-	FIELD(GUEST_ES_AR_BYTES, guest_es_ar_bytes),
-	FIELD(GUEST_CS_AR_BYTES, guest_cs_ar_bytes),
-	FIELD(GUEST_SS_AR_BYTES, guest_ss_ar_bytes),
-	FIELD(GUEST_DS_AR_BYTES, guest_ds_ar_bytes),
-	FIELD(GUEST_FS_AR_BYTES, guest_fs_ar_bytes),
-	FIELD(GUEST_GS_AR_BYTES, guest_gs_ar_bytes),
-	FIELD(GUEST_LDTR_AR_BYTES, guest_ldtr_ar_bytes),
-	FIELD(GUEST_TR_AR_BYTES, guest_tr_ar_bytes),
-	FIELD(GUEST_INTERRUPTIBILITY_INFO, guest_interruptibility_info),
-	FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
-	FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
-	FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
-	FIELD(VMX_PREEMPTION_TIMER_VALUE, vmx_preemption_timer_value),
-	FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask),
-	FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask),
-	FIELD(CR0_READ_SHADOW, cr0_read_shadow),
-	FIELD(CR4_READ_SHADOW, cr4_read_shadow),
-	FIELD(CR3_TARGET_VALUE0, cr3_target_value0),
-	FIELD(CR3_TARGET_VALUE1, cr3_target_value1),
-	FIELD(CR3_TARGET_VALUE2, cr3_target_value2),
-	FIELD(CR3_TARGET_VALUE3, cr3_target_value3),
-	FIELD(EXIT_QUALIFICATION, exit_qualification),
-	FIELD(GUEST_LINEAR_ADDRESS, guest_linear_address),
-	FIELD(GUEST_CR0, guest_cr0),
-	FIELD(GUEST_CR3, guest_cr3),
-	FIELD(GUEST_CR4, guest_cr4),
-	FIELD(GUEST_ES_BASE, guest_es_base),
-	FIELD(GUEST_CS_BASE, guest_cs_base),
-	FIELD(GUEST_SS_BASE, guest_ss_base),
-	FIELD(GUEST_DS_BASE, guest_ds_base),
-	FIELD(GUEST_FS_BASE, guest_fs_base),
-	FIELD(GUEST_GS_BASE, guest_gs_base),
-	FIELD(GUEST_LDTR_BASE, guest_ldtr_base),
-	FIELD(GUEST_TR_BASE, guest_tr_base),
-	FIELD(GUEST_GDTR_BASE, guest_gdtr_base),
-	FIELD(GUEST_IDTR_BASE, guest_idtr_base),
-	FIELD(GUEST_DR7, guest_dr7),
-	FIELD(GUEST_RSP, guest_rsp),
-	FIELD(GUEST_RIP, guest_rip),
-	FIELD(GUEST_RFLAGS, guest_rflags),
-	FIELD(GUEST_PENDING_DBG_EXCEPTIONS, guest_pending_dbg_exceptions),
-	FIELD(GUEST_SYSENTER_ESP, guest_sysenter_esp),
-	FIELD(GUEST_SYSENTER_EIP, guest_sysenter_eip),
-	FIELD(HOST_CR0, host_cr0),
-	FIELD(HOST_CR3, host_cr3),
-	FIELD(HOST_CR4, host_cr4),
-	FIELD(HOST_FS_BASE, host_fs_base),
-	FIELD(HOST_GS_BASE, host_gs_base),
-	FIELD(HOST_TR_BASE, host_tr_base),
-	FIELD(HOST_GDTR_BASE, host_gdtr_base),
-	FIELD(HOST_IDTR_BASE, host_idtr_base),
-	FIELD(HOST_IA32_SYSENTER_ESP, host_ia32_sysenter_esp),
-	FIELD(HOST_IA32_SYSENTER_EIP, host_ia32_sysenter_eip),
-	FIELD(HOST_RSP, host_rsp),
-	FIELD(HOST_RIP, host_rip),
+#include "vmcs12.h"
 };
 
 static inline short vmcs_field_to_offset(unsigned long field)