Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-x86-202105…
Browse files Browse the repository at this point in the history
…19' into staging

Eliminate user-only helper stubs for privledged insns.

# gpg: Signature made Wed 19 May 2021 19:24:27 BST
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* remotes/rth-gitlab/tags/pull-x86-20210519: (50 commits)
  target/i386: Remove user-only i/o stubs
  target/i386: Move helper_check_io to sysemu
  target/i386: Create helper_check_io
  target/i386: Pass in port to gen_check_io
  target/i386: Tidy gen_check_io
  target/i386: Exit tb after wrmsr
  target/i386: Eliminate user stubs for read/write_crN, rd/wrmsr
  target/i386: Inline user cpu_svm_check_intercept_param
  target/i386: Unify invlpg, invlpga
  target/i386: Move invlpg, hlt, monitor, mwait to sysemu
  target/i386: Pass env to do_pause and do_hlt
  target/i386: Cleanup read_crN, write_crN, lmsw
  target/i386: Remove user stub for cpu_vmexit
  target/i386: Remove pc_start argument to gen_svm_check_intercept
  target/i386: Tidy svm_check_intercept from tcg
  target/i386: Simplify gen_debug usage
  target/i386: Mark some helpers as noreturn
  target/i386: Eliminate SVM helpers for user-only
  target/i386: Implement skinit in translate.c
  target/i386: Assert !GUEST for user-only
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed May 20, 2021
2 parents fea2ad7 + 7fb7c42 commit be05216
Show file tree
Hide file tree
Showing 14 changed files with 592 additions and 753 deletions.
8 changes: 8 additions & 0 deletions target/i386/cpu.h
Expand Up @@ -2146,8 +2146,16 @@ static inline void cpu_set_fpuc(CPUX86State *env, uint16_t fpuc)
void helper_lock_init(void);

/* svm_helper.c */
#ifdef CONFIG_USER_ONLY
static inline void
cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
uint64_t param, uintptr_t retaddr)
{ /* no-op */ }
#else
void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
uint64_t param, uintptr_t retaddr);
#endif

/* apic.c */
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
Expand Down
43 changes: 18 additions & 25 deletions target/i386/helper.h
Expand Up @@ -42,32 +42,25 @@ 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_1(clts, void, env)

#ifndef CONFIG_USER_ONLY
DEF_HELPER_FLAGS_3(set_dr, TCG_CALL_NO_WG, void, env, int, tl)
#endif /* !CONFIG_USER_ONLY */

DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int)
DEF_HELPER_2(invlpg, void, env, tl)

DEF_HELPER_1(sysenter, void, env)
DEF_HELPER_2(sysexit, void, env, int)
#ifdef TARGET_X86_64
DEF_HELPER_2(syscall, void, env, int)
DEF_HELPER_2(sysret, void, env, int)
#endif
DEF_HELPER_2(hlt, void, env, int)
DEF_HELPER_2(monitor, void, env, tl)
DEF_HELPER_2(mwait, void, env, int)
DEF_HELPER_2(pause, void, env, int)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_FLAGS_2(pause, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_FLAGS_1(debug, TCG_CALL_NO_WG, noreturn, env)
DEF_HELPER_1(reset_rf, void, env)
DEF_HELPER_3(raise_interrupt, void, env, int, int)
DEF_HELPER_2(raise_exception, void, env, int)
DEF_HELPER_FLAGS_3(raise_interrupt, TCG_CALL_NO_WG, noreturn, env, int, int)
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_1(cli, void, env)
DEF_HELPER_1(sti, void, env)
DEF_HELPER_1(clac, void, env)
Expand All @@ -86,39 +79,39 @@ DEF_HELPER_2(cmpxchg8b, void, env, tl)
DEF_HELPER_2(cmpxchg16b_unlocked, void, env, tl)
DEF_HELPER_2(cmpxchg16b, void, env, tl)
#endif
DEF_HELPER_1(single_step, void, env)
DEF_HELPER_FLAGS_1(single_step, TCG_CALL_NO_WG, noreturn, env)
DEF_HELPER_1(rechecking_single_step, void, env)
DEF_HELPER_1(cpuid, void, env)
DEF_HELPER_1(rdtsc, void, env)
DEF_HELPER_1(rdtscp, void, env)
DEF_HELPER_1(rdpmc, void, env)
DEF_HELPER_1(rdmsr, void, env)
DEF_HELPER_1(wrmsr, void, env)
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)

