diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-03-28 18:47:57 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-06-05 16:10:34 +0200 |
commit | 81cf8d8adc64203567e03326c13ea4abec9fe5df (patch) | |
tree | e84fe22b7f5a14a85bf9e3a8b8736d07ba89024d /target-i386/seg_helper.c | |
parent | 43773ed369a2e1f6c347e30c74df27a8750d1d2d (diff) |
target-i386: move check_io helpers to seg_helper.c
Prepare for adding _kernel accessors there in the next patch.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target-i386/seg_helper.c')
-rw-r--r-- | target-i386/seg_helper.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index ba472154e8..31c5508e6c 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -2469,3 +2469,45 @@ void cpu_x86_load_seg(CPUX86State *env, int seg_reg, int selector) } } #endif + +/* check if Port I/O is allowed in TSS */ +static inline void check_io(CPUX86State *env, int addr, int size) +{ + 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(env, env->tr.base + 0x66); + io_offset += (addr >> 3); + /* Note: the check needs two bytes */ + if ((io_offset + 1) > env->tr.limit) { + goto fail; + } + val = cpu_lduw_kernel(env, env->tr.base + io_offset); + 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(env, EXCP0D_GPF, 0); + } +} + +void helper_check_iob(CPUX86State *env, uint32_t t0) +{ + check_io(env, t0, 1); +} + +void helper_check_iow(CPUX86State *env, uint32_t t0) +{ + check_io(env, t0, 2); +} + +void helper_check_iol(CPUX86State *env, uint32_t t0) +{ + check_io(env, t0, 4); +} |