Eliminate user-only helper stubs for privledged insns.

-----BEGIN PGP SIGNATURE-----
 
 iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmClV9sdHHJpY2hhcmQu
 aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/ZUwf+LbFwBEaTnH4DHstc
 CygLp5zmQr565+HIvQkeAjpjj1wYDvPg1yzvUHk2s0PObsfDRjyYb2G80kyWRSZ3
 w+05Tmt9jXICfgP+xkgPvmigYxxUBcbiSjle4vSjlvqlp8bgonG1BOvf7EpII6R9
 omT55KvOVkfLQz+fAszNsGurFLkIE8ToYfnpo/1j6RaDGwWUyx9ylwPM37YPfcl9
 OwZFoiWjfEc5SG4cRhd8PdxmZrGvVODeadUP+xbn/j6CJw+ReMeTj2lzyUOHwjoC
 uQItSAZPjD6BiFgYcn204yLVXuhp219CzVHVOGOEbehaGC5A7rZjS2L8zAp7u0io
 CK0pOA==
 =UP1f
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-x86-20210519' 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>
This commit is contained in:
Peter Maydell 2021-05-20 13:04:12 +01:00
commit be05216b01
14 changed files with 592 additions and 753 deletions

View File

@ -2146,8 +2146,16 @@ static inline void cpu_set_fpuc(CPUX86State *env, uint16_t fpuc)
void helper_lock_init(void); void helper_lock_init(void);
/* svm_helper.c */ /* 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, void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
uint64_t param, uintptr_t retaddr); uint64_t param, uintptr_t retaddr);
#endif
/* apic.c */ /* apic.c */
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,

View File

