Skip to content

Commit

Permalink
target/i386: Move helper_check_io to sysemu
Browse files Browse the repository at this point in the history
The we never allow i/o from user-only, and the tss check
that helper_check_io does will always fail.  Use an ifdef
within gen_check_io and return false, indicating that an
exception is known to be raised.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20210514151342.384376-50-richard.henderson@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 19, 2021
1 parent e497803 commit d76b9c6
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 30 deletions.
2 changes: 1 addition & 1 deletion target/i386/helper.h
Expand Up @@ -86,7 +86,6 @@ DEF_HELPER_1(rdtsc, void, env)
DEF_HELPER_1(rdtscp, void, env)
DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)

DEF_HELPER_FLAGS_3(check_io, TCG_CALL_NO_WG, void, env, i32, i32)
DEF_HELPER_3(outb, void, env, i32, i32)
DEF_HELPER_2(inb, tl, env, i32)
DEF_HELPER_3(outw, void, env, i32, i32)
Expand All @@ -95,6 +94,7 @@ 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)
DEF_HELPER_2(svm_check_intercept, void, env, i32)
DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32)
Expand Down
28 changes: 0 additions & 28 deletions target/i386/tcg/seg_helper.c
Expand Up @@ -2416,31 +2416,3 @@ void helper_verw(CPUX86State *env, target_ulong selector1)
}
CC_SRC = eflags | CC_Z;
}

/* check if Port I/O is allowed in TSS */
void helper_check_io(CPUX86State *env, uint32_t addr, uint32_t size)
{
uintptr_t retaddr = GETPC();
uint32_t 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);
}
}
29 changes: 29 additions & 0 deletions target/i386/tcg/sysemu/seg_helper.c
Expand Up @@ -23,6 +23,7 @@
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
#include "tcg/helper-tcg.h"
#include "../seg_helper.h"

#ifdef TARGET_X86_64
void helper_syscall(CPUX86State *env, int next_eip_addend)
Expand Down Expand Up @@ -123,3 +124,31 @@ void x86_cpu_do_interrupt(CPUState *cs)
env->old_exception = -1;
}
}

/* check if Port I/O is allowed in TSS */
void helper_check_io(CPUX86State *env, uint32_t addr, uint32_t size)
{
uintptr_t retaddr = GETPC();
uint32_t 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);
}
}
11 changes: 10 additions & 1 deletion target/i386/tcg/translate.c
Expand Up @@ -203,7 +203,6 @@ STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
STUB_HELPER(stgi, TCGv_env env)
STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
STUB_HELPER(svm_check_io, TCGv_env env, TCGv_i32 port, TCGv_i32 p, TCGv_i32 a)
STUB_HELPER(vmload, TCGv_env env, TCGv_i32 aflag)
STUB_HELPER(vmmcall, TCGv_env env)
STUB_HELPER(vmrun, TCGv_env env, TCGv_i32 aflag, TCGv_i32 pc_ofs)
Expand All @@ -217,6 +216,7 @@ static void gen_jr(DisasContext *s, TCGv dest);
static void gen_jmp(DisasContext *s, target_ulong eip);
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
static void gen_exception_gpf(DisasContext *s);

/* i386 arith/logic operations */
enum {
Expand Down Expand Up @@ -681,6 +681,14 @@ static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
uint32_t svm_flags)
{
#ifdef CONFIG_USER_ONLY
/*
* We do not implement the ioperm(2) syscall, so the TSS check
* will always fail.
*/
gen_exception_gpf(s);
return false;
#else
if (PE(s) && (CPL(s) > IOPL(s) || VM86(s))) {
gen_helper_check_io(cpu_env, port, tcg_constant_i32(1 << ot));
}
Expand All @@ -699,6 +707,7 @@ static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
tcg_constant_i32(next_eip - cur_eip));
}
return true;
#endif
}

static inline void gen_movs(DisasContext *s, MemOp ot)
Expand Down

0 comments on commit d76b9c6

Please sign in to comment.