aboutsummaryrefslogtreecommitdiff
path: root/target/i386/tcg/sysemu
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-05-14 10:13:41 -0500
committerRichard Henderson <richard.henderson@linaro.org>2021-05-19 12:17:11 -0500
commitd76b9c6f07a2981a44887e1d61d51e016d45417c (patch)
tree305b06b42b81ae8794170446b6b3f3b1b9887f57 /target/i386/tcg/sysemu
parente49780355674a77c174564fd6b34494475876291 (diff)
target/i386: Move helper_check_io to sysemu
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>
Diffstat (limited to 'target/i386/tcg/sysemu')
-rw-r--r--target/i386/tcg/sysemu/seg_helper.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/target/i386/tcg/sysemu/seg_helper.c b/target/i386/tcg/sysemu/seg_helper.c
index e0d7b32b82..82c0856c41 100644
--- a/target/i386/tcg/sysemu/seg_helper.c
+++ b/target/i386/tcg/sysemu/seg_helper.c
@@ -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)
@@ -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);
+ }
+}