@ -42,9 +42,6 @@ DEF_HELPER_5(lcall_protected, void, env, int, tl, int, tl)
DEF_HELPER_2(iret_real, void, env, int) DEF_HELPER_2(iret_real, void, env, int)
DEF_HELPER_3(iret_protected, void, env, int, int) DEF_HELPER_3(iret_protected, void, env, int, int)
DEF_HELPER_3(lret_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) DEF_HELPER_1(clts, void, env)
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
@ -52,7 +49,6 @@ DEF_HELPER_FLAGS_3(set_dr, TCG_CALL_NO_WG, void, env, int, tl)
#endif /* !CONFIG_USER_ONLY */ #endif /* !CONFIG_USER_ONLY */
DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int) 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_1(sysenter, void, env)
DEF_HELPER_2(sysexit, void, env, int) DEF_HELPER_2(sysexit, void, env, int)
@ -60,14 +56,11 @@ DEF_HELPER_2(sysexit, void, env, int)
DEF_HELPER_2(syscall, void, env, int) DEF_HELPER_2(syscall, void, env, int)
DEF_HELPER_2(sysret, void, env, int) DEF_HELPER_2(sysret, void, env, int)
#endif #endif
DEF_HELPER_2(hlt, void, env, int) DEF_HELPER_FLAGS_2(pause, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_2(monitor, void, env, tl) DEF_HELPER_FLAGS_1(debug, TCG_CALL_NO_WG, noreturn, env)
DEF_HELPER_2(mwait, void, env, int)
DEF_HELPER_2(pause, void, env, int)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_1(reset_rf, void, env) DEF_HELPER_1(reset_rf, void, env)
DEF_HELPER_3(raise_interrupt, void, env, int, int) DEF_HELPER_FLAGS_3(raise_interrupt, TCG_CALL_NO_WG, noreturn, env, int, int)
DEF_HELPER_2(raise_exception, void, env, int) DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, int)
DEF_HELPER_1(cli, void, env) DEF_HELPER_1(cli, void, env)
DEF_HELPER_1(sti, void, env) DEF_HELPER_1(sti, void, env)
DEF_HELPER_1(clac, void, env) DEF_HELPER_1(clac, void, env)
@ -86,30 +79,23 @@ DEF_HELPER_2(cmpxchg8b, void, env, tl)
DEF_HELPER_2(cmpxchg16b_unlocked, void, env, tl) DEF_HELPER_2(cmpxchg16b_unlocked, void, env, tl)
DEF_HELPER_2(cmpxchg16b, void, env, tl) DEF_HELPER_2(cmpxchg16b, void, env, tl)
#endif #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(rechecking_single_step, void, env)
DEF_HELPER_1(cpuid, void, env) DEF_HELPER_1(cpuid, void, env)
DEF_HELPER_1(rdtsc, void, env) DEF_HELPER_1(rdtsc, void, env)
DEF_HELPER_1(rdtscp, void, env) DEF_HELPER_1(rdtscp, void, env)
DEF_HELPER_1(rdpmc, void, env) DEF_HELPER_FLAGS_1(rdpmc, TCG_CALL_NO_WG, noreturn, env)
DEF_HELPER_1(rdmsr, void, env)
DEF_HELPER_1(wrmsr, void, env)
DEF_HELPER_2(check_iob, void, env, i32) #ifndef CONFIG_USER_ONLY
DEF_HELPER_2(check_iow, void, env, i32)
DEF_HELPER_2(check_iol, void, env, i32)
DEF_HELPER_3(outb, void, env, i32, i32) DEF_HELPER_3(outb, void, env, i32, i32)
DEF_HELPER_2(inb, tl, env, i32) DEF_HELPER_2(inb, tl, env, i32)
DEF_HELPER_3(outw, void, env, i32, i32) DEF_HELPER_3(outw, void, env, i32, i32)
DEF_HELPER_2(inw, tl, env, i32) DEF_HELPER_2(inw, tl, env, i32)
DEF_HELPER_3(outl, void, env, i32, i32) DEF_HELPER_3(outl, void, env, i32, i32)
DEF_HELPER_2(inl, tl, env, i32) DEF_HELPER_2(inl, tl, env, i32)
DEF_HELPER_FLAGS_3(check_io, TCG_CALL_NO_WG, void, env, i32, i32)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_FLAGS_4(bpt_io, TCG_CALL_NO_WG, void, env, i32, i32, tl) DEF_HELPER_FLAGS_4(bpt_io, TCG_CALL_NO_WG, void, env, i32, i32, tl)
#endif /* !CONFIG_USER_ONLY */ DEF_HELPER_2(svm_check_intercept, void, env, i32)
DEF_HELPER_3(svm_check_intercept_param, void, env, i32, i64)
DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32) DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32)
DEF_HELPER_3(vmrun, void, env, int, int) DEF_HELPER_3(vmrun, void, env, int, int)
DEF_HELPER_1(vmmcall, void, env) DEF_HELPER_1(vmmcall, void, env)
@ -117,8 +103,15 @@ DEF_HELPER_2(vmload, void, env, int)
DEF_HELPER_2(vmsave, void, env, int) DEF_HELPER_2(vmsave, void, env, int)
DEF_HELPER_1(stgi, void, env) DEF_HELPER_1(stgi, void, env)
DEF_HELPER_1(clgi, void, env) DEF_HELPER_1(clgi, void, env)
DEF_HELPER_1(skinit, void, env) DEF_HELPER_FLAGS_2(flush_page, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_2(invlpga, void, env, int) 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 */ /* x86 FPU */

View File

@ -22,7 +22,7 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "helper-tcg.h" #include "helper-tcg.h"
void helper_single_step(CPUX86State *env) void QEMU_NORETURN helper_single_step(CPUX86State *env)
{ {
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
check_hw_breakpoints(env, true); check_hw_breakpoints(env, true);

View File

@ -25,12 +25,13 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "helper-tcg.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); 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); raise_exception(env, exception_index);
} }
@ -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); raise_interrupt2(env, intno, is_int, error_code, next_eip_addend, 0);
} }
void raise_exception_err(CPUX86State *env, int exception_index, void QEMU_NORETURN raise_exception_err(CPUX86State *env, int exception_index,
int error_code) int error_code)
{ {
raise_interrupt2(env, exception_index, 0, error_code, 0, 0); raise_interrupt2(env, exception_index, 0, error_code, 0, 0);
} }
void raise_exception_err_ra(CPUX86State *env, int exception_index, void QEMU_NORETURN raise_exception_err_ra(CPUX86State *env, int exception_index,
int error_code, uintptr_t retaddr) int error_code, uintptr_t retaddr)
{ {
raise_interrupt2(env, exception_index, 0, error_code, 0, 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); 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); raise_interrupt2(env, exception_index, 0, 0, 0, retaddr);
} }

