From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60123) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZD71l-00016W-FX for qemu-devel@nongnu.org; Thu, 09 Jul 2015 04:17:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZD71k-0002Dy-5I for qemu-devel@nongnu.org; Thu, 09 Jul 2015 04:17:53 -0400 Received: from mail-oi0-x22f.google.com ([2607:f8b0:4003:c06::22f]:34657) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZD71j-0002Dr-Ts for qemu-devel@nongnu.org; Thu, 09 Jul 2015 04:17:52 -0400 Received: by oiab3 with SMTP id b3so66101422oia.1 for ; Thu, 09 Jul 2015 01:17:51 -0700 (PDT) Sender: Richard Henderson From: Richard Henderson Date: Thu, 9 Jul 2015 09:17:19 +0100 Message-Id: <1436429849-18052-5-git-send-email-rth@twiddle.net> In-Reply-To: <1436429849-18052-1-git-send-email-rth@twiddle.net> References: <1436429849-18052-1-git-send-email-rth@twiddle.net> Subject: [Qemu-devel] [PATCH 04/14] target-i386: Implement XSAVEOPT List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, ehabkost@redhat.com Note the cpu.c change -- don't advertise more XSAVE features than we implement. Signed-off-by: Richard Henderson --- target-i386/cpu.c | 2 +- target-i386/fpu_helper.c | 28 +++++++++++++++++++++++----- target-i386/helper.h | 1 + target-i386/translate.c | 27 ++++++++++++++++++++++++--- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 750eed1..b2fc59f 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -405,7 +405,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, [FEAT_XSAVE] = { .feat_names = cpuid_xsave_feature_name, - .cpuid_eax = 0xd, + .cpuid_eax = CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1, .cpuid_needs_ecx = true, .cpuid_ecx = 1, .cpuid_reg = R_EAX, .tcg_features = 0, diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 5e860b7..d0b960c 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -1181,7 +1181,8 @@ static uint64_t get_xinuse(CPUX86State *env) return -1; } -void helper_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm) +static void do_xsave(CPUX86State *env, target_ulong ptr, + uint64_t rfbm, uint64_t inuse, uint64_t opt) { uint64_t old_bv, new_bv; @@ -1192,21 +1193,36 @@ void helper_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm) /* Never save anything not enabled by XCR0. */ rfbm &= env->xcr0; + opt &= rfbm; - if (rfbm & XSTATE_FP) { + if (opt & XSTATE_FP) { do_xsave_fpu(env, ptr); } if (rfbm & XSTATE_SSE) { + /* Note that saving MXCSR is not suppressed by XSAVEOPT. */ do_xsave_mxcsr(env, ptr); + } + if (opt & XSTATE_SSE) { do_xsave_sse(env, ptr); } /* Update the XSTATE_BV field. */ old_bv = cpu_ldq_data(env, ptr + 512); - new_bv = (old_bv & ~rfbm) | (get_xinuse(env) & rfbm); + new_bv = (old_bv & ~rfbm) | (inuse & rfbm); cpu_stq_data(env, ptr + 512, new_bv); } +void helper_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm) +{ + do_xsave(env, ptr, rfbm, get_xinuse(env), -1); +} + +void helper_xsaveopt(CPUX86State *env, target_ulong ptr, uint64_t rfbm) +{ + uint64_t inuse = get_xinuse(env); + do_xsave(env, ptr, rfbm, inuse, inuse); +} + static void do_xrstor_fpu(CPUX86State *env, target_ulong ptr) { int i, fpus, fptag; @@ -1334,8 +1350,10 @@ uint64_t helper_xgetbv(CPUX86State *env, uint32_t ecx) case 0: return env->xcr0; case 1: - /* FIXME: #GP if !CPUID.(EAX=0DH,ECX=1):EAX.XG1[bit 2]. */ - return env->xcr0 & get_xinuse(env); + if (env->features[FEAT_XSAVE] & CPUID_XSAVE_XGETBV1) { + return env->xcr0 & get_xinuse(env); + } + break; } raise_exception(env, EXCP0D_GPF); } diff --git a/target-i386/helper.h b/target-i386/helper.h index 1ea4998..e6df35c 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -186,6 +186,7 @@ DEF_HELPER_3(frstor, void, env, tl, int) DEF_HELPER_FLAGS_2(fxsave, TCG_CALL_NO_WG, void, env, tl) DEF_HELPER_FLAGS_2(fxrstor, TCG_CALL_NO_WG, void, env, tl) DEF_HELPER_FLAGS_3(xsave, TCG_CALL_NO_WG, void, env, tl, i64) +DEF_HELPER_FLAGS_3(xsaveopt, TCG_CALL_NO_WG, void, env, tl, i64) DEF_HELPER_FLAGS_3(xrstor, TCG_CALL_NO_WG, void, env, tl, i64) DEF_HELPER_FLAGS_2(xgetbv, TCG_CALL_NO_WG, i64, env, i32) DEF_HELPER_FLAGS_3(xsetbv, TCG_CALL_NO_WG, void, env, i32, i64) diff --git a/target-i386/translate.c b/target-i386/translate.c index e9992aa..a98347f 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -133,6 +133,7 @@ typedef struct DisasContext { int cpuid_ext2_features; int cpuid_ext3_features; int cpuid_7_0_ebx_features; + int cpuid_xsave_features; } DisasContext; static void gen_eob(DisasContext *s); @@ -7715,9 +7716,28 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_helper_xrstor(cpu_env, cpu_A0, cpu_tmp1_i64); } break; - case 6: /* mfence */ - if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2)) - goto illegal_op; + case 6: + if (mod == 3) { + /* mfence */ + if (!(s->cpuid_features & CPUID_SSE2) + || (s->prefix & PREFIX_LOCK)) { + goto illegal_op; + } + /* no-op */ + } else { + /* xsaveopt */ + if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0 + || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0 + || (s->flags & HF_OSXSAVE_MASK) == 0 + || (s->prefix & (PREFIX_LOCK | PREFIX_DATA + | PREFIX_REPZ | PREFIX_REPNZ))) { + goto illegal_op; + } + gen_lea_modrm(env, s, modrm); + tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX], + cpu_regs[R_EDX]); + gen_helper_xsaveopt(cpu_env, cpu_A0, cpu_tmp1_i64); + } break; case 7: /* sfence / clflush */ if ((modrm & 0xc7) == 0xc0) { @@ -7917,6 +7937,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX]; dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX]; dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX]; + dc->cpuid_xsave_features = env->features[FEAT_XSAVE]; #ifdef TARGET_X86_64 dc->lma = (flags >> HF_LMA_SHIFT) & 1; dc->code64 = (flags >> HF_CS64_SHIFT) & 1; -- 2.4.3