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:
commit
be05216b01
@ -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,
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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());
|
|
||||||
}
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
@ -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',
|
||||||
))
|
))
|
||||||
|
@ -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();
|
|
||||||
}
|
|
@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user