diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/i386/TODO | 31 | ||||
-rw-r--r-- | target/i386/cpu.c | 42 | ||||
-rw-r--r-- | target/i386/cpu.h | 15 | ||||
-rw-r--r-- | target/i386/fpu_helper.c | 258 | ||||
-rw-r--r-- | target/i386/hax-all.c | 25 | ||||
-rw-r--r-- | target/i386/hax-i386.h | 7 | ||||
-rw-r--r-- | target/i386/hvf/hvf-i386.h | 37 | ||||
-rw-r--r-- | target/i386/hvf/hvf.c | 30 | ||||
-rw-r--r-- | target/i386/hvf/x86.c | 2 | ||||
-rw-r--r-- | target/i386/hvf/x86.h | 89 | ||||
-rw-r--r-- | target/i386/hvf/x86_decode.c | 25 | ||||
-rw-r--r-- | target/i386/hvf/x86_emu.c | 122 | ||||
-rw-r--r-- | target/i386/hvf/x86_flags.c | 81 | ||||
-rw-r--r-- | target/i386/hvf/x86_task.c | 10 | ||||
-rw-r--r-- | target/i386/hvf/x86hvf.c | 6 | ||||
-rw-r--r-- | target/i386/kvm.c | 34 | ||||
-rw-r--r-- | target/i386/misc_helper.c | 2 | ||||
-rw-r--r-- | target/i386/ops_sse.h | 57 | ||||
-rw-r--r-- | target/i386/sev.c | 257 | ||||
-rw-r--r-- | target/i386/sev_i386.h | 49 | ||||
-rw-r--r-- | target/ppc/cpu.h | 4 | ||||
-rw-r--r-- | target/ppc/kvm_ppc.h | 22 | ||||
-rw-r--r-- | target/ppc/translate_init.inc.c | 4 |
23 files changed, 704 insertions, 505 deletions
diff --git a/target/i386/TODO b/target/i386/TODO deleted file mode 100644 index a8d69cf87f..0000000000 --- a/target/i386/TODO +++ /dev/null @@ -1,31 +0,0 @@ -Correctness issues: - -- some eflags manipulation incorrectly reset the bit 0x2. -- SVM: test, cpu save/restore, SMM save/restore. -- x86_64: lcall/ljmp intel/amd differences ? -- better code fetch (different exception handling + CS.limit support) -- user/kernel PUSHL/POPL in helper.c -- add missing cpuid tests -- return UD exception if LOCK prefix incorrectly used -- test ldt limit < 7 ? -- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) -- full support of segment limit/rights -- full x87 exception support -- improve x87 bit exactness (use bochs code ?) -- DRx register support -- CR0.AC emulation -- SSE alignment checks - -Optimizations/Features: - -- add SVM nested paging support -- add VMX support -- add AVX support -- add SSE5 support -- fxsave/fxrstor AMD extensions -- improve monitor/mwait support -- faster EFLAGS update: consider SZAP, C, O can be updated separately - with a bit field in CC_OP and more state variables. -- evaluate x87 stack pointer statically -- find a way to avoid translating several time the same TB if CR0.TS - is set or not. diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 02065e35d4..4fe97f9b41 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -29,6 +29,7 @@ #include "sysemu/reset.h" #include "sysemu/hvf.h" #include "sysemu/cpus.h" +#include "sysemu/xen.h" #include "kvm_i386.h" #include "sev_i386.h" @@ -54,7 +55,6 @@ #include "hw/i386/topology.h" #ifndef CONFIG_USER_ONLY #include "exec/address-spaces.h" -#include "hw/xen/xen.h" #include "hw/i386/apic_internal.h" #include "hw/boards.h" #endif @@ -985,7 +985,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .feat_names = { NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", NULL, NULL, NULL, NULL, - NULL, NULL, "md-clear", NULL, + "avx512-vp2intersect", NULL, "md-clear", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* pconfig */, NULL, NULL, NULL, NULL, NULL, @@ -1139,6 +1139,22 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { .index = MSR_IA32_CORE_CAPABILITY, }, }, + [FEAT_PERF_CAPABILITIES] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, "full-width-write", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .msr = { + .index = MSR_IA32_PERF_CAPABILITIES, + }, + }, [FEAT_VMX_PROCBASED_CTLS] = { .type = MSR_FEATURE_WORD, @@ -1317,6 +1333,10 @@ static FeatureDep feature_dependencies[] = { .to = { FEAT_CORE_CAPABILITY, ~0ull }, }, { + .from = { FEAT_1_ECX, CPUID_EXT_PDCM }, + .to = { FEAT_PERF_CAPABILITIES, ~0ull }, + }, + { .from = { FEAT_1_ECX, CPUID_EXT_VMX }, .to = { FEAT_VMX_PROCBASED_CTLS, ~0ull }, }, @@ -5488,6 +5508,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ebx |= (cs->nr_cores * cs->nr_threads) << 16; *edx |= CPUID_HT; } + if (!cpu->enable_pmu) { + *ecx &= ~CPUID_EXT_PDCM; + } break; case 2: /* cache info: needed for Pentium Pro compatibility */ @@ -5837,11 +5860,20 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *eax = cpu->phys_bits; } *ebx = env->features[FEAT_8000_0008_EBX]; - *ecx = 0; - *edx = 0; if (cs->nr_cores * cs->nr_threads > 1) { - *ecx |= (cs->nr_cores * cs->nr_threads) - 1; + /* + * Bits 15:12 is "The number of bits in the initial + * Core::X86::Apic::ApicId[ApicId] value that indicate + * thread ID within a package". This is already stored at + * CPUX86State::pkg_offset. + * Bits 7:0 is "The number of threads in the package is NC+1" + */ + *ecx = (env->pkg_offset << 12) | + ((cs->nr_cores * cs->nr_threads) - 1); + } else { + *ecx = 0; } + *edx = 0; break; case 0x8000000A: if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 408392dbf6..7d77efd9e4 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -356,6 +356,8 @@ typedef enum X86Seg { #define MSR_IA32_ARCH_CAPABILITIES 0x10a #define ARCH_CAP_TSX_CTRL_MSR (1<<7) +#define MSR_IA32_PERF_CAPABILITIES 0x345 + #define MSR_IA32_TSX_CTRL 0x122 #define MSR_IA32_TSCDEADLINE 0x6e0 @@ -529,6 +531,7 @@ typedef enum FeatureWord { FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ FEAT_ARCH_CAPABILITIES, FEAT_CORE_CAPABILITY, + FEAT_PERF_CAPABILITIES, FEAT_VMX_PROCBASED_CTLS, FEAT_VMX_SECONDARY_CTLS, FEAT_VMX_PINBASED_CTLS, @@ -772,6 +775,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Multiply Accumulation Single Precision */ #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) +/* AVX512 Vector Pair Intersection to a Pair of Mask Registers */ +#define CPUID_7_0_EDX_AVX512_VP2INTERSECT (1U << 8) /* Speculation Control */ #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Single Thread Indirect Branch Predictors */ @@ -1361,6 +1366,11 @@ typedef struct CPUCaches { CPUCacheInfo *l3_cache; } CPUCaches; +typedef struct HVFX86LazyFlags { + target_ulong result; + target_ulong auxbits; +} HVFX86LazyFlags; + typedef struct CPUX86State { /* standard registers */ target_ulong regs[CPU_NB_REGS]; @@ -1584,6 +1594,7 @@ typedef struct CPUX86State { bool tsc_valid; int64_t tsc_khz; int64_t user_tsc_khz; /* for sanity check only */ + uint64_t apic_bus_freq; #if defined(CONFIG_KVM) || defined(CONFIG_HVF) void *xsave_buf; #endif @@ -1591,7 +1602,8 @@ typedef struct CPUX86State { struct kvm_nested_state *nested_state; #endif #if defined(CONFIG_HVF) - HVFX86EmulatorState *hvf_emul; + HVFX86LazyFlags hvf_lflags; + void *hvf_mmio_buf; #endif uint64_t mcg_cap; @@ -1633,6 +1645,7 @@ struct X86CPU { CPUNegativeOffsetState neg; CPUX86State env; + VMChangeStateEntry *vmsentry; uint64_t ucode_rev; diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index b34fa784eb..8ef5b463ea 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -59,8 +59,13 @@ #define FPUC_EM 0x3f #define floatx80_lg2 make_floatx80(0x3ffd, 0x9a209a84fbcff799LL) +#define floatx80_lg2_d make_floatx80(0x3ffd, 0x9a209a84fbcff798LL) #define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL) +#define floatx80_l2e_d make_floatx80(0x3fff, 0xb8aa3b295c17f0bbLL) #define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL) +#define floatx80_l2t_u make_floatx80(0x4000, 0xd49a784bcd1b8affLL) +#define floatx80_ln2_d make_floatx80(0x3ffe, 0xb17217f7d1cf79abLL) +#define floatx80_pi_d make_floatx80(0x4000, 0xc90fdaa22168c234LL) #if !defined(CONFIG_USER_ONLY) static qemu_irq ferr_irq; @@ -156,12 +161,32 @@ static void fpu_set_exception(CPUX86State *env, int mask) } } +static inline uint8_t save_exception_flags(CPUX86State *env) +{ + uint8_t old_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); + return old_flags; +} + +static void merge_exception_flags(CPUX86State *env, uint8_t old_flags) +{ + uint8_t new_flags = get_float_exception_flags(&env->fp_status); + float_raise(old_flags, &env->fp_status); + fpu_set_exception(env, + ((new_flags & float_flag_invalid ? FPUS_IE : 0) | + (new_flags & float_flag_divbyzero ? FPUS_ZE : 0) | + (new_flags & float_flag_overflow ? FPUS_OE : 0) | + (new_flags & float_flag_underflow ? FPUS_UE : 0) | + (new_flags & float_flag_inexact ? FPUS_PE : 0) | + (new_flags & float_flag_input_denormal ? FPUS_DE : 0))); +} + static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b) { - if (floatx80_is_zero(b)) { - fpu_set_exception(env, FPUS_ZE); - } - return floatx80_div(a, b, &env->fp_status); + uint8_t old_flags = save_exception_flags(env); + floatx80 ret = floatx80_div(a, b, &env->fp_status); + merge_exception_flags(env, old_flags); + return ret; } static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr) @@ -178,6 +203,7 @@ static void fpu_raise_exception(CPUX86State *env, uintptr_t retaddr) void helper_flds_FT0(CPUX86State *env, uint32_t val) { + uint8_t old_flags = save_exception_flags(env); union { float32 f; uint32_t i; @@ -185,10 +211,12 @@ void helper_flds_FT0(CPUX86State *env, uint32_t val) u.i = val; FT0 = float32_to_floatx80(u.f, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fldl_FT0(CPUX86State *env, uint64_t val) { + uint8_t old_flags = save_exception_flags(env); union { float64 f; uint64_t i; @@ -196,6 +224,7 @@ void helper_fldl_FT0(CPUX86State *env, uint64_t val) u.i = val; FT0 = float64_to_floatx80(u.f, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fildl_FT0(CPUX86State *env, int32_t val) @@ -205,6 +234,7 @@ void helper_fildl_FT0(CPUX86State *env, int32_t val) void helper_flds_ST0(CPUX86State *env, uint32_t val) { + uint8_t old_flags = save_exception_flags(env); int new_fpstt; union { float32 f; @@ -216,10 +246,12 @@ void helper_flds_ST0(CPUX86State *env, uint32_t val) env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ + merge_exception_flags(env, old_flags); } void helper_fldl_ST0(CPUX86State *env, uint64_t val) { + uint8_t old_flags = save_exception_flags(env); int new_fpstt; union { float64 f; @@ -231,6 +263,7 @@ void helper_fldl_ST0(CPUX86State *env, uint64_t val) env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ + merge_exception_flags(env, old_flags); } void helper_fildl_ST0(CPUX86State *env, int32_t val) @@ -255,90 +288,108 @@ void helper_fildll_ST0(CPUX86State *env, int64_t val) uint32_t helper_fsts_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); union { float32 f; uint32_t i; } u; u.f = floatx80_to_float32(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); return u.i; } uint64_t helper_fstl_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); union { float64 f; uint64_t i; } u; u.f = floatx80_to_float64(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); return u.i; } int32_t helper_fist_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int32_t val; val = floatx80_to_int32(ST0, &env->fp_status); if (val != (int16_t)val) { + set_float_exception_flags(float_flag_invalid, &env->fp_status); val = -32768; } + merge_exception_flags(env, old_flags); return val; } int32_t helper_fistl_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int32_t val; - signed char old_exp_flags; - - old_exp_flags = get_float_exception_flags(&env->fp_status); - set_float_exception_flags(0, &env->fp_status); val = floatx80_to_int32(ST0, &env->fp_status); if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { val = 0x80000000; } - set_float_exception_flags(get_float_exception_flags(&env->fp_status) - | old_exp_flags, &env->fp_status); + merge_exception_flags(env, old_flags); return val; } int64_t helper_fistll_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int64_t val; - signed char old_exp_flags; - - old_exp_flags = get_float_exception_flags(&env->fp_status); - set_float_exception_flags(0, &env->fp_status); val = floatx80_to_int64(ST0, &env->fp_status); if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { val = 0x8000000000000000ULL; } - set_float_exception_flags(get_float_exception_flags(&env->fp_status) - | old_exp_flags, &env->fp_status); + merge_exception_flags(env, old_flags); return val; } int32_t helper_fistt_ST0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int32_t val; val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status); if (val != (int16_t)val) { + set_float_exception_flags(float_flag_invalid, &env->fp_status); val = -32768; } + merge_exception_flags(env, old_flags); return val; } int32_t helper_fisttl_ST0(CPUX86State *env) { - return floatx80_to_int32_round_to_zero(ST0, &env->fp_status); + uint8_t old_flags = save_exception_flags(env); + int32_t val; + + val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x80000000; + } + merge_exception_flags(env, old_flags); + return val; } int64_t helper_fisttll_ST0(CPUX86State *env) { - return floatx80_to_int64_round_to_zero(ST0, &env->fp_status); + uint8_t old_flags = save_exception_flags(env); + int64_t val; + + val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x8000000000000000ULL; + } + merge_exception_flags(env, old_flags); + return val; } void helper_fldt_ST0(CPUX86State *env, target_ulong ptr) @@ -420,24 +471,29 @@ static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500}; void helper_fcom_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); FloatRelation ret; ret = floatx80_compare(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; + merge_exception_flags(env, old_flags); } void helper_fucom_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); FloatRelation ret; ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; + merge_exception_flags(env, old_flags); } static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; void helper_fcomi_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int eflags; FloatRelation ret; @@ -445,10 +501,12 @@ void helper_fcomi_ST0_FT0(CPUX86State *env) eflags = cpu_cc_compute_all(env, CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; + merge_exception_flags(env, old_flags); } void helper_fucomi_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); int eflags; FloatRelation ret; @@ -456,26 +514,35 @@ void helper_fucomi_ST0_FT0(CPUX86State *env) eflags = cpu_cc_compute_all(env, CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; + merge_exception_flags(env, old_flags); } void helper_fadd_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_add(ST0, FT0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fmul_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_mul(ST0, FT0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsub_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_sub(ST0, FT0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsubr_ST0_FT0(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_sub(FT0, ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fdiv_ST0_FT0(CPUX86State *env) @@ -492,22 +559,30 @@ void helper_fdivr_ST0_FT0(CPUX86State *env) void helper_fadd_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fmul_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsub_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsubr_STN_ST0(CPUX86State *env, int st_index) { + uint8_t old_flags = save_exception_flags(env); ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fdiv_STN_ST0(CPUX86State *env, int st_index) @@ -544,27 +619,66 @@ void helper_fld1_ST0(CPUX86State *env) void helper_fldl2t_ST0(CPUX86State *env) { - ST0 = floatx80_l2t; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_UP: + ST0 = floatx80_l2t_u; + break; + default: + ST0 = floatx80_l2t; + break; + } } void helper_fldl2e_ST0(CPUX86State *env) { - ST0 = floatx80_l2e; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_l2e_d; + break; + default: + ST0 = floatx80_l2e; + break; + } } void helper_fldpi_ST0(CPUX86State *env) { - ST0 = floatx80_pi; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_pi_d; + break; + default: + ST0 = floatx80_pi; + break; + } } void helper_fldlg2_ST0(CPUX86State *env) { - ST0 = floatx80_lg2; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_lg2_d; + break; + default: + ST0 = floatx80_lg2; + break; + } } void helper_fldln2_ST0(CPUX86State *env) { - ST0 = floatx80_ln2; + switch (env->fpuc & FPU_RC_MASK) { + case FPU_RC_DOWN: + case FPU_RC_CHOP: + ST0 = floatx80_ln2_d; + break; + default: + ST0 = floatx80_ln2; + break; + } } void helper_fldz_ST0(CPUX86State *env) @@ -679,14 +793,29 @@ void helper_fbld_ST0(CPUX86State *env, target_ulong ptr) void helper_fbst_ST0(CPUX86State *env, target_ulong ptr) { + uint8_t old_flags = save_exception_flags(env); int v; target_ulong mem_ref, mem_end; int64_t val; + CPU_LDoubleU temp; + + temp.d = ST0; val = floatx80_to_int64(ST0, &env->fp_status); mem_ref = ptr; + if (val >= 1000000000000000000LL || val <= -1000000000000000000LL) { + set_float_exception_flags(float_flag_invalid, &env->fp_status); + while (mem_ref < ptr + 7) { + cpu_stb_data_ra(env, mem_ref++, 0, GETPC()); + } + cpu_stb_data_ra(env, mem_ref++, 0xc0, GETPC()); + cpu_stb_data_ra(env, mem_ref++, 0xff, GETPC()); + cpu_stb_data_ra(env, mem_ref++, 0xff, GETPC()); + merge_exception_flags(env, old_flags); + return; + } mem_end = mem_ref + 9; - if (val < 0) { + if (SIGND(temp)) { cpu_stb_data_ra(env, mem_end, 0x80, GETPC()); val = -val; } else { @@ -704,6 +833,7 @@ void helper_fbst_ST0(CPUX86State *env, target_ulong ptr) while (mem_ref < mem_end) { cpu_stb_data_ra(env, mem_ref++, 0, GETPC()); } + merge_exception_flags(env, old_flags); } void helper_f2xm1(CPUX86State *env) @@ -757,6 +887,7 @@ void helper_fpatan(CPUX86State *env) void helper_fxtract(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); CPU_LDoubleU temp; temp.d = ST0; @@ -767,16 +898,40 @@ void helper_fxtract(CPUX86State *env) &env->fp_status); fpush(env); ST0 = temp.d; + } else if (floatx80_invalid_encoding(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + fpush(env); + ST0 = ST1; + } else if (floatx80_is_any_nan(ST0)) { + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_silence_nan(ST0, &env->fp_status); + } + fpush(env); + ST0 = ST1; + } else if (floatx80_is_infinity(ST0)) { + fpush(env); + ST0 = ST1; + ST1 = floatx80_infinity; } else { int expdif; - expdif = EXPD(temp) - EXPBIAS; + if (EXPD(temp) == 0) { + int shift = clz64(temp.l.lower); + temp.l.lower <<= shift; + expdif = 1 - EXPBIAS - shift; + float_raise(float_flag_input_denormal, &env->fp_status); + } else { + expdif = EXPD(temp) - EXPBIAS; + } /* DP exponent bias */ ST0 = int32_to_floatx80(expdif, &env->fp_status); fpush(env); BIASEXPONENT(temp); ST0 = temp.d; } + merge_exception_flags(env, old_flags); } void helper_fprem1(CPUX86State *env) @@ -916,11 +1071,13 @@ void helper_fyl2xp1(CPUX86State *env) void helper_fsqrt(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); if (floatx80_is_neg(ST0)) { env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */ env->fpus |= 0x400; } ST0 = floatx80_sqrt(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fsincos(CPUX86State *env) @@ -940,17 +1097,60 @@ void helper_fsincos(CPUX86State *env) void helper_frndint(CPUX86State *env) { + uint8_t old_flags = save_exception_flags(env); ST0 = floatx80_round_to_int(ST0, &env->fp_status); + merge_exception_flags(env, old_flags); } void helper_fscale(CPUX86State *env) { - if (floatx80_is_any_nan(ST1)) { + uint8_t old_flags = save_exception_flags(env); + if (floatx80_invalid_encoding(ST1) || floatx80_invalid_encoding(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else if (floatx80_is_any_nan(ST1)) { + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + } ST0 = ST1; + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_silence_nan(ST0, &env->fp_status); + } + } else if (floatx80_is_infinity(ST1) && + !floatx80_invalid_encoding(ST0) && + !floatx80_is_any_nan(ST0)) { + if (floatx80_is_neg(ST1)) { + if (floatx80_is_infinity(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else { + ST0 = (floatx80_is_neg(ST0) ? + floatx80_chs(floatx80_zero) : + floatx80_zero); + } + } else { + if (floatx80_is_zero(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + } else { + ST0 = (floatx80_is_neg(ST0) ? + floatx80_chs(floatx80_infinity) : + floatx80_infinity); + } + } } else { - int n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status); + int n; + signed char save = env->fp_status.floatx80_rounding_precision; + uint8_t save_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); + n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status); + set_float_exception_flags(save_flags, &env->fp_status); + env->fp_status.floatx80_rounding_precision = 80; ST0 = floatx80_scalbn(ST0, n, &env->fp_status); + env->fp_status.floatx80_rounding_precision = save; } + merge_exception_flags(env, old_flags); } void helper_fsin(CPUX86State *env) @@ -1000,7 +1200,7 @@ void helper_fxam_ST0(CPUX86State *env) if (expdif == MAXEXPD) { if (MANTD(temp) == 0x8000000000000000ULL) { env->fpus |= 0x500; /* Infinity */ - } else { + } else if (MANTD(temp) & 0x8000000000000000ULL) { env->fpus |= 0x100; /* NaN */ } } else if (expdif == 0) { @@ -1009,7 +1209,7 @@ void helper_fxam_ST0(CPUX86State *env) } else { env->fpus |= 0x4400; /* Denormal */ } - } else { + } else if (MANTD(temp) & 0x8000000000000000ULL) { env->fpus |= 0x400; } } diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c index f9c83fff25..c93bb23a44 100644 --- a/target/i386/hax-all.c +++ b/target/i386/hax-all.c @@ -232,10 +232,10 @@ int hax_init_vcpu(CPUState *cpu) return ret; } -struct hax_vm *hax_vm_create(struct hax_state *hax) +struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus) { struct hax_vm *vm; - int vm_id = 0, ret; + int vm_id = 0, ret, i; if (hax_invalid_fd(hax->fd)) { return NULL; @@ -245,6 +245,11 @@ struct hax_vm *hax_vm_create(struct hax_state *hax) return hax->vm; } + if (max_cpus > HAX_MAX_VCPU) { + fprintf(stderr, "Maximum VCPU number QEMU supported is %d\n", HAX_MAX_VCPU); + return NULL; + } + vm = g_new0(struct hax_vm, 1); ret = hax_host_create_vm(hax, &vm_id); @@ -259,6 +264,12 @@ struct hax_vm *hax_vm_create(struct hax_state *hax) goto error; } + vm->numvcpus = max_cpus; + vm->vcpus = g_new0(struct hax_vcpu_state *, vm->numvcpus); + for (i = 0; i < vm->numvcpus; i++) { + vm->vcpus[i] = NULL; + } + hax->vm = vm; return vm; @@ -272,12 +283,14 @@ int hax_vm_destroy(struct hax_vm *vm) { int i; - for (i = 0; i < HAX_MAX_VCPU; i++) + for (i = 0; i < vm->numvcpus; i++) if (vm->vcpus[i]) { fprintf(stderr, "VCPU should be cleaned before vm clean\n"); return -1; } hax_close_fd(vm->fd); + vm->numvcpus = 0; + g_free(vm->vcpus); g_free(vm); hax_global.vm = NULL; return 0; @@ -292,7 +305,7 @@ static void hax_handle_interrupt(CPUState *cpu, int mask) } } -static int hax_init(ram_addr_t ram_size) +static int hax_init(ram_addr_t ram_size, int max_cpus) { struct hax_state *hax = NULL; struct hax_qemu_version qversion; @@ -324,7 +337,7 @@ static int hax_init(ram_addr_t ram_size) goto error; } - hax->vm = hax_vm_create(hax); + hax->vm = hax_vm_create(hax, max_cpus); if (!hax->vm) { fprintf(stderr, "Failed to create HAX VM\n"); ret = -EINVAL; @@ -352,7 +365,7 @@ static int hax_init(ram_addr_t ram_size) static int hax_accel_init(MachineState *ms) { - int ret = hax_init(ms->ram_size); + int ret = hax_init(ms->ram_size, (int)ms->smp.max_cpus); if (ret && (ret != -ENOSPC)) { fprintf(stderr, "No accelerator found.\n"); diff --git a/target/i386/hax-i386.h b/target/i386/hax-i386.h index 54e9d8b057..ec28708185 100644 --- a/target/i386/hax-i386.h +++ b/target/i386/hax-i386.h @@ -41,13 +41,12 @@ struct hax_state { }; #define HAX_MAX_VCPU 0x10 -#define MAX_VM_ID 0x40 -#define MAX_VCPU_ID 0x40 struct hax_vm { hax_fd fd; int id; - struct hax_vcpu_state *vcpus[HAX_MAX_VCPU]; + int numvcpus; + struct hax_vcpu_state **vcpus; }; #ifdef NEED_CPU_H @@ -58,7 +57,7 @@ int valid_hax_tunnel_size(uint16_t size); /* Host specific functions */ int hax_mod_version(struct hax_state *hax, struct hax_module_version *version); int hax_inject_interrupt(CPUArchState *env, int vector); -struct hax_vm *hax_vm_create(struct hax_state *hax); +struct hax_vm *hax_vm_create(struct hax_state *hax, int max_cpus); int hax_vcpu_run(struct hax_vcpu_state *vcpu); int hax_vcpu_create(int id); int hax_sync_vcpu_state(CPUArchState *env, struct vcpu_state_t *state, diff --git a/target/i386/hvf/hvf-i386.h b/target/i386/hvf/hvf-i386.h index 15ee4835cf..ef20c73eca 100644 --- a/target/i386/hvf/hvf-i386.h +++ b/target/i386/hvf/hvf-i386.h @@ -16,13 +16,12 @@ #ifndef HVF_I386_H #define HVF_I386_H +#include "sysemu/accel.h" #include "sysemu/hvf.h" #include "cpu.h" #include "x86.h" #define HVF_MAX_VCPU 0x10 -#define MAX_VM_ID 0x40 -#define MAX_VCPU_ID 0x40 extern struct hvf_state hvf_global; @@ -37,6 +36,40 @@ struct hvf_state { uint64_t mem_quota; }; +/* hvf_slot flags */ +#define HVF_SLOT_LOG (1 << 0) + +typedef struct hvf_slot { + uint64_t start; + uint64_t size; + uint8_t *mem; + int slot_id; + uint32_t flags; + MemoryRegion *region; +} hvf_slot; + +typedef struct hvf_vcpu_caps { + uint64_t vmx_cap_pinbased; + uint64_t vmx_cap_procbased; + uint64_t vmx_cap_procbased2; + uint64_t vmx_cap_entry; + uint64_t vmx_cap_exit; + uint64_t vmx_cap_preemption_timer; +} hvf_vcpu_caps; + +typedef struct HVFState { + AccelState parent; + hvf_slot slots[32]; + int num_slots; + + hvf_vcpu_caps *hvf_caps; +} HVFState; +extern HVFState *hvf_state; + +void hvf_set_phys_mem(MemoryRegionSection *, bool); +void hvf_handle_io(CPUArchState *, uint16_t, void *, int, int, int); +hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t); + #ifdef NEED_CPU_H /* Functions exported to host specific mode */ diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index d72543dc31..be016b951a 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -251,7 +251,7 @@ void vmx_update_tpr(CPUState *cpu) } } -void update_apic_tpr(CPUState *cpu) +static void update_apic_tpr(CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); int tpr = rreg(cpu->hvf_fd, HV_X86_TPR) >> 4; @@ -312,7 +312,8 @@ void hvf_cpu_synchronize_post_reset(CPUState *cpu_state) run_on_cpu(cpu_state, do_hvf_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); } -void _hvf_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) +static void do_hvf_cpu_synchronize_post_init(CPUState *cpu, + run_on_cpu_data arg) { CPUState *cpu_state = cpu; hvf_put_registers(cpu_state); @@ -321,7 +322,7 @@ void _hvf_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) void hvf_cpu_synchronize_post_init(CPUState *cpu_state) { - run_on_cpu(cpu_state, _hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); + run_on_cpu(cpu_state, do_hvf_cpu_synchronize_post_init, RUN_ON_CPU_NULL); } static bool ept_emulation_fault(hvf_slot *slot, uint64_t gpa, uint64_t ept_qual) @@ -532,7 +533,11 @@ void hvf_reset_vcpu(CPUState *cpu) { void hvf_vcpu_destroy(CPUState *cpu) { + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; + hv_return_t ret = hv_vcpu_destroy((hv_vcpuid_t)cpu->hvf_fd); + g_free(env->hvf_mmio_buf); assert_hvf_ok(ret); } @@ -562,7 +567,7 @@ int hvf_init_vcpu(CPUState *cpu) init_decoder(); hvf_state->hvf_caps = g_new0(struct hvf_vcpu_caps, 1); - env->hvf_emul = g_new0(HVFX86EmulatorState, 1); + env->hvf_mmio_buf = g_new(char, 4096); r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf_fd, HV_VCPU_DEFAULT); cpu->vcpu_dirty = 1; @@ -722,8 +727,7 @@ int hvf_vcpu_exec(CPUState *cpu) hvf_store_events(cpu, ins_len, idtvec_info); rip = rreg(cpu->hvf_fd, HV_X86_RIP); - RFLAGS(env) = rreg(cpu->hvf_fd, HV_X86_RFLAGS); - env->eflags = RFLAGS(env); + env->eflags = rreg(cpu->hvf_fd, HV_X86_RFLAGS); qemu_mutex_lock_iothread(); @@ -735,7 +739,7 @@ int hvf_vcpu_exec(CPUState *cpu) case EXIT_REASON_HLT: { macvm_set_rip(cpu, rip + ins_len); if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) && - (EFLAGS(env) & IF_MASK)) + (env->eflags & IF_MASK)) && !(cpu->interrupt_request & CPU_INTERRUPT_NMI) && !(idtvec_info & VMCS_IDT_VEC_VALID)) { cpu->halted = 1; @@ -766,8 +770,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); - env->hvf_emul->fetch_rip = rip; - decode_instruction(env, &decode); exec_instruction(env, &decode); store_regs(cpu); @@ -796,7 +798,7 @@ int hvf_vcpu_exec(CPUState *cpu) } else { RAX(env) = (uint64_t)val; } - RIP(env) += ins_len; + env->eip += ins_len; store_regs(cpu); break; } else if (!string && !in) { @@ -808,8 +810,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); - env->hvf_emul->fetch_rip = rip; - decode_instruction(env, &decode); assert(ins_len == decode.len); exec_instruction(env, &decode); @@ -870,7 +870,7 @@ int hvf_vcpu_exec(CPUState *cpu) } else { simulate_wrmsr(cpu); } - RIP(env) += rvmcs(cpu->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH); + env->eip += ins_len; store_regs(cpu); break; } @@ -906,7 +906,7 @@ int hvf_vcpu_exec(CPUState *cpu) error_report("Unrecognized CR %d", cr); abort(); } - RIP(env) += ins_len; + env->eip += ins_len; store_regs(cpu); break; } @@ -914,8 +914,6 @@ int hvf_vcpu_exec(CPUState *cpu) struct x86_decode decode; load_regs(cpu); - env->hvf_emul->fetch_rip = rip; - decode_instruction(env, &decode); exec_instruction(env, &decode); store_regs(cpu); diff --git a/target/i386/hvf/x86.c b/target/i386/hvf/x86.c index 3afcedc7fc..fdb11c8db9 100644 --- a/target/i386/hvf/x86.c +++ b/target/i386/hvf/x86.c @@ -131,7 +131,7 @@ bool x86_is_v8086(struct CPUState *cpu) { X86CPU *x86_cpu = X86_CPU(cpu); CPUX86State *env = &x86_cpu->env; - return x86_is_protected(cpu) && (RFLAGS(env) & RFLAGS_VM); + return x86_is_protected(cpu) && (env->eflags & VM_MASK); } bool x86_is_long_mode(struct CPUState *cpu) diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h index c95d5b2116..bacade7b65 100644 --- a/target/i386/hvf/x86.h +++ b/target/i386/hvf/x86.h @@ -42,64 +42,6 @@ typedef struct x86_register { }; } __attribute__ ((__packed__)) x86_register; -typedef enum x86_rflags { - RFLAGS_CF = (1L << 0), - RFLAGS_PF = (1L << 2), - RFLAGS_AF = (1L << 4), - RFLAGS_ZF = (1L << 6), - RFLAGS_SF = (1L << 7), - RFLAGS_TF = (1L << 8), - RFLAGS_IF = (1L << 9), - RFLAGS_DF = (1L << 10), - RFLAGS_OF = (1L << 11), - RFLAGS_IOPL = (3L << 12), - RFLAGS_NT = (1L << 14), - RFLAGS_RF = (1L << 16), - RFLAGS_VM = (1L << 17), - RFLAGS_AC = (1L << 18), - RFLAGS_VIF = (1L << 19), - RFLAGS_VIP = (1L << 20), - RFLAGS_ID = (1L << 21), -} x86_rflags; - -/* rflags register */ -typedef struct x86_reg_flags { - union { - struct { - uint64_t rflags; - }; - struct { - uint32_t eflags; - uint32_t hi32_unused1; - }; - struct { - uint32_t cf:1; - uint32_t unused1:1; - uint32_t pf:1; - uint32_t unused2:1; - uint32_t af:1; - uint32_t unused3:1; - uint32_t zf:1; - uint32_t sf:1; - uint32_t tf:1; - uint32_t ief:1; - uint32_t df:1; - uint32_t of:1; - uint32_t iopl:2; - uint32_t nt:1; - uint32_t unused4:1; - uint32_t rf:1; - uint32_t vm:1; - uint32_t ac:1; - uint32_t vif:1; - uint32_t vip:1; - uint32_t id:1; - uint32_t unused5:10; - uint32_t hi32_unused2; - }; - }; -} __attribute__ ((__packed__)) x86_reg_flags; - typedef enum x86_reg_cr0 { CR0_PE = (1L << 0), CR0_MP = (1L << 1), @@ -286,29 +228,10 @@ typedef struct x68_segment_selector { }; } __attribute__ ((__packed__)) x68_segment_selector; -typedef struct lazy_flags { - target_ulong result; - target_ulong auxbits; -} lazy_flags; - -/* Definition of hvf_x86_state is here */ -struct HVFX86EmulatorState { - int interruptable; - uint64_t fetch_rip; - uint64_t rip; - struct x86_register regs[16]; - struct x86_reg_flags rflags; - struct lazy_flags lflags; - uint8_t mmio_buf[4096]; -}; - /* useful register access macros */ -#define RIP(cpu) (cpu->hvf_emul->rip) -#define EIP(cpu) ((uint32_t)cpu->hvf_emul->rip) -#define RFLAGS(cpu) (cpu->hvf_emul->rflags.rflags) -#define EFLAGS(cpu) (cpu->hvf_emul->rflags.eflags) +#define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg]) -#define RRX(cpu, reg) (cpu->hvf_emul->regs[reg].rrx) +#define RRX(cpu, reg) (x86_reg(cpu, reg)->rrx) #define RAX(cpu) RRX(cpu, R_EAX) #define RCX(cpu) RRX(cpu, R_ECX) #define RDX(cpu) RRX(cpu, R_EDX) @@ -326,7 +249,7 @@ struct HVFX86EmulatorState { #define R14(cpu) RRX(cpu, R_R14) #define R15(cpu) RRX(cpu, R_R15) -#define ERX(cpu, reg) (cpu->hvf_emul->regs[reg].erx) +#define ERX(cpu, reg) (x86_reg(cpu, reg)->erx) #define EAX(cpu) ERX(cpu, R_EAX) #define ECX(cpu) ERX(cpu, R_ECX) #define EDX(cpu) ERX(cpu, R_EDX) @@ -336,7 +259,7 @@ struct HVFX86EmulatorState { #define ESI(cpu) ERX(cpu, R_ESI) #define EDI(cpu) ERX(cpu, R_EDI) -#define RX(cpu, reg) (cpu->hvf_emul->regs[reg].rx) +#define RX(cpu, reg) (x86_reg(cpu, reg)->rx) #define AX(cpu) RX(cpu, R_EAX) #define CX(cpu) RX(cpu, R_ECX) #define DX(cpu) RX(cpu, R_EDX) @@ -346,13 +269,13 @@ struct HVFX86EmulatorState { #define SI(cpu) RX(cpu, R_ESI) #define DI(cpu) RX(cpu, R_EDI) -#define RL(cpu, reg) (cpu->hvf_emul->regs[reg].lx) +#define RL(cpu, reg) (x86_reg(cpu, reg)->lx) #define AL(cpu) RL(cpu, R_EAX) #define CL(cpu) RL(cpu, R_ECX) #define DL(cpu) RL(cpu, R_EDX) #define BL(cpu) RL(cpu, R_EBX) -#define RH(cpu, reg) (cpu->hvf_emul->regs[reg].hx) +#define RH(cpu, reg) (x86_reg(cpu, reg)->hx) #define AH(cpu) RH(cpu, R_EAX) #define CH(cpu) RH(cpu, R_ECX) #define DH(cpu) RH(cpu, R_EDX) diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c index 77c346605f..34c5e3006c 100644 --- a/target/i386/hvf/x86_decode.c +++ b/target/i386/hvf/x86_decode.c @@ -29,8 +29,7 @@ static void decode_invalid(CPUX86State *env, struct x86_decode *decode) { - printf("%llx: failed to decode instruction ", env->hvf_emul->fetch_rip - - decode->len); + printf("%llx: failed to decode instruction ", env->eip); for (int i = 0; i < decode->opcode_len; i++) { printf("%x ", decode->opcode[i]); } @@ -75,7 +74,7 @@ static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode, VM_PANIC_EX("%s invalid size %d\n", __func__, size); break; } - target_ulong va = linear_rip(env_cpu(env), RIP(env)) + decode->len; + target_ulong va = linear_rip(env_cpu(env), env->eip) + decode->len; vmx_read_mem(env_cpu(env), &val, va, size); decode->len += size; @@ -698,15 +697,13 @@ static void decode_db_4(CPUX86State *env, struct x86_decode *decode) #define RFLAGS_MASK_NONE 0 -#define RFLAGS_MASK_OSZAPC (RFLAGS_OF | RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | \ - RFLAGS_PF | RFLAGS_CF) -#define RFLAGS_MASK_LAHF (RFLAGS_SF | RFLAGS_ZF | RFLAGS_AF | RFLAGS_PF | \ - RFLAGS_CF) -#define RFLAGS_MASK_CF (RFLAGS_CF) -#define RFLAGS_MASK_IF (RFLAGS_IF) -#define RFLAGS_MASK_TF (RFLAGS_TF) -#define RFLAGS_MASK_DF (RFLAGS_DF) -#define RFLAGS_MASK_ZF (RFLAGS_ZF) +#define RFLAGS_MASK_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_LAHF (CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_CF (CC_C) +#define RFLAGS_MASK_IF (IF_MASK) +#define RFLAGS_MASK_TF (TF_MASK) +#define RFLAGS_MASK_DF (DF_MASK) +#define RFLAGS_MASK_ZF (CC_Z) struct decode_tbl _1op_inst[] = { {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, @@ -1771,7 +1768,7 @@ void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, ptr += get_sib_val(env, decode, &seg); } else if (!decode->modrm.mod && 5 == decode->modrm.rm) { if (x86_is_long_mode(env_cpu(env))) { - ptr += RIP(env) + decode->len; + ptr += env->eip + decode->len; } else { ptr = decode->displacement; } @@ -1807,7 +1804,7 @@ void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, if (4 == rm) { ptr = get_sib_val(env, decode, &seg) + offset; } else if (0 == mod && 5 == rm) { - ptr = RIP(env) + decode->len + (int32_t) offset; + ptr = env->eip + decode->len + (int32_t) offset; } else { ptr = get_reg_val(env, src, decode->rex.rex, decode->rex.b, 8) + (int64_t) offset; diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c index 92ab815f5d..d3e289ed87 100644 --- a/target/i386/hvf/x86_emu.c +++ b/target/i386/hvf/x86_emu.c @@ -95,13 +95,13 @@ target_ulong read_reg(CPUX86State *env, int reg, int size) { switch (size) { case 1: - return env->hvf_emul->regs[reg].lx; + return x86_reg(env, reg)->lx; case 2: - return env->hvf_emul->regs[reg].rx; + return x86_reg(env, reg)->rx; case 4: - return env->hvf_emul->regs[reg].erx; + return x86_reg(env, reg)->erx; case 8: - return env->hvf_emul->regs[reg].rrx; + return x86_reg(env, reg)->rrx; default: abort(); } @@ -112,16 +112,16 @@ void write_reg(CPUX86State *env, int reg, target_ulong val, int size) { switch (size) { case 1: - env->hvf_emul->regs[reg].lx = val; + x86_reg(env, reg)->lx = val; break; case 2: - env->hvf_emul->regs[reg].rx = val; + x86_reg(env, reg)->rx = val; break; case 4: - env->hvf_emul->regs[reg].rrx = (uint32_t)val; + x86_reg(env, reg)->rrx = (uint32_t)val; break; case 8: - env->hvf_emul->regs[reg].rrx = val; + x86_reg(env, reg)->rrx = val; break; default: abort(); @@ -173,7 +173,7 @@ void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size) static bool is_host_reg(struct CPUX86State *env, target_ulong ptr) { - return (ptr - (target_ulong)&env->hvf_emul->regs[0]) < sizeof(env->hvf_emul->regs); + return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs); } void write_val_ext(struct CPUX86State *env, target_ulong ptr, target_ulong val, int size) @@ -187,8 +187,8 @@ void write_val_ext(struct CPUX86State *env, target_ulong ptr, target_ulong val, uint8_t *read_mmio(struct CPUX86State *env, target_ulong ptr, int bytes) { - vmx_read_mem(env_cpu(env), env->hvf_emul->mmio_buf, ptr, bytes); - return env->hvf_emul->mmio_buf; + vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, ptr, bytes); + return env->hvf_mmio_buf; } @@ -267,49 +267,49 @@ static void exec_mov(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[0].ptr, decode->op[1].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_add(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_or(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_adc(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_sbb(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_and(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_sub(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_xor(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_neg(struct CPUX86State *env, struct x86_decode *decode) @@ -332,13 +332,13 @@ static void exec_neg(struct CPUX86State *env, struct x86_decode *decode) } /*lflags_to_rflags(env);*/ - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_cmp(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_inc(struct CPUX86State *env, struct x86_decode *decode) @@ -348,7 +348,7 @@ static void exec_inc(struct CPUX86State *env, struct x86_decode *decode) EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_dec(struct CPUX86State *env, struct x86_decode *decode) @@ -357,13 +357,13 @@ static void exec_dec(struct CPUX86State *env, struct x86_decode *decode) decode->op[1].val = 0; EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_tst(struct CPUX86State *env, struct x86_decode *decode) { EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_not(struct CPUX86State *env, struct x86_decode *decode) @@ -372,7 +372,7 @@ static void exec_not(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } void exec_movzx(struct CPUX86State *env, struct x86_decode *decode) @@ -392,7 +392,7 @@ void exec_movzx(struct CPUX86State *env, struct x86_decode *decode) decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size); write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_out(struct CPUX86State *env, struct x86_decode *decode) @@ -416,7 +416,7 @@ static void exec_out(struct CPUX86State *env, struct x86_decode *decode) VM_PANIC("Bad out opcode\n"); break; } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_in(struct CPUX86State *env, struct x86_decode *decode) @@ -452,14 +452,14 @@ static void exec_in(struct CPUX86State *env, struct x86_decode *decode) break; } - RIP(env) += decode->len; + env->eip += decode->len; } static inline void string_increment_reg(struct CPUX86State *env, int reg, struct x86_decode *decode) { target_ulong val = read_reg(env, reg, decode->addressing_size); - if (env->hvf_emul->rflags.df) { + if (env->eflags & DF_MASK) { val -= decode->operand_size; } else { val += decode->operand_size; @@ -489,9 +489,9 @@ static void exec_ins_single(struct CPUX86State *env, struct x86_decode *decode) target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), decode->addressing_size, R_ES); - hvf_handle_io(env_cpu(env), DX(env), env->hvf_emul->mmio_buf, 0, + hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 0, decode->operand_size, 1); - vmx_write_mem(env_cpu(env), addr, env->hvf_emul->mmio_buf, + vmx_write_mem(env_cpu(env), addr, env->hvf_mmio_buf, decode->operand_size); string_increment_reg(env, R_EDI, decode); @@ -505,16 +505,16 @@ static void exec_ins(struct CPUX86State *env, struct x86_decode *decode) exec_ins_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_outs_single(struct CPUX86State *env, struct x86_decode *decode) { target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); - vmx_read_mem(env_cpu(env), env->hvf_emul->mmio_buf, addr, + vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, addr, decode->operand_size); - hvf_handle_io(env_cpu(env), DX(env), env->hvf_emul->mmio_buf, 1, + hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 1, decode->operand_size, 1); string_increment_reg(env, R_ESI, decode); @@ -528,7 +528,7 @@ static void exec_outs(struct CPUX86State *env, struct x86_decode *decode) exec_outs_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_movs_single(struct CPUX86State *env, struct x86_decode *decode) @@ -556,7 +556,7 @@ static void exec_movs(struct CPUX86State *env, struct x86_decode *decode) exec_movs_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_cmps_single(struct CPUX86State *env, struct x86_decode *decode) @@ -586,7 +586,7 @@ static void exec_cmps(struct CPUX86State *env, struct x86_decode *decode) } else { exec_cmps_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } @@ -612,7 +612,7 @@ static void exec_stos(struct CPUX86State *env, struct x86_decode *decode) exec_stos_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_scas_single(struct CPUX86State *env, struct x86_decode *decode) @@ -638,7 +638,7 @@ static void exec_scas(struct CPUX86State *env, struct x86_decode *decode) exec_scas_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_lods_single(struct CPUX86State *env, struct x86_decode *decode) @@ -661,7 +661,7 @@ static void exec_lods(struct CPUX86State *env, struct x86_decode *decode) exec_lods_single(env, decode); } - RIP(env) += decode->len; + env->eip += decode->len; } void simulate_rdmsr(struct CPUState *cpu) @@ -758,7 +758,7 @@ void simulate_rdmsr(struct CPUState *cpu) static void exec_rdmsr(struct CPUX86State *env, struct x86_decode *decode) { simulate_rdmsr(env_cpu(env)); - RIP(env) += decode->len; + env->eip += decode->len; } void simulate_wrmsr(struct CPUState *cpu) @@ -853,7 +853,7 @@ void simulate_wrmsr(struct CPUState *cpu) static void exec_wrmsr(struct CPUX86State *env, struct x86_decode *decode) { simulate_wrmsr(env_cpu(env)); - RIP(env) += decode->len; + env->eip += decode->len; } /* @@ -909,25 +909,25 @@ static void do_bt(struct CPUX86State *env, struct x86_decode *decode, int flag) static void exec_bt(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 0); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_btc(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 1); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_btr(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 3); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_bts(struct CPUX86State *env, struct x86_decode *decode) { do_bt(env, decode, 2); - RIP(env) += decode->len; + env->eip += decode->len; } void exec_shl(struct CPUX86State *env, struct x86_decode *decode) @@ -991,7 +991,7 @@ void exec_shl(struct CPUX86State *env, struct x86_decode *decode) exit: /* lflags_to_rflags(env); */ - RIP(env) += decode->len; + env->eip += decode->len; } void exec_movsx(CPUX86State *env, struct x86_decode *decode) @@ -1014,7 +1014,7 @@ void exec_movsx(CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); - RIP(env) += decode->len; + env->eip += decode->len; } void exec_ror(struct CPUX86State *env, struct x86_decode *decode) @@ -1092,7 +1092,7 @@ void exec_ror(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } void exec_rol(struct CPUX86State *env, struct x86_decode *decode) @@ -1173,7 +1173,7 @@ void exec_rol(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } @@ -1259,7 +1259,7 @@ void exec_rcl(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } void exec_rcr(struct CPUX86State *env, struct x86_decode *decode) @@ -1334,7 +1334,7 @@ void exec_rcr(struct CPUX86State *env, struct x86_decode *decode) break; } } - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_xchg(struct CPUX86State *env, struct x86_decode *decode) @@ -1346,7 +1346,7 @@ static void exec_xchg(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[1].ptr, decode->op[0].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } static void exec_xadd(struct CPUX86State *env, struct x86_decode *decode) @@ -1355,7 +1355,7 @@ static void exec_xadd(struct CPUX86State *env, struct x86_decode *decode) write_val_ext(env, decode->op[1].ptr, decode->op[0].val, decode->operand_size); - RIP(env) += decode->len; + env->eip += decode->len; } static struct cmd_handler { @@ -1432,9 +1432,9 @@ void load_regs(struct CPUState *cpu) RRX(env, i) = rreg(cpu->hvf_fd, HV_X86_RAX + i); } - RFLAGS(env) = rreg(cpu->hvf_fd, HV_X86_RFLAGS); + env->eflags = rreg(cpu->hvf_fd, HV_X86_RFLAGS); rflags_to_lflags(env); - RIP(env) = rreg(cpu->hvf_fd, HV_X86_RIP); + env->eip = rreg(cpu->hvf_fd, HV_X86_RIP); } void store_regs(struct CPUState *cpu) @@ -1456,21 +1456,21 @@ void store_regs(struct CPUState *cpu) } lflags_to_rflags(env); - wreg(cpu->hvf_fd, HV_X86_RFLAGS, RFLAGS(env)); - macvm_set_rip(cpu, RIP(env)); + wreg(cpu->hvf_fd, HV_X86_RFLAGS, env->eflags); + macvm_set_rip(cpu, env->eip); } bool exec_instruction(struct CPUX86State *env, struct x86_decode *ins) { /*if (hvf_vcpu_id(cpu)) - printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cpu), RIP(cpu), + printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cpu), env->eip, decode_cmd_to_string(ins->cmd));*/ if (!_cmd_handler[ins->cmd].handler) { - printf("Unimplemented handler (%llx) for %d (%x %x) \n", RIP(env), + printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip, ins->cmd, ins->opcode[0], ins->opcode_len > 1 ? ins->opcode[1] : 0); - RIP(env) += ins->len; + env->eip += ins->len; return true; } diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index ee6d33f861..5ca4f41f5c 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -63,7 +63,7 @@ #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ - env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ if ((size) == 32) { \ temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ } else if ((size) == 16) { \ @@ -73,7 +73,7 @@ } else { \ VM_PANIC("unimplemented"); \ } \ - env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)temp; \ + env->hvf_lflags.auxbits = (target_ulong)(uint32_t)temp; \ } /* carries, result */ @@ -100,10 +100,10 @@ } else { \ VM_PANIC("unimplemented"); \ } \ - env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ - target_ulong delta_c = (env->hvf_emul->lflags.auxbits ^ temp) & LF_MASK_CF; \ + env->hvf_lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + target_ulong delta_c = (env->hvf_lflags.auxbits ^ temp) & LF_MASK_CF; \ delta_c ^= (delta_c >> 1); \ - env->hvf_emul->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ + env->hvf_lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ } /* carries, result */ @@ -117,9 +117,8 @@ void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) { uint32_t temp_po = new_of ^ new_cf; - env->hvf_emul->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); - env->hvf_emul->lflags.auxbits |= (temp_po << LF_BIT_PO) | - (new_cf << LF_BIT_CF); + env->hvf_lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); + env->hvf_lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); } void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, @@ -215,27 +214,27 @@ void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, bool get_PF(CPUX86State *env) { - uint32_t temp = (255 & env->hvf_emul->lflags.result); - temp = temp ^ (255 & (env->hvf_emul->lflags.auxbits >> LF_BIT_PDB)); + uint32_t temp = (255 & env->hvf_lflags.result); + temp = temp ^ (255 & (env->hvf_lflags.auxbits >> LF_BIT_PDB)); temp = (temp ^ (temp >> 4)) & 0x0F; return (0x9669U >> temp) & 1; } void set_PF(CPUX86State *env, bool val) { - uint32_t temp = (255 & env->hvf_emul->lflags.result) ^ (!val); - env->hvf_emul->lflags.auxbits &= ~(LF_MASK_PDB); - env->hvf_emul->lflags.auxbits |= (temp << LF_BIT_PDB); + uint32_t temp = (255 & env->hvf_lflags.result) ^ (!val); + env->hvf_lflags.auxbits &= ~(LF_MASK_PDB); + env->hvf_lflags.auxbits |= (temp << LF_BIT_PDB); } bool get_OF(CPUX86State *env) { - return ((env->hvf_emul->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; + return ((env->hvf_lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; } bool get_CF(CPUX86State *env) { - return (env->hvf_emul->lflags.auxbits >> LF_BIT_CF) & 1; + return (env->hvf_lflags.auxbits >> LF_BIT_CF) & 1; } void set_OF(CPUX86State *env, bool val) @@ -252,64 +251,64 @@ void set_CF(CPUX86State *env, bool val) bool get_AF(CPUX86State *env) { - return (env->hvf_emul->lflags.auxbits >> LF_BIT_AF) & 1; + return (env->hvf_lflags.auxbits >> LF_BIT_AF) & 1; } void set_AF(CPUX86State *env, bool val) { - env->hvf_emul->lflags.auxbits &= ~(LF_MASK_AF); - env->hvf_emul->lflags.auxbits |= val << LF_BIT_AF; + env->hvf_lflags.auxbits &= ~(LF_MASK_AF); + env->hvf_lflags.auxbits |= val << LF_BIT_AF; } bool get_ZF(CPUX86State *env) { - return !env->hvf_emul->lflags.result; + return !env->hvf_lflags.result; } void set_ZF(CPUX86State *env, bool val) { if (val) { - env->hvf_emul->lflags.auxbits ^= - (((env->hvf_emul->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); + env->hvf_lflags.auxbits ^= + (((env->hvf_lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); /* merge the parity bits into the Parity Delta Byte */ - uint32_t temp_pdb = (255 & env->hvf_emul->lflags.result); - env->hvf_emul->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); + uint32_t temp_pdb = (255 & env->hvf_lflags.result); + env->hvf_lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); /* now zero the .result value */ - env->hvf_emul->lflags.result = 0; + env->hvf_lflags.result = 0; } else { - env->hvf_emul->lflags.result |= (1 << 8); + env->hvf_lflags.result |= (1 << 8); } } bool get_SF(CPUX86State *env) { - return ((env->hvf_emul->lflags.result >> LF_SIGN_BIT) ^ - (env->hvf_emul->lflags.auxbits >> LF_BIT_SD)) & 1; + return ((env->hvf_lflags.result >> LF_SIGN_BIT) ^ + (env->hvf_lflags.auxbits >> LF_BIT_SD)) & 1; } void set_SF(CPUX86State *env, bool val) { bool temp_sf = get_SF(env); - env->hvf_emul->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; + env->hvf_lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; } void lflags_to_rflags(CPUX86State *env) { - env->hvf_emul->rflags.cf = get_CF(env); - env->hvf_emul->rflags.pf = get_PF(env); - env->hvf_emul->rflags.af = get_AF(env); - env->hvf_emul->rflags.zf = get_ZF(env); - env->hvf_emul->rflags.sf = get_SF(env); - env->hvf_emul->rflags.of = get_OF(env); + env->eflags |= get_CF(env) ? CC_C : 0; + env->eflags |= get_PF(env) ? CC_P : 0; + env->eflags |= get_AF(env) ? CC_A : 0; + env->eflags |= get_ZF(env) ? CC_Z : 0; + env->eflags |= get_SF(env) ? CC_S : 0; + env->eflags |= get_OF(env) ? CC_O : 0; } void rflags_to_lflags(CPUX86State *env) { - env->hvf_emul->lflags.auxbits = env->hvf_emul->lflags.result = 0; - set_OF(env, env->hvf_emul->rflags.of); - set_SF(env, env->hvf_emul->rflags.sf); - set_ZF(env, env->hvf_emul->rflags.zf); - set_AF(env, env->hvf_emul->rflags.af); - set_PF(env, env->hvf_emul->rflags.pf); - set_CF(env, env->hvf_emul->rflags.cf); + env->hvf_lflags.auxbits = env->hvf_lflags.result = 0; + set_OF(env, env->eflags & CC_O); + set_SF(env, env->eflags & CC_S); + set_ZF(env, env->eflags & CC_Z); + set_AF(env, env->eflags & CC_A); + set_PF(env, env->eflags & CC_P); + set_CF(env, env->eflags & CC_C); } diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index 1daac6cc2b..6f04478b3a 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -38,8 +38,8 @@ static void save_state_to_tss32(CPUState *cpu, struct x86_tss_segment32 *tss) CPUX86State *env = &x86_cpu->env; /* CR3 and ldt selector are not saved intentionally */ - tss->eip = EIP(env); - tss->eflags = EFLAGS(env); + tss->eip = (uint32_t)env->eip; + tss->eflags = (uint32_t)env->eflags; tss->eax = EAX(env); tss->ecx = ECX(env); tss->edx = EDX(env); @@ -64,8 +64,8 @@ static void load_state_from_tss32(CPUState *cpu, struct x86_tss_segment32 *tss) wvmcs(cpu->hvf_fd, VMCS_GUEST_CR3, tss->cr3); - RIP(env) = tss->eip; - EFLAGS(env) = tss->eflags | 2; + env->eip = tss->eip; + env->eflags = tss->eflags | 2; /* General purpose registers */ RAX(env) = tss->eax; @@ -158,7 +158,7 @@ void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, int rea } if (reason == TSR_IRET) - EFLAGS(env) &= ~RFLAGS_NT; + env->eflags &= ~NT_MASK; if (reason != TSR_CALL && reason != TSR_IDT_GATE) old_tss_sel.sel = 0xffff; diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index edefe5319a..5cbcb32ab6 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -412,7 +412,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state) if (!(env->hflags & HF_INHIBIT_IRQ_MASK) && (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && - (EFLAGS(env) & IF_MASK) && !(info & VMCS_INTR_VALID)) { + (env->eflags & IF_MASK) && !(info & VMCS_INTR_VALID)) { int line = cpu_get_pic_interrupt(&x86cpu->env); cpu_state->interrupt_request &= ~CPU_INTERRUPT_HARD; if (line >= 0) { @@ -432,7 +432,7 @@ int hvf_process_events(CPUState *cpu_state) X86CPU *cpu = X86_CPU(cpu_state); CPUX86State *env = &cpu->env; - EFLAGS(env) = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS); + env->eflags = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS); if (cpu_state->interrupt_request & CPU_INTERRUPT_INIT) { hvf_cpu_synchronize_state(cpu_state); @@ -444,7 +444,7 @@ int hvf_process_events(CPUState *cpu_state) apic_poll_irq(cpu->apic_state); } if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) && - (EFLAGS(env) & IF_MASK)) || + (env->eflags & IF_MASK)) || (cpu_state->interrupt_request & CPU_INTERRUPT_NMI)) { cpu_state->halted = 0; } diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 34f838728d..b3c13cb898 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -59,6 +59,10 @@ do { } while (0) #endif +/* From arch/x86/kvm/lapic.h */ +#define KVM_APIC_BUS_CYCLE_NS 1 +#define KVM_APIC_BUS_FREQUENCY (1000000000ULL / KVM_APIC_BUS_CYCLE_NS) + #define MSR_KVM_WALL_CLOCK 0x11 #define MSR_KVM_SYSTEM_TIME 0x12 @@ -106,6 +110,7 @@ static bool has_msr_core_capabs; static bool has_msr_vmx_vmfunc; static bool has_msr_ucode_rev; static bool has_msr_vmx_procbased_ctls2; +static bool has_msr_perf_capabs; static uint32_t has_architectural_pmu_version; static uint32_t num_architectural_pmu_gp_counters; @@ -1469,6 +1474,8 @@ int kvm_arch_init_vcpu(CPUState *cs) } } + env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY; + /* Paravirtualization CPUIDs */ r = hyperv_handle_properties(cs, cpuid_data.entries); if (r < 0) { @@ -1735,7 +1742,7 @@ int kvm_arch_init_vcpu(CPUState *cs) } } - qemu_add_vm_change_state_handler(cpu_update_state, env); + cpu->vmsentry = qemu_add_vm_change_state_handler(cpu_update_state, env); c = cpuid_find_entry(&cpuid_data.cpuid, 1, 0); if (c) { @@ -1773,9 +1780,7 @@ int kvm_arch_init_vcpu(CPUState *cs) c = &cpuid_data.entries[cpuid_i++]; c->function = KVM_CPUID_SIGNATURE | 0x10; c->eax = env->tsc_khz; - /* LAPIC resolution of 1ns (freq: 1GHz) is hardcoded in KVM's - * APIC_BUS_CYCLE_NS */ - c->ebx = 1000000; + c->ebx = env->apic_bus_freq / 1000; /* Hz to KHz */ c->ecx = c->edx = 0; c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0); @@ -1848,6 +1853,8 @@ int kvm_arch_destroy_vcpu(CPUState *cs) env->nested_state = NULL; } + qemu_del_vm_change_state_handler(cpu->vmsentry); + return 0; } @@ -2027,6 +2034,9 @@ static int kvm_get_supported_msrs(KVMState *s) case MSR_IA32_CORE_CAPABILITY: has_msr_core_capabs = true; break; + case MSR_IA32_PERF_CAPABILITIES: + has_msr_perf_capabs = true; + break; case MSR_IA32_VMX_VMFUNC: has_msr_vmx_vmfunc = true; break; @@ -2643,6 +2653,18 @@ static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) VMCS12_MAX_FIELD_INDEX << 1); } +static void kvm_msr_entry_add_perf(X86CPU *cpu, FeatureWordArray f) +{ + uint64_t kvm_perf_cap = + kvm_arch_get_supported_msr_feature(kvm_state, + MSR_IA32_PERF_CAPABILITIES); + + if (kvm_perf_cap) { + kvm_msr_entry_add(cpu, MSR_IA32_PERF_CAPABILITIES, + kvm_perf_cap & f[FEAT_PERF_CAPABILITIES]); + } +} + static int kvm_buf_set_msrs(X86CPU *cpu) { int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); @@ -2675,6 +2697,10 @@ static void kvm_init_msrs(X86CPU *cpu) env->features[FEAT_CORE_CAPABILITY]); } + if (has_msr_perf_capabs && cpu->enable_pmu) { + kvm_msr_entry_add_perf(cpu, env->features); + } + if (has_msr_ucode_rev) { kvm_msr_entry_add(cpu, MSR_IA32_UCODE_REV, cpu->ucode_rev); } diff --git a/target/i386/misc_helper.c b/target/i386/misc_helper.c index 7d61221024..b6b1d41b14 100644 --- a/target/i386/misc_helper.c +++ b/target/i386/misc_helper.c @@ -70,7 +70,7 @@ target_ulong helper_inw(CPUX86State *env, uint32_t port) void helper_outl(CPUX86State *env, uint32_t port, uint32_t data) { #ifdef CONFIG_USER_ONLY - fprintf(stderr, "outw: port=0x%04x, data=%08x\n", port, data); + fprintf(stderr, "outl: port=0x%04x, data=%08x\n", port, data); #else address_space_stl(&address_space_io, port, data, cpu_get_mem_attrs(env), NULL); diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 4658768de2..14f2b16abd 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1435,34 +1435,47 @@ void glue(helper_pshufb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) void glue(helper_phaddw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->W(0) = (int16_t)d->W(0) + (int16_t)d->W(1); - d->W(1) = (int16_t)d->W(2) + (int16_t)d->W(3); - XMM_ONLY(d->W(2) = (int16_t)d->W(4) + (int16_t)d->W(5)); - XMM_ONLY(d->W(3) = (int16_t)d->W(6) + (int16_t)d->W(7)); - d->W((2 << SHIFT) + 0) = (int16_t)s->W(0) + (int16_t)s->W(1); - d->W((2 << SHIFT) + 1) = (int16_t)s->W(2) + (int16_t)s->W(3); - XMM_ONLY(d->W(6) = (int16_t)s->W(4) + (int16_t)s->W(5)); - XMM_ONLY(d->W(7) = (int16_t)s->W(6) + (int16_t)s->W(7)); + + Reg r; + + r.W(0) = (int16_t)d->W(0) + (int16_t)d->W(1); + r.W(1) = (int16_t)d->W(2) + (int16_t)d->W(3); + XMM_ONLY(r.W(2) = (int16_t)d->W(4) + (int16_t)d->W(5)); + XMM_ONLY(r.W(3) = (int16_t)d->W(6) + (int16_t)d->W(7)); + r.W((2 << SHIFT) + 0) = (int16_t)s->W(0) + (int16_t)s->W(1); + r.W((2 << SHIFT) + 1) = (int16_t)s->W(2) + (int16_t)s->W(3); + XMM_ONLY(r.W(6) = (int16_t)s->W(4) + (int16_t)s->W(5)); + XMM_ONLY(r.W(7) = (int16_t)s->W(6) + (int16_t)s->W(7)); + + *d = r; } void glue(helper_phaddd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->L(0) = (int32_t)d->L(0) + (int32_t)d->L(1); - XMM_ONLY(d->L(1) = (int32_t)d->L(2) + (int32_t)d->L(3)); - d->L((1 << SHIFT) + 0) = (int32_t)s->L(0) + (int32_t)s->L(1); - XMM_ONLY(d->L(3) = (int32_t)s->L(2) + (int32_t)s->L(3)); + Reg r; + + r.L(0) = (int32_t)d->L(0) + (int32_t)d->L(1); + XMM_ONLY(r.L(1) = (int32_t)d->L(2) + (int32_t)d->L(3)); + r.L((1 << SHIFT) + 0) = (int32_t)s->L(0) + (int32_t)s->L(1); + XMM_ONLY(r.L(3) = (int32_t)s->L(2) + (int32_t)s->L(3)); + + *d = r; } void glue(helper_phaddsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->W(0) = satsw((int16_t)d->W(0) + (int16_t)d->W(1)); - d->W(1) = satsw((int16_t)d->W(2) + (int16_t)d->W(3)); - XMM_ONLY(d->W(2) = satsw((int16_t)d->W(4) + (int16_t)d->W(5))); - XMM_ONLY(d->W(3) = satsw((int16_t)d->W(6) + (int16_t)d->W(7))); - d->W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) + (int16_t)s->W(1)); - d->W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) + (int16_t)s->W(3)); - XMM_ONLY(d->W(6) = satsw((int16_t)s->W(4) + (int16_t)s->W(5))); - XMM_ONLY(d->W(7) = satsw((int16_t)s->W(6) + (int16_t)s->W(7))); + Reg r; + + r.W(0) = satsw((int16_t)d->W(0) + (int16_t)d->W(1)); + r.W(1) = satsw((int16_t)d->W(2) + (int16_t)d->W(3)); + XMM_ONLY(r.W(2) = satsw((int16_t)d->W(4) + (int16_t)d->W(5))); + XMM_ONLY(r.W(3) = satsw((int16_t)d->W(6) + (int16_t)d->W(7))); + r.W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) + (int16_t)s->W(1)); + r.W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) + (int16_t)s->W(3)); + XMM_ONLY(r.W(6) = satsw((int16_t)s->W(4) + (int16_t)s->W(5))); + XMM_ONLY(r.W(7) = satsw((int16_t)s->W(6) + (int16_t)s->W(7))); + + *d = r; } void glue(helper_pmaddubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) @@ -2076,10 +2089,10 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s, res = (2 << upper) - 1; break; } - for (j = valids - validd; j >= 0; j--) { + for (j = valids == upper ? valids : valids - validd; j >= 0; j--) { res <<= 1; v = 1; - for (i = validd; i >= 0; i--) { + for (i = MIN(valids - j, validd); i >= 0; i--) { v &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i)); } res |= v; diff --git a/target/i386/sev.c b/target/i386/sev.c index 51cdbe5496..d273174ad3 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -29,10 +29,48 @@ #include "trace.h" #include "migration/blocker.h" +#define TYPE_SEV_GUEST "sev-guest" +#define SEV_GUEST(obj) \ + OBJECT_CHECK(SevGuestState, (obj), TYPE_SEV_GUEST) + +typedef struct SevGuestState SevGuestState; + +/** + * SevGuestState: + * + * The SevGuestState object is used for creating and managing a SEV + * guest. + * + * # $QEMU \ + * -object sev-guest,id=sev0 \ + * -machine ...,memory-encryption=sev0 + */ +struct SevGuestState { + Object parent_obj; + + /* configuration parameters */ + char *sev_device; + uint32_t policy; + char *dh_cert_file; + char *session_file; + uint32_t cbitpos; + uint32_t reduced_phys_bits; + + /* runtime state */ + uint32_t handle; + uint8_t api_major; + uint8_t api_minor; + uint8_t build_id; + uint64_t me_mask; + int sev_fd; + SevState state; + gchar *measurement; +}; + #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */ #define DEFAULT_SEV_DEVICE "/dev/sev" -static SEVState *sev_state; +static SevGuestState *sev_guest; static Error *sev_mig_blocker; static const char *const sev_fw_errlist[] = { @@ -111,21 +149,21 @@ fw_error_to_str(int code) } static bool -sev_check_state(SevState state) +sev_check_state(const SevGuestState *sev, SevState state) { - assert(sev_state); - return sev_state->state == state ? true : false; + assert(sev); + return sev->state == state ? true : false; } static void -sev_set_guest_state(SevState new_state) +sev_set_guest_state(SevGuestState *sev, SevState new_state) { assert(new_state < SEV_STATE__MAX); - assert(sev_state); + assert(sev); - trace_kvm_sev_change_state(SevState_str(sev_state->state), + trace_kvm_sev_change_state(SevState_str(sev->state), SevState_str(new_state)); - sev_state->state = new_state; + sev->state = new_state; } static void @@ -191,82 +229,82 @@ static struct RAMBlockNotifier sev_ram_notifier = { }; static void -qsev_guest_finalize(Object *obj) +sev_guest_finalize(Object *obj) { } static char * -qsev_guest_get_session_file(Object *obj, Error **errp) +sev_guest_get_session_file(Object *obj, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); return s->session_file ? g_strdup(s->session_file) : NULL; } static void -qsev_guest_set_session_file(Object *obj, const char *value, Error **errp) +sev_guest_set_session_file(Object *obj, const char *value, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); s->session_file = g_strdup(value); } static char * -qsev_guest_get_dh_cert_file(Object *obj, Error **errp) +sev_guest_get_dh_cert_file(Object *obj, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); return g_strdup(s->dh_cert_file); } static void -qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp) +sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp) { - QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + SevGuestState *s = SEV_GUEST(obj); s->dh_cert_file = g_strdup(value); } static char * -qsev_guest_get_sev_device(Object *obj, Error **errp) +sev_guest_get_sev_device(Object *obj, Error **errp) { - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + SevGuestState *sev = SEV_GUEST(obj); return g_strdup(sev->sev_device); } static void -qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp) +sev_guest_set_sev_device(Object *obj, const char *value, Error **errp) { - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + SevGuestState *sev = SEV_GUEST(obj); sev->sev_device = g_strdup(value); } static void -qsev_guest_class_init(ObjectClass *oc, void *data) +sev_guest_class_init(ObjectClass *oc, void *data) { object_class_property_add_str(oc, "sev-device", - qsev_guest_get_sev_device, - qsev_guest_set_sev_device); + sev_guest_get_sev_device, + sev_guest_set_sev_device); object_class_property_set_description(oc, "sev-device", "SEV device to use"); object_class_property_add_str(oc, "dh-cert-file", - qsev_guest_get_dh_cert_file, - qsev_guest_set_dh_cert_file); + sev_guest_get_dh_cert_file, + sev_guest_set_dh_cert_file); object_class_property_set_description(oc, "dh-cert-file", "guest owners DH certificate (encoded with base64)"); object_class_property_add_str(oc, "session-file", - qsev_guest_get_session_file, - qsev_guest_set_session_file); + sev_guest_get_session_file, + sev_guest_set_session_file); object_class_property_set_description(oc, "session-file", "guest owners session parameters (encoded with base64)"); } static void -qsev_guest_init(Object *obj) +sev_guest_instance_init(Object *obj) { - QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + SevGuestState *sev = SEV_GUEST(obj); sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE); sev->policy = DEFAULT_GUEST_POLICY; @@ -282,33 +320,32 @@ qsev_guest_init(Object *obj) } /* sev guest info */ -static const TypeInfo qsev_guest_info = { +static const TypeInfo sev_guest_info = { .parent = TYPE_OBJECT, - .name = TYPE_QSEV_GUEST_INFO, - .instance_size = sizeof(QSevGuestInfo), - .instance_finalize = qsev_guest_finalize, - .class_size = sizeof(QSevGuestInfoClass), - .class_init = qsev_guest_class_init, - .instance_init = qsev_guest_init, + .name = TYPE_SEV_GUEST, + .instance_size = sizeof(SevGuestState), + .instance_finalize = sev_guest_finalize, + .class_init = sev_guest_class_init, + .instance_init = sev_guest_instance_init, .interfaces = (InterfaceInfo[]) { { TYPE_USER_CREATABLE }, { } } }; -static QSevGuestInfo * +static SevGuestState * lookup_sev_guest_info(const char *id) { Object *obj; - QSevGuestInfo *info; + SevGuestState *info; obj = object_resolve_path_component(object_get_objects_root(), id); if (!obj) { return NULL; } - info = (QSevGuestInfo *) - object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO); + info = (SevGuestState *) + object_dynamic_cast(obj, TYPE_SEV_GUEST); if (!info) { return NULL; } @@ -319,25 +356,25 @@ lookup_sev_guest_info(const char *id) bool sev_enabled(void) { - return sev_state ? true : false; + return !!sev_guest; } uint64_t sev_get_me_mask(void) { - return sev_state ? sev_state->me_mask : ~0; + return sev_guest ? sev_guest->me_mask : ~0; } uint32_t sev_get_cbit_position(void) { - return sev_state ? sev_state->cbitpos : 0; + return sev_guest ? sev_guest->cbitpos : 0; } uint32_t sev_get_reduced_phys_bits(void) { - return sev_state ? sev_state->reduced_phys_bits : 0; + return sev_guest ? sev_guest->reduced_phys_bits : 0; } SevInfo * @@ -346,15 +383,15 @@ sev_get_info(void) SevInfo *info; info = g_new0(SevInfo, 1); - info->enabled = sev_state ? true : false; + info->enabled = sev_enabled(); if (info->enabled) { - info->api_major = sev_state->api_major; - info->api_minor = sev_state->api_minor; - info->build_id = sev_state->build_id; - info->policy = sev_state->policy; - info->state = sev_state->state; - info->handle = sev_state->handle; + info->api_major = sev_guest->api_major; + info->api_minor = sev_guest->api_minor; + info->build_id = sev_guest->build_id; + info->policy = sev_guest->policy; + info->state = sev_guest->state; + info->handle = sev_guest->handle; } return info; @@ -462,21 +499,18 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len) } static int -sev_launch_start(SEVState *s) +sev_launch_start(SevGuestState *sev) { gsize sz; int ret = 1; int fw_error, rc; - QSevGuestInfo *sev = s->sev_info; struct kvm_sev_launch_start *start; guchar *session = NULL, *dh_cert = NULL; start = g_new0(struct kvm_sev_launch_start, 1); - start->handle = object_property_get_int(OBJECT(sev), "handle", - &error_abort); - start->policy = object_property_get_int(OBJECT(sev), "policy", - &error_abort); + start->handle = sev->handle; + start->policy = sev->policy; if (sev->session_file) { if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) { goto out; @@ -494,18 +528,15 @@ sev_launch_start(SEVState *s) } trace_kvm_sev_launch_start(start->policy, session, dh_cert); - rc = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error); + rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error); if (rc < 0) { error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); goto out; } - object_property_set_int(OBJECT(sev), start->handle, "handle", - &error_abort); - sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE); - s->handle = start->handle; - s->policy = start->policy; + sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE); + sev->handle = start->handle; ret = 0; out: @@ -516,7 +547,7 @@ out: } static int -sev_launch_update_data(uint8_t *addr, uint64_t len) +sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len) { int ret, fw_error; struct kvm_sev_launch_update_data update; @@ -528,7 +559,7 @@ sev_launch_update_data(uint8_t *addr, uint64_t len) update.uaddr = (__u64)(unsigned long)addr; update.len = len; trace_kvm_sev_launch_update_data(addr, len); - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, &update, &fw_error); if (ret) { error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'", @@ -541,19 +572,19 @@ sev_launch_update_data(uint8_t *addr, uint64_t len) static void sev_launch_get_measure(Notifier *notifier, void *unused) { + SevGuestState *sev = sev_guest; int ret, error; guchar *data; - SEVState *s = sev_state; struct kvm_sev_launch_measure *measurement; - if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { + if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) { return; } measurement = g_new0(struct kvm_sev_launch_measure, 1); /* query the measurement blob length */ - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE, measurement, &error); if (!measurement->len) { error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", @@ -565,7 +596,7 @@ sev_launch_get_measure(Notifier *notifier, void *unused) measurement->uaddr = (unsigned long)data; /* get the measurement blob */ - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE, measurement, &error); if (ret) { error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", @@ -573,11 +604,11 @@ sev_launch_get_measure(Notifier *notifier, void *unused) goto free_data; } - sev_set_guest_state(SEV_STATE_LAUNCH_SECRET); + sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET); /* encode the measurement value and emit the event */ - s->measurement = g_base64_encode(data, measurement->len); - trace_kvm_sev_launch_measurement(s->measurement); + sev->measurement = g_base64_encode(data, measurement->len); + trace_kvm_sev_launch_measurement(sev->measurement); free_data: g_free(data); @@ -588,9 +619,9 @@ free_measurement: char * sev_get_launch_measurement(void) { - if (sev_state && - sev_state->state >= SEV_STATE_LAUNCH_SECRET) { - return g_strdup(sev_state->measurement); + if (sev_guest && + sev_guest->state >= SEV_STATE_LAUNCH_SECRET) { + return g_strdup(sev_guest->measurement); } return NULL; @@ -601,20 +632,20 @@ static Notifier sev_machine_done_notify = { }; static void -sev_launch_finish(SEVState *s) +sev_launch_finish(SevGuestState *sev) { int ret, error; Error *local_err = NULL; trace_kvm_sev_launch_finish(); - ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error); + ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error); if (ret) { error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'", __func__, ret, error, fw_error_to_str(error)); exit(1); } - sev_set_guest_state(SEV_STATE_RUNNING); + sev_set_guest_state(sev, SEV_STATE_RUNNING); /* add migration blocker */ error_setg(&sev_mig_blocker, @@ -630,11 +661,11 @@ sev_launch_finish(SEVState *s) static void sev_vm_state_change(void *opaque, int running, RunState state) { - SEVState *s = opaque; + SevGuestState *sev = opaque; if (running) { - if (!sev_check_state(SEV_STATE_RUNNING)) { - sev_launch_finish(s); + if (!sev_check_state(sev, SEV_STATE_RUNNING)) { + sev_launch_finish(sev); } } } @@ -642,55 +673,52 @@ sev_vm_state_change(void *opaque, int running, RunState state) void * sev_guest_init(const char *id) { - SEVState *s; + SevGuestState *sev; char *devname; int ret, fw_error; uint32_t ebx; uint32_t host_cbitpos; struct sev_user_data_status status = {}; - sev_state = s = g_new0(SEVState, 1); - s->sev_info = lookup_sev_guest_info(id); - if (!s->sev_info) { + sev = lookup_sev_guest_info(id); + if (!sev) { error_report("%s: '%s' is not a valid '%s' object", - __func__, id, TYPE_QSEV_GUEST_INFO); + __func__, id, TYPE_SEV_GUEST); goto err; } - s->state = SEV_STATE_UNINIT; + sev_guest = sev; + sev->state = SEV_STATE_UNINIT; host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL); host_cbitpos = ebx & 0x3f; - s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL); - if (host_cbitpos != s->cbitpos) { + if (host_cbitpos != sev->cbitpos) { error_report("%s: cbitpos check failed, host '%d' requested '%d'", - __func__, host_cbitpos, s->cbitpos); + __func__, host_cbitpos, sev->cbitpos); goto err; } - s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info), - "reduced-phys-bits", NULL); - if (s->reduced_phys_bits < 1) { + if (sev->reduced_phys_bits < 1) { error_report("%s: reduced_phys_bits check failed, it should be >=1," - " requested '%d'", __func__, s->reduced_phys_bits); + " requested '%d'", __func__, sev->reduced_phys_bits); goto err; } - s->me_mask = ~(1UL << s->cbitpos); + sev->me_mask = ~(1UL << sev->cbitpos); - devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL); - s->sev_fd = open(devname, O_RDWR); - if (s->sev_fd < 0) { + devname = object_property_get_str(OBJECT(sev), "sev-device", NULL); + sev->sev_fd = open(devname, O_RDWR); + if (sev->sev_fd < 0) { error_report("%s: Failed to open %s '%s'", __func__, devname, strerror(errno)); } g_free(devname); - if (s->sev_fd < 0) { + if (sev->sev_fd < 0) { goto err; } - ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status, + ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status, &fw_error); if (ret) { error_report("%s: failed to get platform status ret=%d " @@ -698,19 +726,19 @@ sev_guest_init(const char *id) fw_error_to_str(fw_error)); goto err; } - s->build_id = status.build; - s->api_major = status.api_major; - s->api_minor = status.api_minor; + sev->build_id = status.build; + sev->api_major = status.api_major; + sev->api_minor = status.api_minor; trace_kvm_sev_init(); - ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error); + ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error); if (ret) { error_report("%s: failed to initialize ret=%d fw_error=%d '%s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); goto err; } - ret = sev_launch_start(s); + ret = sev_launch_start(sev); if (ret) { error_report("%s: failed to create encryption context", __func__); goto err; @@ -718,23 +746,24 @@ sev_guest_init(const char *id) ram_block_notifier_add(&sev_ram_notifier); qemu_add_machine_init_done_notifier(&sev_machine_done_notify); - qemu_add_vm_change_state_handler(sev_vm_state_change, s); + qemu_add_vm_change_state_handler(sev_vm_state_change, sev); - return s; + return sev; err: - g_free(sev_state); - sev_state = NULL; + sev_guest = NULL; return NULL; } int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) { - assert(handle); + SevGuestState *sev = handle; + + assert(sev); /* if SEV is in update state then encrypt the data else do nothing */ - if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { - return sev_launch_update_data(ptr, len); + if (sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) { + return sev_launch_update_data(sev, ptr, len); } return 0; @@ -743,7 +772,7 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) static void sev_register_types(void) { - type_register_static(&qsev_guest_info); + type_register_static(&sev_guest_info); } type_init(sev_register_types); diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h index 8ada9d385d..8eb7de1bef 100644 --- a/target/i386/sev_i386.h +++ b/target/i386/sev_i386.h @@ -28,10 +28,6 @@ #define SEV_POLICY_DOMAIN 0x10 #define SEV_POLICY_SEV 0x20 -#define TYPE_QSEV_GUEST_INFO "sev-guest" -#define QSEV_GUEST_INFO(obj) \ - OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO) - extern bool sev_enabled(void); extern uint64_t sev_get_me_mask(void); extern SevInfo *sev_get_info(void); @@ -40,49 +36,4 @@ extern uint32_t sev_get_reduced_phys_bits(void); extern char *sev_get_launch_measurement(void); extern SevCapability *sev_get_capabilities(void); -typedef struct QSevGuestInfo QSevGuestInfo; -typedef struct QSevGuestInfoClass QSevGuestInfoClass; - -/** - * QSevGuestInfo: - * - * The QSevGuestInfo object is used for creating a SEV guest. - * - * # $QEMU \ - * -object sev-guest,id=sev0 \ - * -machine ...,memory-encryption=sev0 - */ -struct QSevGuestInfo { - Object parent_obj; - - char *sev_device; - uint32_t policy; - uint32_t handle; - char *dh_cert_file; - char *session_file; - uint32_t cbitpos; - uint32_t reduced_phys_bits; -}; - -struct QSevGuestInfoClass { - ObjectClass parent_class; -}; - -struct SEVState { - QSevGuestInfo *sev_info; - uint8_t api_major; - uint8_t api_minor; - uint8_t build_id; - uint32_t policy; - uint64_t me_mask; - uint32_t cbitpos; - uint32_t reduced_phys_bits; - uint32_t handle; - int sev_fd; - SevState state; - gchar *measurement; -}; - -typedef struct SEVState SEVState; - #endif diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 1988b436cb..e7d382ac10 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1202,6 +1202,7 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr); PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr); PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc); +#ifndef CONFIG_USER_ONLY struct PPCVirtualHypervisorClass { InterfaceClass parent; void (*hypercall)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); @@ -1215,10 +1216,8 @@ struct PPCVirtualHypervisorClass { void (*hpte_set_r)(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte1); void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry); target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp); -#ifndef CONFIG_USER_ONLY void (*cpu_exec_enter)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); void (*cpu_exec_exit)(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu); -#endif }; #define TYPE_PPC_VIRTUAL_HYPERVISOR "ppc-virtual-hypervisor" @@ -1230,6 +1229,7 @@ struct PPCVirtualHypervisorClass { #define PPC_VIRTUAL_HYPERVISOR_GET_CLASS(obj) \ OBJECT_GET_CLASS(PPCVirtualHypervisorClass, (obj), \ TYPE_PPC_VIRTUAL_HYPERVISOR) +#endif /* CONFIG_USER_ONLY */ void ppc_cpu_do_interrupt(CPUState *cpu); bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req); diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index fcaf745516..701c0c262b 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -280,6 +280,17 @@ static inline bool kvmppc_has_cap_spapr_vfio(void) return false; } +static inline void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, + hwaddr ptex, int n) +{ + abort(); +} + +static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) +{ + abort(); +} + #endif /* !CONFIG_USER_ONLY */ static inline bool kvmppc_has_cap_epr(void) @@ -310,17 +321,6 @@ static inline int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index, abort(); } -static inline void kvmppc_read_hptes(ppc_hash_pte64_t *hptes, - hwaddr ptex, int n) -{ - abort(); -} - -static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) -{ - abort(); -} - static inline bool kvmppc_has_cap_fixup_hcalls(void) { abort(); diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index 38cb773ab4..a40888411c 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -10942,16 +10942,20 @@ static const TypeInfo ppc_cpu_type_info = { .class_init = ppc_cpu_class_init, }; +#ifndef CONFIG_USER_ONLY static const TypeInfo ppc_vhyp_type_info = { .name = TYPE_PPC_VIRTUAL_HYPERVISOR, .parent = TYPE_INTERFACE, .class_size = sizeof(PPCVirtualHypervisorClass), }; +#endif static void ppc_cpu_register_types(void) { type_register_static(&ppc_cpu_type_info); +#ifndef CONFIG_USER_ONLY type_register_static(&ppc_vhyp_type_info); +#endif } type_init(ppc_cpu_register_types) |