From 6c09fb82edbf8c19be0a3ea3e1e823c8891ee5a1 Mon Sep 17 00:00:00 2001 From: Marios Pomonis Date: Thu, 27 Mar 2025 01:49:18 -0700 Subject: executor/kvm: bug fix and minor refactor in KVM * Fixes a bug when setting up a 64-bit guest by making the bit manipulation macros produce unsigned long long: To create a VCPU that has paging enabled, one needs to set the CR0.PE and CR0.PG bits in CR0. The latter is problematic when setting up a 64-bit guest since if the macro is not using 1ULL, it sign extends the output (in 64-bit mode the control registers are extended to 64-bits with some of the CR0[32:63] bits reserved). This results in either failing the KVM_SET_SREGS ioctl (in newer kernel versions) or just failing the KVM_RUN ioctl with EXIT_REASON_INVALID_STATE. * Moved the bit manipulation definitions from the amd64 specific to the generic kvm header to consolidate them with the already existing ones. Prefixed them with X86_ to avoid confusion. --- executor/kvm.h | 202 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 131 insertions(+), 71 deletions(-) (limited to 'executor/kvm.h') diff --git a/executor/kvm.h b/executor/kvm.h index d72913bc3..df89d9fb6 100644 --- a/executor/kvm.h +++ b/executor/kvm.h @@ -1,81 +1,141 @@ // Copyright 2017 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. -#define ADDR_TEXT 0x0000 -#define ADDR_GDT 0x1000 -#define ADDR_LDT 0x1800 -#define ADDR_PML4 0x2000 -#define ADDR_PDP 0x3000 -#define ADDR_PD 0x4000 -#define ADDR_STACK0 0x0f80 -#define ADDR_VAR_HLT 0x2800 -#define ADDR_VAR_SYSRET 0x2808 -#define ADDR_VAR_SYSEXIT 0x2810 -#define ADDR_VAR_IDT 0x3800 -#define ADDR_VAR_TSS64 0x3a00 -#define ADDR_VAR_TSS64_CPL3 0x3c00 -#define ADDR_VAR_TSS16 0x3d00 -#define ADDR_VAR_TSS16_2 0x3e00 -#define ADDR_VAR_TSS16_CPL3 0x3f00 -#define ADDR_VAR_TSS32 0x4800 -#define ADDR_VAR_TSS32_2 0x4a00 -#define ADDR_VAR_TSS32_CPL3 0x4c00 -#define ADDR_VAR_TSS32_VM86 0x4e00 -#define ADDR_VAR_VMXON_PTR 0x5f00 -#define ADDR_VAR_VMCS_PTR 0x5f08 -#define ADDR_VAR_VMEXIT_PTR 0x5f10 -#define ADDR_VAR_VMWRITE_FLD 0x5f18 -#define ADDR_VAR_VMWRITE_VAL 0x5f20 -#define ADDR_VAR_VMXON 0x6000 -#define ADDR_VAR_VMCS 0x7000 -#define ADDR_VAR_VMEXIT_CODE 0x9000 -#define ADDR_VAR_USER_CODE 0x9100 -#define ADDR_VAR_USER_CODE2 0x9120 +#define X86_ADDR_TEXT 0x0000 +#define X86_ADDR_GDT 0x1000 +#define X86_ADDR_LDT 0x1800 +#define X86_ADDR_PML4 0x2000 +#define X86_ADDR_PDP 0x3000 +#define X86_ADDR_PD 0x4000 +#define X86_ADDR_STACK0 0x0f80 +#define X86_ADDR_VAR_HLT 0x2800 +#define X86_ADDR_VAR_SYSRET 0x2808 +#define X86_ADDR_VAR_SYSEXIT 0x2810 +#define X86_ADDR_VAR_IDT 0x3800 +#define X86_ADDR_VAR_TSS64 0x3a00 +#define X86_ADDR_VAR_TSS64_CPL3 0x3c00 +#define X86_ADDR_VAR_TSS16 0x3d00 +#define X86_ADDR_VAR_TSS16_2 0x3e00 +#define X86_ADDR_VAR_TSS16_CPL3 0x3f00 +#define X86_ADDR_VAR_TSS32 0x4800 +#define X86_ADDR_VAR_TSS32_2 0x4a00 +#define X86_ADDR_VAR_TSS32_CPL3 0x4c00 +#define X86_ADDR_VAR_TSS32_VM86 0x4e00 +#define X86_ADDR_VAR_VMXON_PTR 0x5f00 +#define X86_ADDR_VAR_VMCS_PTR 0x5f08 +#define X86_ADDR_VAR_VMEXIT_PTR 0x5f10 +#define X86_ADDR_VAR_VMWRITE_FLD 0x5f18 +#define X86_ADDR_VAR_VMWRITE_VAL 0x5f20 +#define X86_ADDR_VAR_VMXON 0x6000 +#define X86_ADDR_VAR_VMCS 0x7000 +#define X86_ADDR_VAR_VMEXIT_CODE 0x9000 +#define X86_ADDR_VAR_USER_CODE 0x9100 +#define X86_ADDR_VAR_USER_CODE2 0x9120 -#define SEL_LDT (1 << 3) -#define SEL_CS16 (2 << 3) -#define SEL_DS16 (3 << 3) -#define SEL_CS16_CPL3 ((4 << 3) + 3) -#define SEL_DS16_CPL3 ((5 << 3) + 3) -#define SEL_CS32 (6 << 3) -#define SEL_DS32 (7 << 3) -#define SEL_CS32_CPL3 ((8 << 3) + 3) -#define SEL_DS32_CPL3 ((9 << 3) + 3) -#define SEL_CS64 (10 << 3) -#define SEL_DS64 (11 << 3) -#define SEL_CS64_CPL3 ((12 << 3) + 3) -#define SEL_DS64_CPL3 ((13 << 3) + 3) -#define SEL_CGATE16 (14 << 3) -#define SEL_TGATE16 (15 << 3) -#define SEL_CGATE32 (16 << 3) -#define SEL_TGATE32 (17 << 3) -#define SEL_CGATE64 (18 << 3) -#define SEL_CGATE64_HI (19 << 3) -#define SEL_TSS16 (20 << 3) -#define SEL_TSS16_2 (21 << 3) -#define SEL_TSS16_CPL3 ((22 << 3) + 3) -#define SEL_TSS32 (23 << 3) -#define SEL_TSS32_2 (24 << 3) -#define SEL_TSS32_CPL3 ((25 << 3) + 3) -#define SEL_TSS32_VM86 (26 << 3) -#define SEL_TSS64 (27 << 3) -#define SEL_TSS64_HI (28 << 3) -#define SEL_TSS64_CPL3 ((29 << 3) + 3) -#define SEL_TSS64_CPL3_HI (30 << 3) +#define X86_CR0_PE 1ULL +#define X86_CR0_MP (1ULL << 1) +#define X86_CR0_EM (1ULL << 2) +#define X86_CR0_TS (1ULL << 3) +#define X86_CR0_ET (1ULL << 4) +#define X86_CR0_NE (1ULL << 5) +#define X86_CR0_WP (1ULL << 16) +#define X86_CR0_AM (1ULL << 18) +#define X86_CR0_NW (1ULL << 29) +#define X86_CR0_CD (1ULL << 30) +#define X86_CR0_PG (1ULL << 31) -#define MSR_IA32_FEATURE_CONTROL 0x3a -#define MSR_IA32_VMX_BASIC 0x480 -#define MSR_IA32_SMBASE 0x9e -#define MSR_IA32_SYSENTER_CS 0x174 -#define MSR_IA32_SYSENTER_ESP 0x175 -#define MSR_IA32_SYSENTER_EIP 0x176 -#define MSR_IA32_STAR 0xC0000081 -#define MSR_IA32_LSTAR 0xC0000082 -#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B +#define X86_CR4_VME 1ULL +#define X86_CR4_PVI (1ULL << 1) +#define X86_CR4_TSD (1ULL << 2) +#define X86_CR4_DE (1ULL << 3) +#define X86_CR4_PSE (1ULL << 4) +#define X86_CR4_PAE (1ULL << 5) +#define X86_CR4_MCE (1ULL << 6) +#define X86_CR4_PGE (1ULL << 7) +#define X86_CR4_PCE (1ULL << 8) +#define X86_CR4_OSFXSR (1ULL << 8) +#define X86_CR4_OSXMMEXCPT (1ULL << 10) +#define X86_CR4_UMIP (1ULL << 11) +#define X86_CR4_VMXE (1ULL << 13) +#define X86_CR4_SMXE (1ULL << 14) +#define X86_CR4_FSGSBASE (1ULL << 16) +#define X86_CR4_PCIDE (1ULL << 17) +#define X86_CR4_OSXSAVE (1ULL << 18) +#define X86_CR4_SMEP (1ULL << 20) +#define X86_CR4_SMAP (1ULL << 21) +#define X86_CR4_PKE (1ULL << 22) -#define NEXT_INSN $0xbadc0de -#define PREFIX_SIZE 0xba1d +#define X86_EFER_SCE 1ULL +#define X86_EFER_LME (1ULL << 8) +#define X86_EFER_LMA (1ULL << 10) +#define X86_EFER_NXE (1ULL << 11) +#define X86_EFER_SVME (1ULL << 12) +#define X86_EFER_LMSLE (1ULL << 13) +#define X86_EFER_FFXSR (1ULL << 14) +#define X86_EFER_TCE (1ULL << 15) +// 32-bit page directory entry bits +#define X86_PDE32_PRESENT 1UL +#define X86_PDE32_RW (1UL << 1) +#define X86_PDE32_USER (1UL << 2) +#define X86_PDE32_PS (1UL << 7) + +// 64-bit page * entry bits +#define X86_PDE64_PRESENT 1 +#define X86_PDE64_RW (1ULL << 1) +#define X86_PDE64_USER (1ULL << 2) +#define X86_PDE64_ACCESSED (1ULL << 5) +#define X86_PDE64_DIRTY (1ULL << 6) +#define X86_PDE64_PS (1ULL << 7) +#define X86_PDE64_G (1ULL << 8) + +#define X86_SEL_LDT (1 << 3) +#define X86_SEL_CS16 (2 << 3) +#define X86_SEL_DS16 (3 << 3) +#define X86_SEL_CS16_CPL3 ((4 << 3) + 3) +#define X86_SEL_DS16_CPL3 ((5 << 3) + 3) +#define X86_SEL_CS32 (6 << 3) +#define X86_SEL_DS32 (7 << 3) +#define X86_SEL_CS32_CPL3 ((8 << 3) + 3) +#define X86_SEL_DS32_CPL3 ((9 << 3) + 3) +#define X86_SEL_CS64 (10 << 3) +#define X86_SEL_DS64 (11 << 3) +#define X86_SEL_CS64_CPL3 ((12 << 3) + 3) +#define X86_SEL_DS64_CPL3 ((13 << 3) + 3) +#define X86_SEL_CGATE16 (14 << 3) +#define X86_SEL_TGATE16 (15 << 3) +#define X86_SEL_CGATE32 (16 << 3) +#define X86_SEL_TGATE32 (17 << 3) +#define X86_SEL_CGATE64 (18 << 3) +#define X86_SEL_CGATE64_HI (19 << 3) +#define X86_SEL_TSS16 (20 << 3) +#define X86_SEL_TSS16_2 (21 << 3) +#define X86_SEL_TSS16_CPL3 ((22 << 3) + 3) +#define X86_SEL_TSS32 (23 << 3) +#define X86_SEL_TSS32_2 (24 << 3) +#define X86_SEL_TSS32_CPL3 ((25 << 3) + 3) +#define X86_SEL_TSS32_VM86 (26 << 3) +#define X86_SEL_TSS64 (27 << 3) +#define X86_SEL_TSS64_HI (28 << 3) +#define X86_SEL_TSS64_CPL3 ((29 << 3) + 3) +#define X86_SEL_TSS64_CPL3_HI (30 << 3) + +#define X86_MSR_IA32_FEATURE_CONTROL 0x3a +#define X86_MSR_IA32_VMX_BASIC 0x480 +#define X86_MSR_IA32_SMBASE 0x9e +#define X86_MSR_IA32_SYSENTER_CS 0x174 +#define X86_MSR_IA32_SYSENTER_ESP 0x175 +#define X86_MSR_IA32_SYSENTER_EIP 0x176 +#define X86_MSR_IA32_STAR 0xC0000081 +#define X86_MSR_IA32_LSTAR 0xC0000082 +#define X86_MSR_IA32_VMX_PROCBASED_CTLS2 0x48B + +#define X86_NEXT_INSN $0xbadc0de +#define X86_PREFIX_SIZE 0xba1d + +#define KVM_MAX_VCPU 4 +#define KVM_PAGE_SIZE (1 << 12) +#define KVM_GUEST_MEM_SIZE (1024 * KVM_PAGE_SIZE) #define SZ_4K 0x00001000 #define SZ_64K 0x00010000 -- cgit mrf-deployment