DEF_HELPER_2(check_iob, void, env, i32)
DEF_HELPER_2(check_iow, void, env, i32)
DEF_HELPER_2(check_iol, void, env, i32)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_3(outb, void, env, i32, i32)
DEF_HELPER_2(inb, tl, env, i32)
DEF_HELPER_3(outw, void, env, i32, i32)
DEF_HELPER_2(inw, tl, env, i32)
DEF_HELPER_3(outl, void, env, i32, i32)
DEF_HELPER_2(inl, tl, env, i32)

#ifndef CONFIG_USER_ONLY
DEF_HELPER_FLAGS_3(check_io, TCG_CALL_NO_WG, void, env, i32, i32)
DEF_HELPER_FLAGS_4(bpt_io, TCG_CALL_NO_WG, void, env, i32, i32, tl)
#endif /* !CONFIG_USER_ONLY */

DEF_HELPER_3(svm_check_intercept_param, void, env, i32, i64)
DEF_HELPER_2(svm_check_intercept, void, env, i32)
DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32)
DEF_HELPER_3(vmrun, void, env, int, int)
DEF_HELPER_1(vmmcall, void, env)
DEF_HELPER_2(vmload, void, env, int)
DEF_HELPER_2(vmsave, void, env, int)
DEF_HELPER_1(stgi, void, env)
DEF_HELPER_1(clgi, void, env)
DEF_HELPER_1(skinit, void, env)
DEF_HELPER_2(invlpga, void, env, int)
DEF_HELPER_FLAGS_2(flush_page, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(hlt, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_FLAGS_2(monitor, TCG_CALL_NO_WG, void, env, tl)
DEF_HELPER_FLAGS_2(mwait, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_1(rdmsr, void, env)
DEF_HELPER_1(wrmsr, void, env)
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)
#endif /* !CONFIG_USER_ONLY */

/* x86 FPU */

Expand Down
2 changes: 1 addition & 1 deletion target/i386/tcg/bpt_helper.c
Expand Up @@ -22,7 +22,7 @@
#include "exec/helper-proto.h"
#include "helper-tcg.h"

void helper_single_step(CPUX86State *env)
void QEMU_NORETURN helper_single_step(CPUX86State *env)
{
#ifndef CONFIG_USER_ONLY
check_hw_breakpoints(env, true);
Expand Down
18 changes: 10 additions & 8 deletions target/i386/tcg/excp_helper.c
Expand Up @@ -25,12 +25,13 @@
#include "exec/helper-proto.h"
#include "helper-tcg.h"

void helper_raise_interrupt(CPUX86State *env, int intno, int next_eip_addend)
void QEMU_NORETURN helper_raise_interrupt(CPUX86State *env, int intno,
int next_eip_addend)
{
raise_interrupt(env, intno, 1, 0, next_eip_addend);
}

void helper_raise_exception(CPUX86State *env, int exception_index)
void QEMU_NORETURN helper_raise_exception(CPUX86State *env, int exception_index)
{
raise_exception(env, exception_index);
}
Expand Down Expand Up @@ -116,24 +117,25 @@ void QEMU_NORETURN raise_interrupt(CPUX86State *env, int intno, int is_int,
raise_interrupt2(env, intno, is_int, error_code, next_eip_addend, 0);
}

void raise_exception_err(CPUX86State *env, int exception_index,
int error_code)
void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index,
int error_code)
{
raise_interrupt2(env, exception_index, 0, error_code, 0, 0);
}

void raise_exception_err_ra(CPUX86State *env, int exception_index,
int error_code, uintptr_t retaddr)
void QEMU_NORETURN raise_exception_err_ra(CPUX86State *env, int exception_index,
int error_code, uintptr_t retaddr)
{
raise_interrupt2(env, exception_index, 0, error_code, 0, retaddr);
}

void raise_exception(CPUX86State *env, int exception_index)
void QEMU_NORETURN raise_exception(CPUX86State *env, int exception_index)
{
raise_interrupt2(env, exception_index, 0, 0, 0, 0);
}

void raise_exception_ra(CPUX86State *env, int exception_index, uintptr_t retaddr)
void QEMU_NORETURN raise_exception_ra(CPUX86State *env, int exception_index,
uintptr_t retaddr)
{
raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
}
5 changes: 4 additions & 1 deletion target/i386/tcg/helper-tcg.h
Expand Up @@ -76,11 +76,14 @@ extern const uint8_t parity_table[256];

/* misc_helper.c */
void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask);
void do_pause(CPUX86State *env) QEMU_NORETURN;

/* svm_helper.c */
/* sysemu/svm_helper.c */
#ifndef CONFIG_USER_ONLY
void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code,
uint64_t exit_info_1, uintptr_t retaddr);
void do_vmexit(CPUX86State *env);
#endif