View File

@ -76,11 +76,14 @@ extern const uint8_t parity_table[256];
/* misc_helper.c */ /* misc_helper.c */
void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask); 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, void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code,
uint64_t exit_info_1, uintptr_t retaddr); uint64_t exit_info_1, uintptr_t retaddr);
void do_vmexit(CPUX86State *env); void do_vmexit(CPUX86State *env);
#endif
/* seg_helper.c */ /* seg_helper.c */
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);

View File

@ -60,22 +60,6 @@ void helper_cpuid(CPUX86State *env)
env->regs[R_EDX] = edx; 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) void helper_rdtsc(CPUX86State *env)
{ {
uint64_t val; uint64_t val;
@ -96,7 +80,7 @@ void helper_rdtscp(CPUX86State *env)
env->regs[R_ECX] = (uint32_t)(env->tsc_aux); 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 ) && if (((env->cr[4] & CR4_PCE_MASK) == 0 ) &&
((env->hflags & HF_CPL_MASK) != 0)) { ((env->hflags & HF_CPL_MASK) != 0)) {
@ -109,75 +93,24 @@ void helper_rdpmc(CPUX86State *env)
raise_exception_err(env, EXCP06_ILLOP, 0); 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. */ /* Just let another CPU run. */
cs->exception_index = EXCP_INTERRUPT; cs->exception_index = EXCP_INTERRUPT;
cpu_loop_exit(cs); cpu_loop_exit(cs);
} }
static void do_hlt(X86CPU *cpu) void QEMU_NORETURN helper_pause(CPUX86State *env, int next_eip_addend)
{ {
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)
{
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()); cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
env->eip += next_eip_addend; 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); CPUState *cs = env_cpu(env);

View File

@ -2416,46 +2416,3 @@ void helper_verw(CPUX86State *env, target_ulong selector1)
} }
CC_SRC = eflags | CC_Z; 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());
}

View File

