Skip to content

Commit

Permalink
target/i386: Cleanup read_crN, write_crN, lmsw
Browse files Browse the repository at this point in the history
Pull the svm intercept check into the translator.
Pull the entire implementation of lmsw into the translator.
Push the check for CR8LEG into the regno validation switch.
Unify the gen_io_start check between read/write.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20210514151342.384376-40-richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 19, 2021
1 parent 3d4fce8 commit 7eff2e7
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 58 deletions.
5 changes: 2 additions & 3 deletions target/i386/helper.h
Expand Up @@ -42,9 +42,8 @@ DEF_HELPER_5(lcall_protected, void, env, int, tl, int, tl)
DEF_HELPER_2(iret_real, void, env, int)
DEF_HELPER_3(iret_protected, void, env, int, int)
DEF_HELPER_3(lret_protected, void, env, int, int)
DEF_HELPER_2(read_crN, tl, env, int)
DEF_HELPER_3(write_crN, void, env, int, tl)
DEF_HELPER_2(lmsw, void, env, tl)
DEF_HELPER_FLAGS_2(read_crN, TCG_CALL_NO_RWG, tl, env, int)
DEF_HELPER_FLAGS_3(write_crN, TCG_CALL_NO_RWG, void, env, int, tl)
DEF_HELPER_1(clts, void, env)

#ifndef CONFIG_USER_ONLY
Expand Down
8 changes: 0 additions & 8 deletions target/i386/tcg/misc_helper.c
Expand Up @@ -60,14 +60,6 @@ void helper_cpuid(CPUX86State *env)
env->regs[R_EDX] = edx;
}

void helper_lmsw(CPUX86State *env, target_ulong t0)
{
/* only 4 lower bits of CR0 are modified. PE cannot be set to zero
if already set to one. */
t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
helper_write_crN(env, 0, t0);
}

void helper_invlpg(CPUX86State *env, target_ulong addr)
{
X86CPU *cpu = env_archcpu(env);
Expand Down
2 changes: 0 additions & 2 deletions target/i386/tcg/sysemu/misc_helper.c
Expand Up @@ -65,7 +65,6 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
{
target_ulong val;

cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
switch (reg) {
default:
val = env->cr[reg];
Expand All @@ -83,7 +82,6 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)

void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
switch (reg) {
case 0:
cpu_x86_update_cr0(env, t0);
Expand Down
97 changes: 52 additions & 45 deletions target/i386/tcg/translate.c
Expand Up @@ -7654,13 +7654,22 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
gen_helper_wrpkru(cpu_env, s->tmp2_i32, s->tmp1_i64);
break;

CASE_MODRM_OP(6): /* lmsw */
if (!check_cpl0(s)) {
break;
}
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
gen_helper_lmsw(cpu_env, s->T0);
/*
* Only the 4 lower bits of CR0 are modified.
* PE cannot be set to zero if already set to one.
*/
tcg_gen_ld_tl(s->T1, cpu_env, offsetof(CPUX86State, cr[0]));
tcg_gen_andi_tl(s->T0, s->T0, 0xf);
tcg_gen_andi_tl(s->T1, s->T1, ~0xe);
tcg_gen_or_tl(s->T0, s->T0, s->T1);
gen_helper_write_crN(cpu_env, tcg_constant_i32(0), s->T0);
gen_jmp_im(s, s->pc - s->cs_base);
gen_eob(s);
break;
Expand Down Expand Up @@ -8034,58 +8043,56 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
modrm = x86_ldub_code(env, s);
gen_nop_modrm(env, s, modrm);
break;

case 0x120: /* mov reg, crN */
case 0x122: /* mov crN, reg */
if (check_cpl0(s)) {
modrm = x86_ldub_code(env, s);
/* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
* AMD documentation (24594.pdf) and testing of
* intel 386 and 486 processors all show that the mod bits
* are assumed to be 1's, regardless of actual values.
*/
rm = (modrm & 7) | REX_B(s);
reg = ((modrm >> 3) & 7) | REX_R(s);
if (CODE64(s))
ot = MO_64;
else
ot = MO_32;
if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
if (!check_cpl0(s)) {
break;
}
modrm = x86_ldub_code(env, s);
/*
* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
* AMD documentation (24594.pdf) and testing of Intel 386 and 486
* processors all show that the mod bits are assumed to be 1's,
* regardless of actual values.
*/
rm = (modrm & 7) | REX_B(s);
reg = ((modrm >> 3) & 7) | REX_R(s);
switch (reg) {
case 0:
if ((prefixes & PREFIX_LOCK) &&
(s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
reg = 8;
}
switch(reg) {
case 0:
case 2:
case 3:
case 4:
case 8:
gen_update_cc_op(s);
gen_jmp_im(s, pc_start - s->cs_base);
if (b & 2) {
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_op_mov_v_reg(s, ot, s->T0, rm);
gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
s->T0);
gen_jmp_im(s, s->pc - s->cs_base);
gen_eob(s);
} else {
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg));
gen_op_mov_reg_v(s, ot, rm, s->T0);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_jmp(s, s->pc - s->cs_base);
}
}
break;
default:
goto unknown_op;
break;
case 2:
case 3:
case 4:
break;
default:
goto unknown_op;
}
ot = (CODE64(s) ? MO_64 : MO_32);

if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
if (b & 2) {
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
gen_op_mov_v_reg(s, ot, s->T0, rm);
gen_helper_write_crN(cpu_env, tcg_constant_i32(reg), s->T0);
gen_jmp_im(s, s->pc - s->cs_base);
gen_eob(s);
} else {
gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
gen_helper_read_crN(s->T0, cpu_env, tcg_constant_i32(reg));
gen_op_mov_reg_v(s, ot, rm, s->T0);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_jmp(s, s->pc - s->cs_base);
}
}
break;

case 0x121: /* mov reg, drN */
case 0x123: /* mov drN, reg */
if (check_cpl0(s)) {
Expand Down

0 comments on commit 7eff2e7

Please sign in to comment.