From b503717d28e8f7eff39bf38624e6cf42687d951a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 19 Nov 2015 16:52:33 -0200 Subject: [PATCH 01/15] target-i386: Define structs for layout of xsave area Add structs that define the layout of the xsave areas used by Intel processors. Add some QEMU_BUILD_BUG_ON lines to ensure the structs match the XSAVE_* macros in target-i386/kvm.c and the offsets and sizes at target-i386/cpu.c:ext_save_areas. Signed-off-by: Eduardo Habkost --- target-i386/cpu.h | 95 +++++++++++++++++++++++++++++++++++++++++++++++ target-i386/kvm.c | 23 ++++++++++++ 2 files changed, 118 insertions(+) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 5cf2422efb..a91d000407 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -830,6 +830,101 @@ typedef struct { #define NB_OPMASK_REGS 8 +typedef union X86LegacyXSaveArea { + struct { + uint16_t fcw; + uint16_t fsw; + uint8_t ftw; + uint8_t reserved; + uint16_t fpop; + uint64_t fpip; + uint64_t fpdp; + uint32_t mxcsr; + uint32_t mxcsr_mask; + FPReg fpregs[8]; + uint8_t xmm_regs[16][16]; + }; + uint8_t data[512]; +} X86LegacyXSaveArea; + +typedef struct X86XSaveHeader { + uint64_t xstate_bv; + uint64_t xcomp_bv; + uint8_t reserved[48]; +} X86XSaveHeader; + +/* Ext. save area 2: AVX State */ +typedef struct XSaveAVX { + uint8_t ymmh[16][16]; +} XSaveAVX; + +/* Ext. save area 3: BNDREG */ +typedef struct XSaveBNDREG { + BNDReg bnd_regs[4]; +} XSaveBNDREG; + +/* Ext. save area 4: BNDCSR */ +typedef union XSaveBNDCSR { + BNDCSReg bndcsr; + uint8_t data[64]; +} XSaveBNDCSR; + +/* Ext. save area 5: Opmask */ +typedef struct XSaveOpmask { + uint64_t opmask_regs[NB_OPMASK_REGS]; +} XSaveOpmask; + +/* Ext. save area 6: ZMM_Hi256 */ +typedef struct XSaveZMM_Hi256 { + uint8_t zmm_hi256[16][32]; +} XSaveZMM_Hi256; + +/* Ext. save area 7: Hi16_ZMM */ +typedef struct XSaveHi16_ZMM { + uint8_t hi16_zmm[16][64]; +} XSaveHi16_ZMM; + +/* Ext. save area 9: PKRU state */ +typedef struct XSavePKRU { + uint32_t pkru; + uint32_t padding; +} XSavePKRU; + +typedef struct X86XSaveArea { + X86LegacyXSaveArea legacy; + X86XSaveHeader header; + + /* Extended save areas: */ + + /* AVX State: */ + XSaveAVX avx_state; + uint8_t padding[960 - 576 - sizeof(XSaveAVX)]; + /* MPX State: */ + XSaveBNDREG bndreg_state; + XSaveBNDCSR bndcsr_state; + /* AVX-512 State: */ + XSaveOpmask opmask_state; + XSaveZMM_Hi256 zmm_hi256_state; + XSaveHi16_ZMM hi16_zmm_state; + /* PKRU State: */ + XSavePKRU pkru_state; +} X86XSaveArea; + +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != 0x240); +QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != 0x3c0); +QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != 0x400); +QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != 0x440); +QEMU_BUILD_BUG_ON(sizeof(XSaveOpmask) != 0x40); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != 0x480); +QEMU_BUILD_BUG_ON(sizeof(XSaveZMM_Hi256) != 0x200); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != 0x680); +QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != 0xA80); +QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); + typedef enum TPRAccess { TPR_ACCESS_READ, TPR_ACCESS_WRITE, diff --git a/target-i386/kvm.c b/target-i386/kvm.c index c76e7bbc89..6937016570 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1307,6 +1307,29 @@ static int kvm_put_fpu(X86CPU *cpu) #define XSAVE_Hi16_ZMM 416 #define XSAVE_PKRU 672 +#define XSAVE_BYTE_OFFSET(word_offset) \ + ((word_offset) * sizeof(((struct kvm_xsave *)0)->region[0])) + +#define ASSERT_OFFSET(word_offset, field) \ + QEMU_BUILD_BUG_ON(XSAVE_BYTE_OFFSET(word_offset) != \ + offsetof(X86XSaveArea, field)) + +ASSERT_OFFSET(XSAVE_FCW_FSW, legacy.fcw); +ASSERT_OFFSET(XSAVE_FTW_FOP, legacy.ftw); +ASSERT_OFFSET(XSAVE_CWD_RIP, legacy.fpip); +ASSERT_OFFSET(XSAVE_CWD_RDP, legacy.fpdp); +ASSERT_OFFSET(XSAVE_MXCSR, legacy.mxcsr); +ASSERT_OFFSET(XSAVE_ST_SPACE, legacy.fpregs); +ASSERT_OFFSET(XSAVE_XMM_SPACE, legacy.xmm_regs); +ASSERT_OFFSET(XSAVE_XSTATE_BV, header.xstate_bv); +ASSERT_OFFSET(XSAVE_YMMH_SPACE, avx_state); +ASSERT_OFFSET(XSAVE_BNDREGS, bndreg_state); +ASSERT_OFFSET(XSAVE_BNDCSR, bndcsr_state); +ASSERT_OFFSET(XSAVE_OPMASK, opmask_state); +ASSERT_OFFSET(XSAVE_ZMM_Hi256, zmm_hi256_state); +ASSERT_OFFSET(XSAVE_Hi16_ZMM, hi16_zmm_state); +ASSERT_OFFSET(XSAVE_PKRU, pkru_state); + static int kvm_put_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; From ee1b09f695dcd8532f470e53297473bd3bc88718 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 28 Nov 2015 14:32:26 -0200 Subject: [PATCH 02/15] target-i386: Use xsave structs for ext_save_area This doesn't introduce any change in the code, as the offsets and struct sizes match what was present in the table. This can be validated by the QEMU_BUILD_BUG_ON lines on target-i386/cpu.h, which ensures the struct sizes and offsets match the existing values in ext_save_area. Signed-off-by: Eduardo Habkost --- target-i386/cpu.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 05bf5ed2f0..e9ef39b634 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -474,25 +474,32 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { const ExtSaveArea x86_ext_save_areas[] = { [XSTATE_YMM_BIT] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX, - .offset = 0x240, .size = 0x100 }, + .offset = offsetof(X86XSaveArea, avx_state), + .size = sizeof(XSaveAVX) }, [XSTATE_BNDREGS_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, - .offset = 0x3c0, .size = 0x40 }, + .offset = offsetof(X86XSaveArea, bndreg_state), + .size = sizeof(XSaveBNDREG) }, [XSTATE_BNDCSR_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, - .offset = 0x400, .size = 0x40 }, + .offset = offsetof(X86XSaveArea, bndcsr_state), + .size = sizeof(XSaveBNDCSR) }, [XSTATE_OPMASK_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, - .offset = 0x440, .size = 0x40 }, + .offset = offsetof(X86XSaveArea, opmask_state), + .size = sizeof(XSaveOpmask) }, [XSTATE_ZMM_Hi256_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, - .offset = 0x480, .size = 0x200 }, + .offset = offsetof(X86XSaveArea, zmm_hi256_state), + .size = sizeof(XSaveZMM_Hi256) }, [XSTATE_Hi16_ZMM_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, - .offset = 0x680, .size = 0x400 }, + .offset = offsetof(X86XSaveArea, hi16_zmm_state), + .size = sizeof(XSaveHi16_ZMM) }, [XSTATE_PKRU_BIT] = { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU, - .offset = 0xA80, .size = 0x8 }, + .offset = offsetof(X86XSaveArea, pkru_state), + .size = sizeof(XSavePKRU) }, }; const char *get_register_name_32(unsigned int reg) From 86cd2ea071b925d9fa231abb3e0f1ecfb5633f91 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Mon, 23 Nov 2015 10:43:26 -0200 Subject: [PATCH 03/15] target-i386: kvm: Use X86XSaveArea struct for xsave save/load Instead of using offset macros and bit operations in a uint32_t array, use the X86XSaveArea struct to perform the loading/saving operations in kvm_put_xsave() and kvm_get_xsave(). Signed-off-by: Eduardo Habkost --- target-i386/kvm.c | 78 +++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 6937016570..084183510a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1333,9 +1333,8 @@ ASSERT_OFFSET(XSAVE_PKRU, pkru_state); static int kvm_put_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; - struct kvm_xsave* xsave = env->kvm_xsave_buf; + X86XSaveArea *xsave = env->kvm_xsave_buf; uint16_t cwd, swd, twd; - uint8_t *xmm, *ymmh, *zmmh; int i, r; if (!has_xsave) { @@ -1350,25 +1349,26 @@ static int kvm_put_xsave(X86CPU *cpu) for (i = 0; i < 8; ++i) { twd |= (!env->fptags[i]) << i; } - xsave->region[XSAVE_FCW_FSW] = (uint32_t)(swd << 16) + cwd; - xsave->region[XSAVE_FTW_FOP] = (uint32_t)(env->fpop << 16) + twd; - memcpy(&xsave->region[XSAVE_CWD_RIP], &env->fpip, sizeof(env->fpip)); - memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp)); - memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs, + xsave->legacy.fcw = cwd; + xsave->legacy.fsw = swd; + xsave->legacy.ftw = twd; + xsave->legacy.fpop = env->fpop; + xsave->legacy.fpip = env->fpip; + xsave->legacy.fpdp = env->fpdp; + memcpy(&xsave->legacy.fpregs, env->fpregs, sizeof env->fpregs); - xsave->region[XSAVE_MXCSR] = env->mxcsr; - *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv; - memcpy(&xsave->region[XSAVE_BNDREGS], env->bnd_regs, + xsave->legacy.mxcsr = env->mxcsr; + xsave->header.xstate_bv = env->xstate_bv; + memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs, sizeof env->bnd_regs); - memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs, - sizeof(env->bndcs_regs)); - memcpy(&xsave->region[XSAVE_OPMASK], env->opmask_regs, + xsave->bndcsr_state.bndcsr = env->bndcs_regs; + memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs, sizeof env->opmask_regs); - xmm = (uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; - ymmh = (uint8_t *)&xsave->region[XSAVE_YMMH_SPACE]; - zmmh = (uint8_t *)&xsave->region[XSAVE_ZMM_Hi256]; - for (i = 0; i < CPU_NB_REGS; i++, xmm += 16, ymmh += 16, zmmh += 32) { + for (i = 0; i < CPU_NB_REGS; i++) { + uint8_t *xmm = xsave->legacy.xmm_regs[i]; + uint8_t *ymmh = xsave->avx_state.ymmh[i]; + uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i]; stq_p(xmm, env->xmm_regs[i].ZMM_Q(0)); stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1)); stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2)); @@ -1380,9 +1380,9 @@ static int kvm_put_xsave(X86CPU *cpu) } #ifdef TARGET_X86_64 - memcpy(&xsave->region[XSAVE_Hi16_ZMM], &env->xmm_regs[16], + memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16], 16 * sizeof env->xmm_regs[16]); - memcpy(&xsave->region[XSAVE_PKRU], &env->pkru, sizeof env->pkru); + memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru); #endif r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave); return r; @@ -1771,9 +1771,8 @@ static int kvm_get_fpu(X86CPU *cpu) static int kvm_get_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; - struct kvm_xsave* xsave = env->kvm_xsave_buf; + X86XSaveArea *xsave = env->kvm_xsave_buf; int ret, i; - const uint8_t *xmm, *ymmh, *zmmh; uint16_t cwd, swd, twd; if (!has_xsave) { @@ -1785,33 +1784,32 @@ static int kvm_get_xsave(X86CPU *cpu) return ret; } - cwd = (uint16_t)xsave->region[XSAVE_FCW_FSW]; - swd = (uint16_t)(xsave->region[XSAVE_FCW_FSW] >> 16); - twd = (uint16_t)xsave->region[XSAVE_FTW_FOP]; - env->fpop = (uint16_t)(xsave->region[XSAVE_FTW_FOP] >> 16); + cwd = xsave->legacy.fcw; + swd = xsave->legacy.fsw; + twd = xsave->legacy.ftw; + env->fpop = xsave->legacy.fpop; env->fpstt = (swd >> 11) & 7; env->fpus = swd; env->fpuc = cwd; for (i = 0; i < 8; ++i) { env->fptags[i] = !((twd >> i) & 1); } - memcpy(&env->fpip, &xsave->region[XSAVE_CWD_RIP], sizeof(env->fpip)); - memcpy(&env->fpdp, &xsave->region[XSAVE_CWD_RDP], sizeof(env->fpdp)); - env->mxcsr = xsave->region[XSAVE_MXCSR]; - memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE], + env->fpip = xsave->legacy.fpip; + env->fpdp = xsave->legacy.fpdp; + env->mxcsr = xsave->legacy.mxcsr; + memcpy(env->fpregs, &xsave->legacy.fpregs, sizeof env->fpregs); - env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV]; - memcpy(env->bnd_regs, &xsave->region[XSAVE_BNDREGS], + env->xstate_bv = xsave->header.xstate_bv; + memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs, sizeof env->bnd_regs); - memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR], - sizeof(env->bndcs_regs)); - memcpy(env->opmask_regs, &xsave->region[XSAVE_OPMASK], + env->bndcs_regs = xsave->bndcsr_state.bndcsr; + memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs, sizeof env->opmask_regs); - xmm = (const uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; - ymmh = (const uint8_t *)&xsave->region[XSAVE_YMMH_SPACE]; - zmmh = (const uint8_t *)&xsave->region[XSAVE_ZMM_Hi256]; - for (i = 0; i < CPU_NB_REGS; i++, xmm += 16, ymmh += 16, zmmh += 32) { + for (i = 0; i < CPU_NB_REGS; i++) { + uint8_t *xmm = xsave->legacy.xmm_regs[i]; + uint8_t *ymmh = xsave->avx_state.ymmh[i]; + uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i]; env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm); env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8); env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh); @@ -1823,9 +1821,9 @@ static int kvm_get_xsave(X86CPU *cpu) } #ifdef TARGET_X86_64 - memcpy(&env->xmm_regs[16], &xsave->region[XSAVE_Hi16_ZMM], + memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm, 16 * sizeof env->xmm_regs[16]); - memcpy(&env->pkru, &xsave->region[XSAVE_PKRU], sizeof env->pkru); + memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru); #endif return 0; } From d494352c2f7818aeba184a8ef757569083740bb2 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 9 Apr 2016 16:42:44 -0300 Subject: [PATCH 04/15] osdep: Move default qemu_hw_version() value to a macro The macro will be used by code that will stop calling qemu_hw_version() at runtime and just need a constant value. Signed-off-by: Eduardo Habkost --- include/qemu/osdep.h | 9 +++++++++ util/osdep.c | 9 +-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 994bfa023a..693769403f 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -327,6 +327,15 @@ static inline void qemu_timersub(const struct timeval *val1, void qemu_set_cloexec(int fd); +/* Starting on QEMU 2.5, qemu_hw_version() returns "2.5+" by default + * instead of QEMU_VERSION, so setting hw_version on MachineClass + * is no longer mandatory. + * + * Do NOT change this string, or it will break compatibility on all + * machine classes that don't set hw_version. + */ +#define QEMU_HW_VERSION "2.5+" + /* QEMU "hardware version" setting. Used to replace code that exposed * QEMU_VERSION to guests in the past and need to keep compatibility. * Do not use qemu_hw_version() in new code. diff --git a/util/osdep.c b/util/osdep.c index d56d071111..9a7a439e13 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -44,14 +44,7 @@ extern int madvise(caddr_t, size_t, int); static bool fips_enabled = false; -/* Starting on QEMU 2.5, qemu_hw_version() returns "2.5+" by default - * instead of QEMU_VERSION, so setting hw_version on MachineClass - * is no longer mandatory. - * - * Do NOT change this string, or it will break compatibility on all - * machine classes that don't set hw_version. - */ -static const char *hw_version = "2.5+"; +static const char *hw_version = QEMU_HW_VERSION; int socket_set_cork(int fd, int v) { From cd6c1b7057bc897675897f44d15277c3a6e7b118 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 9 Apr 2016 16:26:38 -0300 Subject: [PATCH 05/15] pc: Set CPU model-id on compat_props for pc <= 2.4 Instead of relying on x86_cpudef_setup() calling qemu_hw_version(), just make old machines set model-id explicitly on compat_props for qemu64, qemu32, and athlon. This will allow us to eliminate x86_cpudef_setup() later. Reviewed-by: Michael S. Tsirkin Signed-off-by: Eduardo Habkost --- hw/i386/pc_piix.c | 13 +++++++++++++ include/hw/i386/pc.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 32918bb294..24e7042680 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -582,6 +582,7 @@ DEFINE_I440FX_MACHINE(v1_4, "pc-i440fx-1.4", pc_compat_1_4, #define PC_COMPAT_1_3 \ + PC_CPU_MODEL_IDS("1.3.0") \ {\ .driver = "usb-tablet",\ .property = "usb_version",\ @@ -613,6 +614,7 @@ DEFINE_I440FX_MACHINE(v1_3, "pc-1.3", pc_compat_1_3, #define PC_COMPAT_1_2 \ + PC_CPU_MODEL_IDS("1.2.0") \ {\ .driver = "nec-usb-xhci",\ .property = "msi",\ @@ -651,6 +653,7 @@ DEFINE_I440FX_MACHINE(v1_2, "pc-1.2", pc_compat_1_2, #define PC_COMPAT_1_1 \ + PC_CPU_MODEL_IDS("1.1.0") \ {\ .driver = "virtio-scsi-pci",\ .property = "hotplug",\ @@ -693,6 +696,7 @@ DEFINE_I440FX_MACHINE(v1_1, "pc-1.1", pc_compat_1_2, #define PC_COMPAT_1_0 \ + PC_CPU_MODEL_IDS("1.0") \ {\ .driver = TYPE_ISA_FDC,\ .property = "check_media_rate",\ @@ -722,10 +726,14 @@ DEFINE_I440FX_MACHINE(v1_0, "pc-1.0", pc_compat_1_2, pc_i440fx_1_0_machine_options); +#define PC_COMPAT_0_15 \ + PC_CPU_MODEL_IDS("0.15") + static void pc_i440fx_0_15_machine_options(MachineClass *m) { pc_i440fx_1_0_machine_options(m); m->hw_version = "0.15"; + SET_MACHINE_COMPAT(m, PC_COMPAT_0_15); } DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2, @@ -733,6 +741,7 @@ DEFINE_I440FX_MACHINE(v0_15, "pc-0.15", pc_compat_1_2, #define PC_COMPAT_0_14 \ + PC_CPU_MODEL_IDS("0.14") \ {\ .driver = "virtio-blk-pci",\ .property = "event_idx",\ @@ -771,6 +780,7 @@ DEFINE_I440FX_MACHINE(v0_14, "pc-0.14", pc_compat_1_2, #define PC_COMPAT_0_13 \ + PC_CPU_MODEL_IDS("0.13") \ {\ .driver = TYPE_PCI_DEVICE,\ .property = "command_serr_enable",\ @@ -807,6 +817,7 @@ DEFINE_I440FX_MACHINE(v0_13, "pc-0.13", pc_compat_0_13, #define PC_COMPAT_0_12 \ + PC_CPU_MODEL_IDS("0.12") \ {\ .driver = "virtio-serial-pci",\ .property = "max_ports",\ @@ -841,6 +852,7 @@ DEFINE_I440FX_MACHINE(v0_12, "pc-0.12", pc_compat_0_13, #define PC_COMPAT_0_11 \ + PC_CPU_MODEL_IDS("0.11") \ {\ .driver = "virtio-blk-pci",\ .property = "vectors",\ @@ -871,6 +883,7 @@ DEFINE_I440FX_MACHINE(v0_11, "pc-0.11", pc_compat_0_13, #define PC_COMPAT_0_10 \ + PC_CPU_MODEL_IDS("0.10") \ {\ .driver = "virtio-blk-pci",\ .property = "class",\ diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 367b6dbf0e..9ca23098bd 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -359,8 +359,29 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); #define PC_COMPAT_2_5 \ HW_COMPAT_2_5 +/* Helper for setting model-id for CPU models that changed model-id + * depending on QEMU versions up to QEMU 2.4. + */ +#define PC_CPU_MODEL_IDS(v) \ + {\ + .driver = "qemu32-" TYPE_X86_CPU,\ + .property = "model-id",\ + .value = "QEMU Virtual CPU version " v,\ + },\ + {\ + .driver = "qemu64-" TYPE_X86_CPU,\ + .property = "model-id",\ + .value = "QEMU Virtual CPU version " v,\ + },\ + {\ + .driver = "athlon-" TYPE_X86_CPU,\ + .property = "model-id",\ + .value = "QEMU Virtual CPU version " v,\ + }, + #define PC_COMPAT_2_4 \ HW_COMPAT_2_4 \ + PC_CPU_MODEL_IDS("2.4.0") \ {\ .driver = "Haswell-" TYPE_X86_CPU,\ .property = "abm",\ @@ -431,6 +452,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); #define PC_COMPAT_2_3 \ HW_COMPAT_2_3 \ + PC_CPU_MODEL_IDS("2.3.0") \ {\ .driver = TYPE_X86_CPU,\ .property = "arat",\ @@ -511,6 +533,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); #define PC_COMPAT_2_2 \ HW_COMPAT_2_2 \ + PC_CPU_MODEL_IDS("2.3.0") \ {\ .driver = "kvm64" "-" TYPE_X86_CPU,\ .property = "vme",\ @@ -604,6 +627,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); #define PC_COMPAT_2_1 \ HW_COMPAT_2_1 \ + PC_CPU_MODEL_IDS("2.1.0") \ {\ .driver = "coreduo" "-" TYPE_X86_CPU,\ .property = "vmx",\ @@ -616,6 +640,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); }, #define PC_COMPAT_2_0 \ + PC_CPU_MODEL_IDS("2.0.0") \ {\ .driver = "virtio-scsi-pci",\ .property = "any_layout",\ @@ -675,6 +700,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); }, #define PC_COMPAT_1_7 \ + PC_CPU_MODEL_IDS("1.7.0") \ {\ .driver = TYPE_USB_DEVICE,\ .property = "msos-desc",\ @@ -692,6 +718,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); }, #define PC_COMPAT_1_6 \ + PC_CPU_MODEL_IDS("1.6.0") \ {\ .driver = "e1000",\ .property = "mitigation",\ @@ -715,6 +742,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); }, #define PC_COMPAT_1_5 \ + PC_CPU_MODEL_IDS("1.5.0") \ {\ .driver = "Conroe-" TYPE_X86_CPU,\ .property = "model",\ @@ -758,6 +786,7 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); }, #define PC_COMPAT_1_4 \ + PC_CPU_MODEL_IDS("1.4.0") \ {\ .driver = "scsi-hd",\ .property = "discard_granularity",\ From 9cf2cc3d8237732946720d78bf9aec0064026ed8 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Sat, 9 Apr 2016 16:44:20 -0300 Subject: [PATCH 06/15] target-i386: Set constant model_id for qemu64/qemu32/athlon Newer PC machines don't set hw_version, and older machines set model-id on compat_props explicitly, so we don't need the x86_cpudef_setup() code that sets model_id using qemu_hw_version() anymore. Signed-off-by: Eduardo Habkost --- target-i386/cpu.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e9ef39b634..14f64cb3b9 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -710,6 +710,7 @@ static X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM, .xlevel = 0x8000000A, + .model_id = "QEMU Virtual CPU version " QEMU_HW_VERSION, }, { .name = "phenom", @@ -806,6 +807,7 @@ static X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_1_ECX] = CPUID_EXT_SSE3, .xlevel = 0x80000004, + .model_id = "QEMU Virtual CPU version " QEMU_HW_VERSION, }, { .name = "kvm32", @@ -902,6 +904,7 @@ static X86CPUDefinition builtin_x86_defs[] = { .features[FEAT_8000_0001_EDX] = CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT, .xlevel = 0x80000008, + .model_id = "QEMU Virtual CPU version " QEMU_HW_VERSION, }, { .name = "n270", @@ -2271,28 +2274,8 @@ void cpu_clear_apic_feature(CPUX86State *env) #endif /* !CONFIG_USER_ONLY */ -/* Initialize list of CPU models, filling some non-static fields if necessary - */ void x86_cpudef_setup(void) { - int i, j; - static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" }; - - for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) { - X86CPUDefinition *def = &builtin_x86_defs[i]; - - /* Look for specific "cpudef" models that */ - /* have the QEMU version in .model_id */ - for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) { - if (strcmp(model_with_versions[j], def->name) == 0) { - pstrcpy(def->model_id, sizeof(def->model_id), - "QEMU Virtual CPU version "); - pstrcat(def->model_id, sizeof(def->model_id), - qemu_hw_version()); - break; - } - } - } } void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, From 3e2c0e062f0963a6b73b0cd1990fad79495463d9 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Fri, 30 Oct 2015 18:10:57 -0200 Subject: [PATCH 07/15] cpu: Eliminate cpudef_init(), cpudef_setup() x86_cpudef_init() doesn't do anything anymore, cpudef_init(), cpudef_setup(), and x86_cpudef_init() can be finally removed. Signed-off-by: Eduardo Habkost --- arch_init.c | 7 ------- bsd-user/main.c | 3 --- include/sysemu/arch_init.h | 1 - linux-user/main.c | 3 --- target-i386/cpu.c | 4 ---- target-i386/cpu.h | 2 -- vl.c | 7 ------- 7 files changed, 27 deletions(-) diff --git a/arch_init.c b/arch_init.c index 07f047fad4..fa059731ed 100644 --- a/arch_init.c +++ b/arch_init.c @@ -274,13 +274,6 @@ void do_smbios_option(QemuOpts *opts) #endif } -void cpudef_init(void) -{ -#if defined(cpudef_setup) - cpudef_setup(); /* parse cpu definitions in target config file */ -#endif -} - int kvm_available(void) { #ifdef CONFIG_KVM diff --git a/bsd-user/main.c b/bsd-user/main.c index 8e338c7f22..9f592be96f 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -753,9 +753,6 @@ int main(int argc, char **argv) } cpu_model = NULL; -#if defined(cpudef_setup) - cpudef_setup(); /* parse cpu definitions in target config file (TBD) */ -#endif optind = 1; for(;;) { diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index c38892fec6..d690dfabdf 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -30,7 +30,6 @@ extern const uint32_t arch_type; void select_soundhw(const char *optarg); void do_acpitable_option(const QemuOpts *opts); void do_smbios_option(QemuOpts *opts); -void cpudef_init(void); void audio_init(void); int kvm_available(void); int xen_available(void); diff --git a/linux-user/main.c b/linux-user/main.c index ba38aed431..95ed11d85c 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4154,9 +4154,6 @@ int main(int argc, char **argv, char **envp) } cpu_model = NULL; -#if defined(cpudef_setup) - cpudef_setup(); /* parse cpu definitions in target config file (TBD) */ -#endif srand(time(NULL)); diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 14f64cb3b9..e615486596 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2274,10 +2274,6 @@ void cpu_clear_apic_feature(CPUX86State *env) #endif /* !CONFIG_USER_ONLY */ -void x86_cpudef_setup(void) -{ -} - void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index a91d000407..cd26decaaf 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1225,7 +1225,6 @@ X86CPU *cpu_x86_init(const char *cpu_model); X86CPU *cpu_x86_create(const char *cpu_model, Error **errp); int cpu_x86_exec(CPUState *cpu); void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf); -void x86_cpudef_setup(void); int cpu_x86_support_mca_broadcast(CPUX86State *env); int cpu_get_pic_interrupt(CPUX86State *s); @@ -1403,7 +1402,6 @@ uint64_t cpu_get_tsc(CPUX86State *env); #define cpu_exec cpu_x86_exec #define cpu_signal_handler cpu_x86_signal_handler #define cpu_list x86_cpu_list -#define cpudef_setup x86_cpudef_setup /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _ksmap diff --git a/vl.c b/vl.c index 2569dbb8d8..18d1423e57 100644 --- a/vl.c +++ b/vl.c @@ -4047,13 +4047,6 @@ int main(int argc, char **argv, char **envp) qemu_set_hw_version(machine_class->hw_version); } - /* Init CPU def lists, based on config - * - Must be called after all the qemu_read_config_file() calls - * - Must be called before list_cpus() - * - Must be called before machine_class->init() - */ - cpudef_init(); - if (cpu_model && is_help_option(cpu_model)) { list_cpus(stdout, &fprintf, cpu_model); exit(0); From 4fe15cdedf8728e58b8e475f8b1a26fb16aa9caa Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 5 Mar 2015 13:43:16 -0300 Subject: [PATCH 08/15] target-i386: Move TCG initialization check to tcg_x86_init() Instead of requiring cpu.c to check if TCG was already initialized, simply let the function be called multiple times. Suggested-by: Igor Mammedov Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- target-i386/cpu.c | 4 +--- target-i386/translate.c | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e615486596..2dc3d3cf3b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -3088,7 +3088,6 @@ static void x86_cpu_initfn(Object *obj) X86CPUClass *xcc = X86_CPU_GET_CLASS(obj); CPUX86State *env = &cpu->env; FeatureWord w; - static int inited; cs->env_ptr = env; cpu_exec_init(cs, &error_abort); @@ -3139,8 +3138,7 @@ static void x86_cpu_initfn(Object *obj) x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort); /* init various static tables used in TCG mode */ - if (tcg_enabled() && !inited) { - inited = 1; + if (tcg_enabled()) { tcg_x86_init(); } } diff --git a/target-i386/translate.c b/target-i386/translate.c index 731b10de06..bf33e6b353 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -8144,6 +8144,12 @@ void tcg_x86_init(void) "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub" }; int i; + static bool initialized; + + if (initialized) { + return; + } + initialized = true; cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); cpu_cc_op = tcg_global_mem_new_i32(cpu_env, From 57f2453ab48a771b30aeced01b329ee85853bb7b Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 12 Feb 2015 22:57:44 -0200 Subject: [PATCH 09/15] target-i386: Move TCG initialization to realize time QOM instance_init functions are not supposed to have any side-effects, as new objects may be created at any moment for querying property information (see qmp_device_list_properties()). Move TCG initialization to realize time so it won't be called when just doing object_new() on a X86CPU subclass. Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- target-i386/cpu.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 2dc3d3cf3b..9ac2e59151 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2902,6 +2902,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) } + if (tcg_enabled()) { + tcg_x86_init(); + } + #ifndef CONFIG_USER_ONLY qemu_register_reset(x86_cpu_machine_reset_cb, cpu); @@ -3136,11 +3140,6 @@ static void x86_cpu_initfn(Object *obj) } x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort); - - /* init various static tables used in TCG mode */ - if (tcg_enabled()) { - tcg_x86_init(); - } } static int64_t x86_cpu_get_arch_id(CPUState *cs) From 42ecabaae16c0054dde6d8b0fdf90a8c7cce270d Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 12 Feb 2015 23:04:50 -0200 Subject: [PATCH 10/15] target-i386: Call cpu_exec_init() on realize QOM instance_init functions are not supposed to have any side-effects, as new objects may be created at any moment for querying property information (see qmp_device_list_properties()). Calling cpu_exec_init() also affects QEMU's ability to handle errors during CPU creation, as some actions done by cpu_exec_init() can't be reverted. Move cpu_exec_init() call to realize so a simple object_new() won't trigger it, and so that it is called after some basic validation of CPU parameters. Reviewed-by: Igor Mammedov Signed-off-by: Eduardo Habkost --- target-i386/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 9ac2e59151..895a386d3b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2902,6 +2902,8 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) } + cpu_exec_init(cs, &error_abort); + if (tcg_enabled()) { tcg_x86_init(); } @@ -3094,7 +3096,6 @@ static void x86_cpu_initfn(Object *obj) FeatureWord w; cs->env_ptr = env; - cpu_exec_init(cs, &error_abort); object_property_add(obj, "family", "int", x86_cpuid_version_get_family, From d71b62a165b6af463f376bd398cfc1aec4e2f213 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 16 Dec 2015 17:06:42 -0200 Subject: [PATCH 11/15] target-i386: kvm: Allocate kvm_msrs struct once per VCPU Instead of using 2400 bytes in the stack for 150 MSR entries in kvm_get_msrs() and kvm_put_msrs(), allocate a buffer once for each VCPU. Reviewed-by: Paolo Bonzini Signed-off-by: Eduardo Habkost --- target-i386/cpu.h | 4 ++++ target-i386/kvm.c | 37 +++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index cd26decaaf..0426459bba 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1124,6 +1124,8 @@ typedef struct CPUX86State { TPRAccess tpr_access_type; } CPUX86State; +struct kvm_msrs; + /** * X86CPU: * @env: #CPUX86State @@ -1176,6 +1178,8 @@ struct X86CPU { struct DeviceState *apic_state; struct MemoryRegion *cpu_as_root, *cpu_as_mem, *smram; Notifier machine_done; + + struct kvm_msrs *kvm_msr_buf; }; static inline X86CPU *x86_env_get_cpu(CPUX86State *env) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 084183510a..7ad9c32326 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -57,6 +57,9 @@ #define MSR_KVM_WALL_CLOCK 0x11 #define MSR_KVM_SYSTEM_TIME 0x12 +#define MSR_BUF_SIZE \ + (sizeof(struct kvm_msrs) + 150 * sizeof(struct kvm_msr_entry)) + #ifndef BUS_MCEERR_AR #define BUS_MCEERR_AR 4 #endif @@ -914,6 +917,7 @@ int kvm_arch_init_vcpu(CPUState *cs) if (has_xsave) { env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); } + cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); if (env->features[FEAT_1_EDX] & CPUID_MTRR) { has_msr_mtrr = true; @@ -1462,6 +1466,11 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry, entry->data = value; } +static void kvm_msr_buf_reset(X86CPU *cpu) +{ + memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); +} + static int kvm_put_tscdeadline_msr(X86CPU *cpu) { CPUX86State *env = &cpu->env; @@ -1528,14 +1537,12 @@ static int kvm_put_msr_feature_control(X86CPU *cpu) static int kvm_put_msrs(X86CPU *cpu, int level) { CPUX86State *env = &cpu->env; - struct { - struct kvm_msrs info; - struct kvm_msr_entry entries[150]; - } msr_data; - struct kvm_msr_entry *msrs = msr_data.entries; + struct kvm_msr_entry *msrs = cpu->kvm_msr_buf->entries; int n = 0, i; int ret; + kvm_msr_buf_reset(cpu); + kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs); kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip); @@ -1724,11 +1731,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) } } - msr_data.info = (struct kvm_msrs) { - .nmsrs = n, - }; + cpu->kvm_msr_buf->nmsrs = n; - ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { return ret; } @@ -1944,13 +1949,11 @@ static int kvm_get_sregs(X86CPU *cpu) static int kvm_get_msrs(X86CPU *cpu) { CPUX86State *env = &cpu->env; - struct { - struct kvm_msrs info; - struct kvm_msr_entry entries[150]; - } msr_data; - struct kvm_msr_entry *msrs = msr_data.entries; + struct kvm_msr_entry *msrs = cpu->kvm_msr_buf->entries; int ret, i, n; + kvm_msr_buf_reset(cpu); + n = 0; msrs[n++].index = MSR_IA32_SYSENTER_CS; msrs[n++].index = MSR_IA32_SYSENTER_ESP; @@ -2092,11 +2095,9 @@ static int kvm_get_msrs(X86CPU *cpu) } } - msr_data.info = (struct kvm_msrs) { - .nmsrs = n, - }; + cpu->kvm_msr_buf->nmsrs = n; - ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { return ret; } From d1138251bf712cc076cdbbfd68aae3c8792bfcf9 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 16 Dec 2015 17:06:43 -0200 Subject: [PATCH 12/15] target-i386: kvm: Increase MSR_BUF_SIZE We are dangerously close to the array limits in kvm_put_msrs() and kvm_get_msrs(): with the default mcg_cap configuration, we can set up to 148 MSRs in kvm_put_msrs(), and if we allow mcg_cap to be changed, we can write up to 236 MSRs. Use 4096 bytes for the buffer, that can hold 255 kvm_msr_entry structs. Reviewed-by: Paolo Bonzini Signed-off-by: Eduardo Habkost --- target-i386/kvm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 7ad9c32326..1c20e3ce5b 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -57,8 +57,9 @@ #define MSR_KVM_WALL_CLOCK 0x11 #define MSR_KVM_SYSTEM_TIME 0x12 -#define MSR_BUF_SIZE \ - (sizeof(struct kvm_msrs) + 150 * sizeof(struct kvm_msr_entry)) +/* A 4096-byte buffer can hold the 8-byte kvm_msrs header, plus + * 255 kvm_msr_entry structs */ +#define MSR_BUF_SIZE 4096 #ifndef BUS_MCEERR_AR #define BUS_MCEERR_AR 4 From 9c600a84544dfedff238f6e0cfac0d88c58654c0 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 16 Dec 2015 17:06:44 -0200 Subject: [PATCH 13/15] target-i386: kvm: Simplify MSR array construction Add a helper function that appends new entries to the MSR buffer and checks for the buffer size limit. Reviewed-by: Paolo Bonzini Signed-off-by: Eduardo Habkost --- target-i386/kvm.c | 291 ++++++++++++++++++++++------------------------ 1 file changed, 140 insertions(+), 151 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 1c20e3ce5b..dbe0f907a2 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1472,6 +1472,18 @@ static void kvm_msr_buf_reset(X86CPU *cpu) memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); } +static void kvm_msr_entry_add(X86CPU *cpu, uint32_t index, uint64_t value) +{ + struct kvm_msrs *msrs = cpu->kvm_msr_buf; + void *limit = ((void *)msrs) + MSR_BUF_SIZE; + struct kvm_msr_entry *entry = &msrs->entries[msrs->nmsrs]; + + assert((void *)(entry + 1) <= limit); + + kvm_msr_entry_set(entry, index, value); + msrs->nmsrs++; +} + static int kvm_put_tscdeadline_msr(X86CPU *cpu) { CPUX86State *env = &cpu->env; @@ -1538,47 +1550,46 @@ static int kvm_put_msr_feature_control(X86CPU *cpu) static int kvm_put_msrs(X86CPU *cpu, int level) { CPUX86State *env = &cpu->env; - struct kvm_msr_entry *msrs = cpu->kvm_msr_buf->entries; - int n = 0, i; + int i; int ret; kvm_msr_buf_reset(cpu); - kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs); - kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); - kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip); - kvm_msr_entry_set(&msrs[n++], MSR_PAT, env->pat); + kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_CS, env->sysenter_cs); + kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_ESP, env->sysenter_esp); + kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_EIP, env->sysenter_eip); + kvm_msr_entry_add(cpu, MSR_PAT, env->pat); if (has_msr_star) { - kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star); + kvm_msr_entry_add(cpu, MSR_STAR, env->star); } if (has_msr_hsave_pa) { - kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave); + kvm_msr_entry_add(cpu, MSR_VM_HSAVE_PA, env->vm_hsave); } if (has_msr_tsc_aux) { - kvm_msr_entry_set(&msrs[n++], MSR_TSC_AUX, env->tsc_aux); + kvm_msr_entry_add(cpu, MSR_TSC_AUX, env->tsc_aux); } if (has_msr_tsc_adjust) { - kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust); + kvm_msr_entry_add(cpu, MSR_TSC_ADJUST, env->tsc_adjust); } if (has_msr_misc_enable) { - kvm_msr_entry_set(&msrs[n++], MSR_IA32_MISC_ENABLE, + kvm_msr_entry_add(cpu, MSR_IA32_MISC_ENABLE, env->msr_ia32_misc_enable); } if (has_msr_smbase) { - kvm_msr_entry_set(&msrs[n++], MSR_IA32_SMBASE, env->smbase); + kvm_msr_entry_add(cpu, MSR_IA32_SMBASE, env->smbase); } if (has_msr_bndcfgs) { - kvm_msr_entry_set(&msrs[n++], MSR_IA32_BNDCFGS, env->msr_bndcfgs); + kvm_msr_entry_add(cpu, MSR_IA32_BNDCFGS, env->msr_bndcfgs); } if (has_msr_xss) { - kvm_msr_entry_set(&msrs[n++], MSR_IA32_XSS, env->xss); + kvm_msr_entry_add(cpu, MSR_IA32_XSS, env->xss); } #ifdef TARGET_X86_64 if (lm_capable_kernel) { - kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar); - kvm_msr_entry_set(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase); - kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask); - kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar); + kvm_msr_entry_add(cpu, MSR_CSTAR, env->cstar); + kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, env->kernelgsbase); + kvm_msr_entry_add(cpu, MSR_FMASK, env->fmask); + kvm_msr_entry_add(cpu, MSR_LSTAR, env->lstar); } #endif /* @@ -1586,91 +1597,85 @@ static int kvm_put_msrs(X86CPU *cpu, int level) * for normal writeback. Limit them to reset or full state updates. */ if (level >= KVM_PUT_RESET_STATE) { - kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc); - kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, - env->system_time_msr); - kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr); + kvm_msr_entry_add(cpu, MSR_IA32_TSC, env->tsc); + kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, env->system_time_msr); + kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, env->wall_clock_msr); if (has_msr_async_pf_en) { - kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, - env->async_pf_en_msr); + kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr); } if (has_msr_pv_eoi_en) { - kvm_msr_entry_set(&msrs[n++], MSR_KVM_PV_EOI_EN, - env->pv_eoi_en_msr); + kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, env->pv_eoi_en_msr); } if (has_msr_kvm_steal_time) { - kvm_msr_entry_set(&msrs[n++], MSR_KVM_STEAL_TIME, - env->steal_time_msr); + kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, env->steal_time_msr); } if (has_msr_architectural_pmu) { /* Stop the counter. */ - kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL, 0); - kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, 0); + kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0); + kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0); /* Set the counter values. */ for (i = 0; i < MAX_FIXED_COUNTERS; i++) { - kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR0 + i, + kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i, env->msr_fixed_counters[i]); } for (i = 0; i < num_architectural_pmu_counters; i++) { - kvm_msr_entry_set(&msrs[n++], MSR_P6_PERFCTR0 + i, + kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i, env->msr_gp_counters[i]); - kvm_msr_entry_set(&msrs[n++], MSR_P6_EVNTSEL0 + i, + kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i, env->msr_gp_evtsel[i]); } - kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_STATUS, + kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS, env->msr_global_status); - kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_OVF_CTRL, + kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL, env->msr_global_ovf_ctrl); /* Now start the PMU. */ - kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL, + kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, env->msr_fixed_ctr_ctrl); - kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, + kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, env->msr_global_ctrl); } if (has_msr_hv_hypercall) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, + kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID, env->msr_hv_guest_os_id); - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, + kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL, env->msr_hv_hypercall); } if (has_msr_hv_vapic) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, + kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE, env->msr_hv_vapic); } if (has_msr_hv_tsc) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_REFERENCE_TSC, - env->msr_hv_tsc); + kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, env->msr_hv_tsc); } if (has_msr_hv_crash) { int j; for (j = 0; j < HV_X64_MSR_CRASH_PARAMS; j++) - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_CRASH_P0 + j, + kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_P0 + j, env->msr_hv_crash_params[j]); - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_CRASH_CTL, + kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_CTL, HV_X64_MSR_CRASH_CTL_NOTIFY); } if (has_msr_hv_runtime) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_VP_RUNTIME, - env->msr_hv_runtime); + kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, env->msr_hv_runtime); } if (cpu->hyperv_synic) { int j; - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SCONTROL, + kvm_msr_entry_add(cpu, HV_X64_MSR_SCONTROL, env->msr_hv_synic_control); - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SVERSION, + kvm_msr_entry_add(cpu, HV_X64_MSR_SVERSION, env->msr_hv_synic_version); - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIEFP, + kvm_msr_entry_add(cpu, HV_X64_MSR_SIEFP, env->msr_hv_synic_evt_page); - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIMP, + kvm_msr_entry_add(cpu, HV_X64_MSR_SIMP, env->msr_hv_synic_msg_page); for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SINT0 + j, + kvm_msr_entry_add(cpu, HV_X64_MSR_SINT0 + j, env->msr_hv_synic_sint[j]); } } @@ -1678,44 +1683,33 @@ static int kvm_put_msrs(X86CPU *cpu, int level) int j; for (j = 0; j < ARRAY_SIZE(env->msr_hv_stimer_config); j++) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_STIMER0_CONFIG + j*2, + kvm_msr_entry_add(cpu, HV_X64_MSR_STIMER0_CONFIG + j * 2, env->msr_hv_stimer_config[j]); } for (j = 0; j < ARRAY_SIZE(env->msr_hv_stimer_count); j++) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_STIMER0_COUNT + j*2, + kvm_msr_entry_add(cpu, HV_X64_MSR_STIMER0_COUNT + j * 2, env->msr_hv_stimer_count[j]); } } if (has_msr_mtrr) { - kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix64K_00000, env->mtrr_fixed[0]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix16K_80000, env->mtrr_fixed[1]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix16K_A0000, env->mtrr_fixed[2]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_C0000, env->mtrr_fixed[3]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_C8000, env->mtrr_fixed[4]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_D0000, env->mtrr_fixed[5]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_D8000, env->mtrr_fixed[6]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_E0000, env->mtrr_fixed[7]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_E8000, env->mtrr_fixed[8]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]); + kvm_msr_entry_add(cpu, MSR_MTRRdefType, env->mtrr_deftype); + kvm_msr_entry_add(cpu, MSR_MTRRfix64K_00000, env->mtrr_fixed[0]); + kvm_msr_entry_add(cpu, MSR_MTRRfix16K_80000, env->mtrr_fixed[1]); + kvm_msr_entry_add(cpu, MSR_MTRRfix16K_A0000, env->mtrr_fixed[2]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C0000, env->mtrr_fixed[3]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C8000, env->mtrr_fixed[4]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D0000, env->mtrr_fixed[5]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D8000, env->mtrr_fixed[6]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E0000, env->mtrr_fixed[7]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E8000, env->mtrr_fixed[8]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]); for (i = 0; i < MSR_MTRRcap_VCNT; i++) { - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRphysBase(i), env->mtrr_var[i].base); - kvm_msr_entry_set(&msrs[n++], - MSR_MTRRphysMask(i), env->mtrr_var[i].mask); + kvm_msr_entry_add(cpu, MSR_MTRRphysBase(i), + env->mtrr_var[i].base); + kvm_msr_entry_add(cpu, MSR_MTRRphysMask(i), + env->mtrr_var[i].mask); } } @@ -1725,21 +1719,19 @@ static int kvm_put_msrs(X86CPU *cpu, int level) if (env->mcg_cap) { int i; - kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status); - kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl); + kvm_msr_entry_add(cpu, MSR_MCG_STATUS, env->mcg_status); + kvm_msr_entry_add(cpu, MSR_MCG_CTL, env->mcg_ctl); for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) { - kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]); + kvm_msr_entry_add(cpu, MSR_MC0_CTL + i, env->mce_banks[i]); } } - cpu->kvm_msr_buf->nmsrs = n; - ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { return ret; } - assert(ret == n); + assert(ret == cpu->kvm_msr_buf->nmsrs); return 0; } @@ -1951,122 +1943,121 @@ static int kvm_get_msrs(X86CPU *cpu) { CPUX86State *env = &cpu->env; struct kvm_msr_entry *msrs = cpu->kvm_msr_buf->entries; - int ret, i, n; + int ret, i; kvm_msr_buf_reset(cpu); - n = 0; - msrs[n++].index = MSR_IA32_SYSENTER_CS; - msrs[n++].index = MSR_IA32_SYSENTER_ESP; - msrs[n++].index = MSR_IA32_SYSENTER_EIP; - msrs[n++].index = MSR_PAT; + kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_CS, 0); + kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_ESP, 0); + kvm_msr_entry_add(cpu, MSR_IA32_SYSENTER_EIP, 0); + kvm_msr_entry_add(cpu, MSR_PAT, 0); if (has_msr_star) { - msrs[n++].index = MSR_STAR; + kvm_msr_entry_add(cpu, MSR_STAR, 0); } if (has_msr_hsave_pa) { - msrs[n++].index = MSR_VM_HSAVE_PA; + kvm_msr_entry_add(cpu, MSR_VM_HSAVE_PA, 0); } if (has_msr_tsc_aux) { - msrs[n++].index = MSR_TSC_AUX; + kvm_msr_entry_add(cpu, MSR_TSC_AUX, 0); } if (has_msr_tsc_adjust) { - msrs[n++].index = MSR_TSC_ADJUST; + kvm_msr_entry_add(cpu, MSR_TSC_ADJUST, 0); } if (has_msr_tsc_deadline) { - msrs[n++].index = MSR_IA32_TSCDEADLINE; + kvm_msr_entry_add(cpu, MSR_IA32_TSCDEADLINE, 0); } if (has_msr_misc_enable) { - msrs[n++].index = MSR_IA32_MISC_ENABLE; + kvm_msr_entry_add(cpu, MSR_IA32_MISC_ENABLE, 0); } if (has_msr_smbase) { - msrs[n++].index = MSR_IA32_SMBASE; + kvm_msr_entry_add(cpu, MSR_IA32_SMBASE, 0); } if (has_msr_feature_control) { - msrs[n++].index = MSR_IA32_FEATURE_CONTROL; + kvm_msr_entry_add(cpu, MSR_IA32_FEATURE_CONTROL, 0); } if (has_msr_bndcfgs) { - msrs[n++].index = MSR_IA32_BNDCFGS; + kvm_msr_entry_add(cpu, MSR_IA32_BNDCFGS, 0); } if (has_msr_xss) { - msrs[n++].index = MSR_IA32_XSS; + kvm_msr_entry_add(cpu, MSR_IA32_XSS, 0); } if (!env->tsc_valid) { - msrs[n++].index = MSR_IA32_TSC; + kvm_msr_entry_add(cpu, MSR_IA32_TSC, 0); env->tsc_valid = !runstate_is_running(); } #ifdef TARGET_X86_64 if (lm_capable_kernel) { - msrs[n++].index = MSR_CSTAR; - msrs[n++].index = MSR_KERNELGSBASE; - msrs[n++].index = MSR_FMASK; - msrs[n++].index = MSR_LSTAR; + kvm_msr_entry_add(cpu, MSR_CSTAR, 0); + kvm_msr_entry_add(cpu, MSR_KERNELGSBASE, 0); + kvm_msr_entry_add(cpu, MSR_FMASK, 0); + kvm_msr_entry_add(cpu, MSR_LSTAR, 0); } #endif - msrs[n++].index = MSR_KVM_SYSTEM_TIME; - msrs[n++].index = MSR_KVM_WALL_CLOCK; + kvm_msr_entry_add(cpu, MSR_KVM_SYSTEM_TIME, 0); + kvm_msr_entry_add(cpu, MSR_KVM_WALL_CLOCK, 0); if (has_msr_async_pf_en) { - msrs[n++].index = MSR_KVM_ASYNC_PF_EN; + kvm_msr_entry_add(cpu, MSR_KVM_ASYNC_PF_EN, 0); } if (has_msr_pv_eoi_en) { - msrs[n++].index = MSR_KVM_PV_EOI_EN; + kvm_msr_entry_add(cpu, MSR_KVM_PV_EOI_EN, 0); } if (has_msr_kvm_steal_time) { - msrs[n++].index = MSR_KVM_STEAL_TIME; + kvm_msr_entry_add(cpu, MSR_KVM_STEAL_TIME, 0); } if (has_msr_architectural_pmu) { - msrs[n++].index = MSR_CORE_PERF_FIXED_CTR_CTRL; - msrs[n++].index = MSR_CORE_PERF_GLOBAL_CTRL; - msrs[n++].index = MSR_CORE_PERF_GLOBAL_STATUS; - msrs[n++].index = MSR_CORE_PERF_GLOBAL_OVF_CTRL; + kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR_CTRL, 0); + kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL, 0); + kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_STATUS, 0); + kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL, 0); for (i = 0; i < MAX_FIXED_COUNTERS; i++) { - msrs[n++].index = MSR_CORE_PERF_FIXED_CTR0 + i; + kvm_msr_entry_add(cpu, MSR_CORE_PERF_FIXED_CTR0 + i, 0); } for (i = 0; i < num_architectural_pmu_counters; i++) { - msrs[n++].index = MSR_P6_PERFCTR0 + i; - msrs[n++].index = MSR_P6_EVNTSEL0 + i; + kvm_msr_entry_add(cpu, MSR_P6_PERFCTR0 + i, 0); + kvm_msr_entry_add(cpu, MSR_P6_EVNTSEL0 + i, 0); } } if (env->mcg_cap) { - msrs[n++].index = MSR_MCG_STATUS; - msrs[n++].index = MSR_MCG_CTL; + kvm_msr_entry_add(cpu, MSR_MCG_STATUS, 0); + kvm_msr_entry_add(cpu, MSR_MCG_CTL, 0); for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) { - msrs[n++].index = MSR_MC0_CTL + i; + kvm_msr_entry_add(cpu, MSR_MC0_CTL + i, 0); } } if (has_msr_hv_hypercall) { - msrs[n++].index = HV_X64_MSR_HYPERCALL; - msrs[n++].index = HV_X64_MSR_GUEST_OS_ID; + kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL, 0); + kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID, 0); } if (has_msr_hv_vapic) { - msrs[n++].index = HV_X64_MSR_APIC_ASSIST_PAGE; + kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE, 0); } if (has_msr_hv_tsc) { - msrs[n++].index = HV_X64_MSR_REFERENCE_TSC; + kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, 0); } if (has_msr_hv_crash) { int j; for (j = 0; j < HV_X64_MSR_CRASH_PARAMS; j++) { - msrs[n++].index = HV_X64_MSR_CRASH_P0 + j; + kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_P0 + j, 0); } } if (has_msr_hv_runtime) { - msrs[n++].index = HV_X64_MSR_VP_RUNTIME; + kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, 0); } if (cpu->hyperv_synic) { uint32_t msr; - msrs[n++].index = HV_X64_MSR_SCONTROL; - msrs[n++].index = HV_X64_MSR_SVERSION; - msrs[n++].index = HV_X64_MSR_SIEFP; - msrs[n++].index = HV_X64_MSR_SIMP; + kvm_msr_entry_add(cpu, HV_X64_MSR_SCONTROL, 0); + kvm_msr_entry_add(cpu, HV_X64_MSR_SVERSION, 0); + kvm_msr_entry_add(cpu, HV_X64_MSR_SIEFP, 0); + kvm_msr_entry_add(cpu, HV_X64_MSR_SIMP, 0); for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) { - msrs[n++].index = msr; + kvm_msr_entry_add(cpu, msr, 0); } } if (has_msr_hv_stimer) { @@ -2074,36 +2065,34 @@ static int kvm_get_msrs(X86CPU *cpu) for (msr = HV_X64_MSR_STIMER0_CONFIG; msr <= HV_X64_MSR_STIMER3_COUNT; msr++) { - msrs[n++].index = msr; + kvm_msr_entry_add(cpu, msr, 0); } } if (has_msr_mtrr) { - msrs[n++].index = MSR_MTRRdefType; - msrs[n++].index = MSR_MTRRfix64K_00000; - msrs[n++].index = MSR_MTRRfix16K_80000; - msrs[n++].index = MSR_MTRRfix16K_A0000; - msrs[n++].index = MSR_MTRRfix4K_C0000; - msrs[n++].index = MSR_MTRRfix4K_C8000; - msrs[n++].index = MSR_MTRRfix4K_D0000; - msrs[n++].index = MSR_MTRRfix4K_D8000; - msrs[n++].index = MSR_MTRRfix4K_E0000; - msrs[n++].index = MSR_MTRRfix4K_E8000; - msrs[n++].index = MSR_MTRRfix4K_F0000; - msrs[n++].index = MSR_MTRRfix4K_F8000; + kvm_msr_entry_add(cpu, MSR_MTRRdefType, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix64K_00000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix16K_80000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix16K_A0000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C0000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_C8000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D0000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_D8000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E0000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_E8000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F0000, 0); + kvm_msr_entry_add(cpu, MSR_MTRRfix4K_F8000, 0); for (i = 0; i < MSR_MTRRcap_VCNT; i++) { - msrs[n++].index = MSR_MTRRphysBase(i); - msrs[n++].index = MSR_MTRRphysMask(i); + kvm_msr_entry_add(cpu, MSR_MTRRphysBase(i), 0); + kvm_msr_entry_add(cpu, MSR_MTRRphysMask(i), 0); } } - cpu->kvm_msr_buf->nmsrs = n; - ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { return ret; } - assert(ret == n); + assert(ret == cpu->kvm_msr_buf->nmsrs); for (i = 0; i < ret; i++) { uint32_t index = msrs[i].index; switch (index) { From e25ffda7bd9e8b10d4d08f944ad87c7523096de5 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 16 Dec 2015 17:06:45 -0200 Subject: [PATCH 14/15] target-i386: kvm: Simplify MSR setting functions Simplify kvm_put_tscdeadline_msr() and kvm_put_msr_feature_control() using kvm_msr_buf and the kvm_msr_entry_add() helper. Reviewed-by: Paolo Bonzini Signed-off-by: Eduardo Habkost --- target-i386/kvm.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index dbe0f907a2..0b56b38de8 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1487,24 +1487,16 @@ static void kvm_msr_entry_add(X86CPU *cpu, uint32_t index, uint64_t value) static int kvm_put_tscdeadline_msr(X86CPU *cpu) { CPUX86State *env = &cpu->env; - struct { - struct kvm_msrs info; - struct kvm_msr_entry entries[1]; - } msr_data; - struct kvm_msr_entry *msrs = msr_data.entries; int ret; if (!has_msr_tsc_deadline) { return 0; } - kvm_msr_entry_set(&msrs[0], MSR_IA32_TSCDEADLINE, env->tsc_deadline); + kvm_msr_buf_reset(cpu); + kvm_msr_entry_add(cpu, MSR_IA32_TSCDEADLINE, env->tsc_deadline); - msr_data.info = (struct kvm_msrs) { - .nmsrs = 1, - }; - - ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { return ret; } @@ -1521,24 +1513,17 @@ static int kvm_put_tscdeadline_msr(X86CPU *cpu) */ static int kvm_put_msr_feature_control(X86CPU *cpu) { - struct { - struct kvm_msrs info; - struct kvm_msr_entry entry; - } msr_data; int ret; if (!has_msr_feature_control) { return 0; } - kvm_msr_entry_set(&msr_data.entry, MSR_IA32_FEATURE_CONTROL, + kvm_msr_buf_reset(cpu); + kvm_msr_entry_add(cpu, MSR_IA32_FEATURE_CONTROL, cpu->env.msr_ia32_feature_control); - msr_data.info = (struct kvm_msrs) { - .nmsrs = 1, - }; - - ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); if (ret < 0) { return ret; } From 1abc2cae46b77ed345fd3eff88a49fe8f4b24abe Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 16 Dec 2015 17:06:46 -0200 Subject: [PATCH 15/15] target-i386: kvm: Eliminate kvm_msr_entry_set() Inline the function inside kvm_msr_entry_add(). Reviewed-by: Paolo Bonzini Signed-off-by: Eduardo Habkost --- target-i386/kvm.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 0b56b38de8..7b3667a089 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1459,14 +1459,6 @@ static int kvm_put_sregs(X86CPU *cpu) return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); } -static void kvm_msr_entry_set(struct kvm_msr_entry *entry, - uint32_t index, uint64_t value) -{ - entry->index = index; - entry->reserved = 0; - entry->data = value; -} - static void kvm_msr_buf_reset(X86CPU *cpu) { memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); @@ -1480,7 +1472,9 @@ static void kvm_msr_entry_add(X86CPU *cpu, uint32_t index, uint64_t value) assert((void *)(entry + 1) <= limit); - kvm_msr_entry_set(entry, index, value); + entry->index = index; + entry->reserved = 0; + entry->data = value; msrs->nmsrs++; }