[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 08/50] target/i386: Assert IOPL is 0 for user-only
From: |
Richard Henderson |
Subject: |
[PATCH 08/50] target/i386: Assert IOPL is 0 for user-only |
Date: |
Sun, 28 Feb 2021 15:22:39 -0800 |
On real hardware, the linux kernel has the iopl(2) syscall which
can set IOPL to 3, to allow e.g. the xserver to briefly disable
interrupts while programming the graphics card.
However, QEMU cannot and does not implement this syscall, so the
IOPL is never changed from 0. Which means that all of the checks
vs CPL <= IOPL are false for user-only.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 50dc693edc..5f24615826 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -97,6 +97,7 @@ typedef struct DisasContext {
#ifndef CONFIG_USER_ONLY
uint8_t cpl; /* code priv level */
+ uint8_t iopl; /* i/o priv level */
#endif
int code32; /* 32 bit code segment */
@@ -116,7 +117,6 @@ typedef struct DisasContext {
int addseg; /* non zero if either DS/ES/SS have a non zero base */
int f_st; /* currently unused */
int vm86; /* vm86 mode */
- int iopl;
int tf; /* TF cpu flag */
int jmp_opt; /* use direct block chaining for direct jumps */
int repz_opt; /* optimize jumps within repz instructions */
@@ -153,9 +153,11 @@ typedef struct DisasContext {
#ifdef CONFIG_USER_ONLY
#define PE(S) true
#define CPL(S) 3
+#define IOPL(S) 0
#else
#define PE(S) (((S)->flags & HF_PE_MASK) != 0)
#define CPL(S) ((S)->cpl)
+#define IOPL(S) ((S)->iopl)
#endif
static void gen_eob(DisasContext *s);
@@ -629,7 +631,7 @@ static void gen_check_io(DisasContext *s, MemOp ot,
target_ulong cur_eip,
{
target_ulong next_eip;
- if (PE(s) && (CPL(s) > s->iopl || s->vm86)) {
+ if (PE(s) && (CPL(s) > IOPL(s) || s->vm86)) {
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
switch (ot) {
case MO_8:
@@ -1307,7 +1309,7 @@ static bool check_cpl0(DisasContext *s)
/* If vm86, check for iopl == 3; if not, raise #GP and return false. */
static bool check_vm86_iopl(DisasContext *s)
{
- if (!s->vm86 || s->iopl == 3) {
+ if (!s->vm86 || IOPL(s) == 3) {
return true;
}
gen_exception_gpf(s);
@@ -1317,7 +1319,7 @@ static bool check_vm86_iopl(DisasContext *s)
/* Check for iopl allowing access; if not, raise #GP and return false. */
static bool check_iopl(DisasContext *s)
{
- if (s->vm86 ? s->iopl == 3 : CPL(s) <= s->iopl) {
+ if (s->vm86 ? IOPL(s) == 3 : CPL(s) <= IOPL(s)) {
return true;
}
gen_exception_gpf(s);
@@ -6750,7 +6752,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState
*cpu)
& 0xffff));
}
} else {
- if (CPL(s) <= s->iopl) {
+ if (CPL(s) <= IOPL(s)) {
if (dflag != MO_16) {
gen_helper_write_eflags(cpu_env, s->T0,
tcg_const_i32((TF_MASK |
@@ -8468,23 +8470,25 @@ static void i386_tr_init_disas_context(DisasContextBase
*dcbase, CPUState *cpu)
CPUX86State *env = cpu->env_ptr;
uint32_t flags = dc->base.tb->flags;
int cpl = (flags >> HF_CPL_SHIFT) & 3;
+ int iopl = (flags >> IOPL_SHIFT) & 3;
dc->cs_base = dc->base.tb->cs_base;
dc->flags = flags;
#ifndef CONFIG_USER_ONLY
dc->cpl = cpl;
+ dc->iopl = iopl;
#endif
/* We make some simplifying assumptions; validate they're correct. */
g_assert(PE(dc) == ((flags & HF_PE_MASK) != 0));
g_assert(CPL(dc) == cpl);
+ g_assert(IOPL(dc) == iopl);
dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
dc->f_st = 0;
dc->vm86 = (flags >> VM_SHIFT) & 1;
- dc->iopl = (flags >> IOPL_SHIFT) & 3;
dc->tf = (flags >> TF_SHIFT) & 1;
dc->cc_op = CC_OP_DYNAMIC;
dc->cc_op_dirty = false;
--
2.25.1
- [PATCH 00/50] i386 cleanup part 3, Richard Henderson, 2021/02/28
- [PATCH 01/50] target/i386: Split out gen_exception_gpf, Richard Henderson, 2021/02/28
- [PATCH 03/50] target/i386: Unify code paths for IRET, Richard Henderson, 2021/02/28
- [PATCH 02/50] target/i386: Split out check_cpl0, Richard Henderson, 2021/02/28
- [PATCH 05/50] target/i386: Split out check_iopl, Richard Henderson, 2021/02/28
- [PATCH 07/50] target/i386: Assert CPL is 3 for user-only, Richard Henderson, 2021/02/28
- [PATCH 04/50] target/i386: Split out check_vm86_iopl, Richard Henderson, 2021/02/28
- [PATCH 11/50] target/i386: Assert SS32 for x86_64 user-only, Richard Henderson, 2021/02/28
- [PATCH 09/50] target/i386: Assert !VM86 for x86_64 user-only, Richard Henderson, 2021/02/28
- [PATCH 08/50] target/i386: Assert IOPL is 0 for user-only,
Richard Henderson <=
- [PATCH 06/50] target/i386: Assert PE is set for user-only, Richard Henderson, 2021/02/28
- [PATCH 13/50] target/i386: Assert LMA for x86_64 user-only, Richard Henderson, 2021/02/28
- [PATCH 12/50] target/i386: Assert CODE64 for x86_64 user-only, Richard Henderson, 2021/02/28
- [PATCH 18/50] target/i386: Move rex_w into DisasContext, Richard Henderson, 2021/02/28
- [PATCH 10/50] target/i386: Assert CODE32 for x86_64 user-only, Richard Henderson, 2021/02/28
- [PATCH 15/50] target/i386: Introduce REX_PREFIX, Richard Henderson, 2021/02/28
- [PATCH 16/50] target/i386: Tidy REX_B, REX_X definition, Richard Henderson, 2021/02/28
- [PATCH 19/50] target/i386: Remove DisasContext.f_st as unused, Richard Henderson, 2021/02/28
- [PATCH 21/50] target/i386: Reduce DisasContext.override to int8_t, Richard Henderson, 2021/02/28
- [PATCH 14/50] target/i386: Assert !ADDSEG for x86_64 user-only, Richard Henderson, 2021/02/28