/* seg_helper.c */
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
Expand Down
79 changes: 6 additions & 73 deletions target/i386/tcg/misc_helper.c
Expand Up @@ -60,22 +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);

cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
tlb_flush_page(CPU(cpu), addr);
}

void helper_rdtsc(CPUX86State *env)
{
uint64_t val;
Expand All @@ -96,7 +80,7 @@ void helper_rdtscp(CPUX86State *env)
env->regs[R_ECX] = (uint32_t)(env->tsc_aux);
}

void helper_rdpmc(CPUX86State *env)
void QEMU_NORETURN helper_rdpmc(CPUX86State *env)
{
if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
((env->hflags & HF_CPL_MASK) != 0)) {
Expand All @@ -109,75 +93,24 @@ void helper_rdpmc(CPUX86State *env)
raise_exception_err(env, EXCP06_ILLOP, 0);
}

static void do_pause(X86CPU *cpu)
void QEMU_NORETURN do_pause(CPUX86State *env)
{
CPUState *cs = CPU(cpu);
CPUState *cs = env_cpu(env);

/* Just let another CPU run. */
cs->exception_index = EXCP_INTERRUPT;
cpu_loop_exit(cs);
}

static void do_hlt(X86CPU *cpu)
{
CPUState *cs = CPU(cpu);
CPUX86State *env = &cpu->env;

env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
cs->halted = 1;
cs->exception_index = EXCP_HLT;
cpu_loop_exit(cs);
}

void helper_hlt(CPUX86State *env, int next_eip_addend)
void QEMU_NORETURN helper_pause(CPUX86State *env, int next_eip_addend)
{
X86CPU *cpu = env_archcpu(env);

cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
env->eip += next_eip_addend;

do_hlt(cpu);
}

void helper_monitor(CPUX86State *env, target_ulong ptr)
{
if ((uint32_t)env->regs[R_ECX] != 0) {
raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
/* XXX: store address? */
cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
}

void helper_mwait(CPUX86State *env, int next_eip_addend)
{
CPUState *cs = env_cpu(env);
X86CPU *cpu = env_archcpu(env);

if ((uint32_t)env->regs[R_ECX] != 0) {
raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
env->eip += next_eip_addend;

/* XXX: not complete but not completely erroneous */
if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
do_pause(cpu);
} else {
do_hlt(cpu);
}
}

void helper_pause(CPUX86State *env, int next_eip_addend)
{
X86CPU *cpu = env_archcpu(env);

cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
env->eip += next_eip_addend;

do_pause(cpu);
do_pause(env);
}

void helper_debug(CPUX86State *env)
void QEMU_NORETURN helper_debug(CPUX86State *env)
{
CPUState *cs = env_cpu(env);

Expand Down
43 changes: 0 additions & 43 deletions target/i386/tcg/seg_helper.c
Expand Up @@ -2416,46 +2416,3 @@ void helper_verw(CPUX86State *env, target_ulong selector1)
}
CC_SRC = eflags | CC_Z;
}

/* check if Port I/O is allowed in TSS */
static inline void check_io(CPUX86State *env, int addr, int size,
uintptr_t retaddr)
{
int io_offset, val, mask;

/* TSS must be a valid 32 bit one */
if (!(env->tr.flags & DESC_P_MASK) ||
((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
env->tr.limit < 103) {
goto fail;
}
io_offset = cpu_lduw_kernel_ra(env, env->tr.base + 0x66, retaddr);
io_offset += (addr >> 3);
/* Note: the check needs two bytes */
if ((io_offset + 1) > env->tr.limit) {
goto fail;
}
val = cpu_lduw_kernel_ra(env, env->tr.base + io_offset, retaddr);
val >>= (addr & 7);
mask = (1 << size) - 1;
/* all bits must be zero to allow the I/O */
if ((val & mask) != 0) {
fail:
raise_exception_err_ra(env, EXCP0D_GPF, 0, retaddr);
}
}

void helper_check_iob(CPUX86State *env, uint32_t t0)
{
check_io(env, t0, 1, GETPC());
}

void helper_check_iow(CPUX86State *env, uint32_t t0)
{
check_io(env, t0, 2, GETPC());
}

void helper_check_iol(CPUX86State *env, uint32_t t0)
{
check_io(env, t0, 4, GETPC());
}

0 comments on commit be05216

Please sign in to comment.