@ -65,7 +65,6 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
{ {
target_ulong val; target_ulong val;
cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
switch (reg) { switch (reg) {
default: default:
val = env->cr[reg]; val = env->cr[reg];
@ -83,7 +82,6 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
{ {
cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
switch (reg) { switch (reg) {
case 0: case 0:
cpu_x86_update_cr0(env, t0); cpu_x86_update_cr0(env, t0);
@ -440,3 +438,53 @@ void helper_rdmsr(CPUX86State *env)
env->regs[R_EAX] = (uint32_t)(val); env->regs[R_EAX] = (uint32_t)(val);
env->regs[R_EDX] = (uint32_t)(val >> 32); env->regs[R_EDX] = (uint32_t)(val >> 32);
} }
void helper_flush_page(CPUX86State *env, target_ulong addr)
{
tlb_flush_page(env_cpu(env), addr);
}
static void QEMU_NORETURN do_hlt(CPUX86State *env)
{
CPUState *cs = 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 QEMU_NORETURN helper_hlt(CPUX86State *env, int next_eip_addend)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
env->eip += next_eip_addend;
do_hlt(env);
}
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 QEMU_NORETURN helper_mwait(CPUX86State *env, int next_eip_addend)
{
CPUState *cs = env_cpu(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(env);
} else {
do_hlt(env);
}
}

View File

@ -23,6 +23,7 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include "tcg/helper-tcg.h" #include "tcg/helper-tcg.h"
#include "../seg_helper.h"
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
void helper_syscall(CPUX86State *env, int next_eip_addend) void helper_syscall(CPUX86State *env, int next_eip_addend)
@ -123,3 +124,31 @@ void x86_cpu_do_interrupt(CPUState *cs)
env->old_exception = -1; 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);
}
}

View File

@ -412,31 +412,6 @@ void helper_clgi(CPUX86State *env)
env->hflags2 &= ~HF2_GIF_MASK; env->hflags2 &= ~HF2_GIF_MASK;
} }
void helper_skinit(CPUX86State *env)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_SKINIT, 0, GETPC());
/* XXX: not implemented */
raise_exception(env, EXCP06_ILLOP);
}
void helper_invlpga(CPUX86State *env, int aflag)
{
X86CPU *cpu = env_archcpu(env);
target_ulong addr;
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPGA, 0, GETPC());
if (aflag == 2) {
addr = env->regs[R_EAX];
} else {
addr = (uint32_t)env->regs[R_EAX];
}
/* XXX: could use the ASID to see if it is needed to do the
flush */
tlb_flush_page(CPU(cpu), addr);
}
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param, uintptr_t retaddr) uint64_t param, uintptr_t retaddr)
{ {
@ -513,10 +488,9 @@ void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
} }
} }
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type, void helper_svm_check_intercept(CPUX86State *env, uint32_t type)
uint64_t param)
{ {
cpu_svm_check_intercept_param(env, type, param, GETPC()); cpu_svm_check_intercept_param(env, type, 0, GETPC());
} }
void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param, void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,4 @@
i386_user_ss.add(when: ['CONFIG_TCG', 'CONFIG_USER_ONLY'], if_true: files( i386_user_ss.add(when: ['CONFIG_TCG', 'CONFIG_USER_ONLY'], if_true: files(
'excp_helper.c', 'excp_helper.c',
'misc_stubs.c',
'svm_stubs.c',
'seg_helper.c', 'seg_helper.c',
)) ))

View File

@ -1,75 +0,0 @@
/*
* x86 misc helpers
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/helper-proto.h"
void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
{
g_assert_not_reached();
}
target_ulong helper_inb(CPUX86State *env, uint32_t port)
{
g_assert_not_reached();
return 0;
}
void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
{
g_assert_not_reached();
}
target_ulong helper_inw(CPUX86State *env, uint32_t port)
{
g_assert_not_reached();
return 0;
}
void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
{
g_assert_not_reached();
}
target_ulong helper_inl(CPUX86State *env, uint32_t port)
{
g_assert_not_reached();
return 0;
}
target_ulong helper_read_crN(CPUX86State *env, int reg)
{
g_assert_not_reached();
}
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
{
g_assert_not_reached();
}
void helper_wrmsr(CPUX86State *env)
{
g_assert_not_reached();
}
void helper_rdmsr(CPUX86State *env)
{
g_assert_not_reached();
}

View File

@ -1,76 +0,0 @@
/*
* x86 SVM helpers (user-mode)
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/helper-proto.h"
#include "tcg/helper-tcg.h"
void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
{
}
void helper_vmmcall(CPUX86State *env)
{
}
void helper_vmload(CPUX86State *env, int aflag)
{
}
void helper_vmsave(CPUX86State *env, int aflag)
{
}
void helper_stgi(CPUX86State *env)
{
}
void helper_clgi(CPUX86State *env)
{
}
void helper_skinit(CPUX86State *env)
{
}
void helper_invlpga(CPUX86State *env, int aflag)
{
}
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1,
uintptr_t retaddr)
{
assert(0);
}
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param)
{
}
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param, uintptr_t retaddr)
{
}
void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
uint32_t next_eip_addend)
{
}