mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
converted more helpers to TCG - fixed some SVM issues
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4459 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
+11
-2
@@ -3,12 +3,13 @@ Correctness issues:
|
||||
- rework eflags optimization (will be a consequence of TCG port)
|
||||
- SVM: rework the implementation: simplify code, move most intercept
|
||||
tests as dynamic, correct segment access, verify exception safety,
|
||||
remove most of the added CPU state.
|
||||
cpu save/restore, SMM save/restore.
|
||||
- arpl eflags computation is invalid
|
||||
- x86_64: fxsave/fxrestore intel/amd differences
|
||||
- x86_64: lcall/ljmp intel/amd differences ?
|
||||
- x86_64: cmpxchgl intel/amd differences ?
|
||||
- x86_64: cmovl bug intel/amd differences ?
|
||||
- x86_64: cmovl intel/amd differences ?
|
||||
- cmpxchg16b + cmpxchg8b cpuid test
|
||||
- x86: monitor invalid
|
||||
- better code fetch (different exception handling + CS.limit support)
|
||||
- user/kernel PUSHL/POPL in helper.c
|
||||
@@ -19,10 +20,18 @@ Correctness issues:
|
||||
- full support of segment limit/rights
|
||||
- full x87 exception support
|
||||
- improve x87 bit exactness (use bochs code ?)
|
||||
- DRx register support
|
||||
- CR0.AC emulation
|
||||
- SSE alignment checks
|
||||
- fix SSE min/max with nans
|
||||
|
||||
Optimizations/Features:
|
||||
|
||||
- finish TCG port
|
||||
- add SVM nested paging support
|
||||
- add VMX support
|
||||
- add AVX support
|
||||
- add SSE5 support
|
||||
- evaluate x87 stack pointer statically
|
||||
- find a way to avoid translating several time the same TB if CR0.TS
|
||||
is set or not.
|
||||
|
||||
+4
-22
@@ -105,16 +105,6 @@ typedef struct CCTable {
|
||||
|
||||
extern CCTable cc_table[];
|
||||
|
||||
void helper_load_seg(int seg_reg, int selector);
|
||||
void helper_ljmp_protected_T0_T1(int next_eip);
|
||||
void helper_lcall_real_T0_T1(int shift, int next_eip);
|
||||
void helper_lcall_protected_T0_T1(int shift, int next_eip);
|
||||
void helper_iret_real(int shift);
|
||||
void helper_iret_protected(int shift, int next_eip);
|
||||
void helper_lret_protected(int shift, int addend);
|
||||
void helper_movl_crN_T0(int reg);
|
||||
void helper_movl_drN_T0(int reg);
|
||||
void helper_invlpg(target_ulong addr);
|
||||
void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
|
||||
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
|
||||
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
|
||||
@@ -141,17 +131,10 @@ void OPPROTO op_movl_T0_eflags(void);
|
||||
|
||||
#include "helper.h"
|
||||
|
||||
void helper_mulq_EAX_T0(void);
|
||||
void helper_imulq_EAX_T0(void);
|
||||
void helper_imulq_T0_T1(void);
|
||||
void helper_cmpxchg8b(void);
|
||||
|
||||
void check_iob_T0(void);
|
||||
void check_iow_T0(void);
|
||||
void check_iol_T0(void);
|
||||
void check_iob_DX(void);
|
||||
void check_iow_DX(void);
|
||||
void check_iol_DX(void);
|
||||
static inline void svm_check_intercept(uint32_t type)
|
||||
{
|
||||
helper_svm_check_intercept_param(type, 0);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
@@ -363,7 +346,6 @@ extern const CPU86_LDouble f15rk[7];
|
||||
void fpu_raise_exception(void);
|
||||
void restore_native_fp_state(CPUState *env);
|
||||
void save_native_fp_state(CPUState *env);
|
||||
void vmexit(uint64_t exit_code, uint64_t exit_info_1);
|
||||
|
||||
extern const uint8_t parity_table[256];
|
||||
extern const uint8_t rclw_table[32];
|
||||
|
||||
+180
-131
File diff suppressed because it is too large
Load Diff
+39
-11
@@ -1,5 +1,7 @@
|
||||
#define TCG_HELPER_PROTO
|
||||
|
||||
void helper_lock(void);
|
||||
void helper_unlock(void);
|
||||
void helper_divb_AL(target_ulong t0);
|
||||
void helper_idivb_AL(target_ulong t0);
|
||||
void helper_divw_AX(target_ulong t0);
|
||||
@@ -7,6 +9,9 @@ void helper_idivw_AX(target_ulong t0);
|
||||
void helper_divl_EAX(target_ulong t0);
|
||||
void helper_idivl_EAX(target_ulong t0);
|
||||
#ifdef TARGET_X86_64
|
||||
void helper_mulq_EAX_T0(target_ulong t0);
|
||||
void helper_imulq_EAX_T0(target_ulong t0);
|
||||
target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1);
|
||||
void helper_divq_EAX(target_ulong t0);
|
||||
void helper_idivq_EAX(target_ulong t0);
|
||||
#endif
|
||||
@@ -18,26 +23,34 @@ void helper_aas(void);
|
||||
void helper_daa(void);
|
||||
void helper_das(void);
|
||||
|
||||
void helper_lsl(uint32_t selector);
|
||||
void helper_lar(uint32_t selector);
|
||||
uint32_t helper_lsl(uint32_t selector);
|
||||
uint32_t helper_lar(uint32_t selector);
|
||||
void helper_verr(uint32_t selector);
|
||||
void helper_verw(uint32_t selector);
|
||||
void helper_lldt(int selector);
|
||||
void helper_ltr(int selector);
|
||||
void helper_load_seg(int seg_reg, int selector);
|
||||
void helper_ljmp_protected_T0_T1(int next_eip);
|
||||
void helper_lcall_real_T0_T1(int shift, int next_eip);
|
||||
void helper_lcall_protected_T0_T1(int shift, int next_eip);
|
||||
void helper_ljmp_protected(int new_cs, target_ulong new_eip,
|
||||
int next_eip_addend);
|
||||
void helper_lcall_real(int new_cs, target_ulong new_eip1,
|
||||
int shift, int next_eip);
|
||||
void helper_lcall_protected(int new_cs, target_ulong new_eip,
|
||||
int shift, int next_eip_addend);
|
||||
void helper_iret_real(int shift);
|
||||
void helper_iret_protected(int shift, int next_eip);
|
||||
void helper_lret_protected(int shift, int addend);
|
||||
void helper_movl_crN_T0(int reg);
|
||||
void helper_movl_drN_T0(int reg);
|
||||
void helper_movl_crN_T0(int reg, target_ulong t0);
|
||||
void helper_lmsw(target_ulong t0);
|
||||
void helper_clts(void);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
target_ulong helper_movtl_T0_cr8(void);
|
||||
#endif
|
||||
void helper_movl_drN_T0(int reg, target_ulong t0);
|
||||
void helper_invlpg(target_ulong addr);
|
||||
|
||||
void helper_enter_level(int level, int data32);
|
||||
void helper_enter_level(int level, int data32, target_ulong t1);
|
||||
#ifdef TARGET_X86_64
|
||||
void helper_enter64_level(int level, int data64);
|
||||
void helper_enter64_level(int level, int data64, target_ulong t1);
|
||||
#endif
|
||||
void helper_sysenter(void);
|
||||
void helper_sysexit(void);
|
||||
@@ -55,9 +68,10 @@ void helper_cli(void);
|
||||
void helper_sti(void);
|
||||
void helper_set_inhibit_irq(void);
|
||||
void helper_reset_inhibit_irq(void);
|
||||
void helper_boundw(void);
|
||||
void helper_boundl(void);
|
||||
void helper_boundw(target_ulong a0, int v);
|
||||
void helper_boundl(target_ulong a0, int v);
|
||||
void helper_rsm(void);
|
||||
void helper_cmpxchg8b(target_ulong a0);
|
||||
void helper_single_step(void);
|
||||
void helper_cpuid(void);
|
||||
void helper_rdtsc(void);
|
||||
@@ -65,6 +79,20 @@ void helper_rdpmc(void);
|
||||
void helper_rdmsr(void);
|
||||
void helper_wrmsr(void);
|
||||
|
||||
void helper_check_iob(uint32_t t0);
|
||||
void helper_check_iow(uint32_t t0);
|
||||
void helper_check_iol(uint32_t t0);
|
||||
void helper_outb(uint32_t port, uint32_t data);
|
||||
target_ulong helper_inb(uint32_t port);
|
||||
void helper_outw(uint32_t port, uint32_t data);
|
||||
target_ulong helper_inw(uint32_t port);
|
||||
void helper_outl(uint32_t port, uint32_t data);
|
||||
target_ulong helper_inl(uint32_t port);
|
||||
|
||||
void helper_svm_check_intercept_param(uint32_t type, uint64_t param);
|
||||
void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1);
|
||||
void helper_svm_check_io(uint32_t port, uint32_t param,
|
||||
uint32_t next_eip_addend);
|
||||
void helper_vmrun(void);
|
||||
void helper_vmmcall(void);
|
||||
void helper_vmload(void);
|
||||
|
||||
+14
-127
@@ -276,17 +276,17 @@ void OPPROTO op_imull_T0_T1(void)
|
||||
#ifdef TARGET_X86_64
|
||||
void OPPROTO op_mulq_EAX_T0(void)
|
||||
{
|
||||
helper_mulq_EAX_T0();
|
||||
helper_mulq_EAX_T0(T0);
|
||||
}
|
||||
|
||||
void OPPROTO op_imulq_EAX_T0(void)
|
||||
{
|
||||
helper_imulq_EAX_T0();
|
||||
helper_imulq_EAX_T0(T0);
|
||||
}
|
||||
|
||||
void OPPROTO op_imulq_T0_T1(void)
|
||||
{
|
||||
helper_imulq_T0_T1();
|
||||
T0 = helper_imulq_T0_T1(T0, T1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -351,7 +351,7 @@ void OPPROTO op_into(void)
|
||||
|
||||
void OPPROTO op_cmpxchg8b(void)
|
||||
{
|
||||
helper_cmpxchg8b();
|
||||
helper_cmpxchg8b(A0);
|
||||
}
|
||||
|
||||
/* multiple size ops */
|
||||
@@ -522,12 +522,6 @@ void OPPROTO op_das(void)
|
||||
|
||||
/* segment handling */
|
||||
|
||||
/* never use it with R_CS */
|
||||
void OPPROTO op_movl_seg_T0(void)
|
||||
{
|
||||
helper_load_seg(PARAM1, T0);
|
||||
}
|
||||
|
||||
/* faster VM86 version */
|
||||
void OPPROTO op_movl_seg_T0_vm(void)
|
||||
{
|
||||
@@ -548,12 +542,20 @@ void OPPROTO op_movl_T0_seg(void)
|
||||
|
||||
void OPPROTO op_lsl(void)
|
||||
{
|
||||
helper_lsl(T0);
|
||||
uint32_t val;
|
||||
val = helper_lsl(T0);
|
||||
if (CC_SRC & CC_Z)
|
||||
T1 = val;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_lar(void)
|
||||
{
|
||||
helper_lar(T0);
|
||||
uint32_t val;
|
||||
val = helper_lar(T0);
|
||||
if (CC_SRC & CC_Z)
|
||||
T1 = val;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_verr(void)
|
||||
@@ -585,104 +587,6 @@ void OPPROTO op_arpl_update(void)
|
||||
CC_SRC = (eflags & ~CC_Z) | T1;
|
||||
}
|
||||
|
||||
/* T0: segment, T1:eip */
|
||||
void OPPROTO op_ljmp_protected_T0_T1(void)
|
||||
{
|
||||
helper_ljmp_protected_T0_T1(PARAM1);
|
||||
}
|
||||
|
||||
void OPPROTO op_lcall_real_T0_T1(void)
|
||||
{
|
||||
helper_lcall_real_T0_T1(PARAM1, PARAM2);
|
||||
}
|
||||
|
||||
void OPPROTO op_lcall_protected_T0_T1(void)
|
||||
{
|
||||
helper_lcall_protected_T0_T1(PARAM1, PARAM2);
|
||||
}
|
||||
|
||||
void OPPROTO op_iret_real(void)
|
||||
{
|
||||
helper_iret_real(PARAM1);
|
||||
}
|
||||
|
||||
void OPPROTO op_iret_protected(void)
|
||||
{
|
||||
helper_iret_protected(PARAM1, PARAM2);
|
||||
}
|
||||
|
||||
void OPPROTO op_lret_protected(void)
|
||||
{
|
||||
helper_lret_protected(PARAM1, PARAM2);
|
||||
}
|
||||
|
||||
/* CR registers access. */
|
||||
void OPPROTO op_movl_crN_T0(void)
|
||||
{
|
||||
helper_movl_crN_T0(PARAM1);
|
||||
}
|
||||
|
||||
/* These pseudo-opcodes check for SVM intercepts. */
|
||||
void OPPROTO op_svm_check_intercept(void)
|
||||
{
|
||||
A0 = PARAM1 & PARAM2;
|
||||
svm_check_intercept(PARAMQ1);
|
||||
}
|
||||
|
||||
void OPPROTO op_svm_check_intercept_param(void)
|
||||
{
|
||||
A0 = PARAM1 & PARAM2;
|
||||
svm_check_intercept_param(PARAMQ1, T1);
|
||||
}
|
||||
|
||||
void OPPROTO op_svm_vmexit(void)
|
||||
{
|
||||
A0 = PARAM1 & PARAM2;
|
||||
vmexit(PARAMQ1, T1);
|
||||
}
|
||||
|
||||
void OPPROTO op_geneflags(void)
|
||||
{
|
||||
CC_SRC = cc_table[CC_OP].compute_all();
|
||||
}
|
||||
|
||||
/* This pseudo-opcode checks for IO intercepts. */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void OPPROTO op_svm_check_intercept_io(void)
|
||||
{
|
||||
A0 = PARAM1 & PARAM2;
|
||||
/* PARAMQ1 = TYPE (0 = OUT, 1 = IN; 4 = STRING; 8 = REP)
|
||||
T0 = PORT
|
||||
T1 = next eip */
|
||||
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), T1);
|
||||
/* ASIZE does not appear on real hw */
|
||||
svm_check_intercept_param(SVM_EXIT_IOIO,
|
||||
(PARAMQ1 & ~SVM_IOIO_ASIZE_MASK) |
|
||||
((T0 & 0xffff) << 16));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void OPPROTO op_movtl_T0_cr8(void)
|
||||
{
|
||||
T0 = cpu_get_apic_tpr(env);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* DR registers access */
|
||||
void OPPROTO op_movl_drN_T0(void)
|
||||
{
|
||||
helper_movl_drN_T0(PARAM1);
|
||||
}
|
||||
|
||||
void OPPROTO op_lmsw_T0(void)
|
||||
{
|
||||
/* 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_movl_crN_T0(0);
|
||||
}
|
||||
|
||||
void OPPROTO op_movl_T0_env(void)
|
||||
{
|
||||
T0 = *(uint32_t *)((char *)env + PARAM1);
|
||||
@@ -718,12 +622,6 @@ void OPPROTO op_movtl_env_T1(void)
|
||||
*(target_ulong *)((char *)env + PARAM1) = T1;
|
||||
}
|
||||
|
||||
void OPPROTO op_clts(void)
|
||||
{
|
||||
env->cr[0] &= ~CR0_TS_MASK;
|
||||
env->hflags &= ~HF_TS_MASK;
|
||||
}
|
||||
|
||||
/* flags handling */
|
||||
|
||||
void OPPROTO op_jmp_label(void)
|
||||
@@ -1028,17 +926,6 @@ void OPPROTO op_fcomi_dummy(void)
|
||||
T0 = 0;
|
||||
}
|
||||
|
||||
/* threading support */
|
||||
void OPPROTO op_lock(void)
|
||||
{
|
||||
cpu_lock();
|
||||
}
|
||||
|
||||
void OPPROTO op_unlock(void)
|
||||
{
|
||||
cpu_unlock();
|
||||
}
|
||||
|
||||
/* SSE support */
|
||||
void OPPROTO op_com_dummy(void)
|
||||
{
|
||||
|
||||
@@ -471,12 +471,12 @@ void glue(helper_psadbw, SUFFIX) (Reg *d, Reg *s)
|
||||
#endif
|
||||
}
|
||||
|
||||
void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s)
|
||||
void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s, target_ulong a0)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < (8 << SHIFT); i++) {
|
||||
if (s->B(i) & 0x80)
|
||||
stb(A0 + i, d->B(i));
|
||||
stb(a0 + i, d->B(i));
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ void glue(helper_pmuludq, SUFFIX) (Reg *d, Reg *s);
|
||||
void glue(helper_pmaddwd, SUFFIX) (Reg *d, Reg *s);
|
||||
|
||||
void glue(helper_psadbw, SUFFIX) (Reg *d, Reg *s);
|
||||
void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s);
|
||||
void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s, target_ulong a0);
|
||||
void glue(helper_movl_mm_T0, SUFFIX) (Reg *d, uint32_t val);
|
||||
#ifdef TARGET_X86_64
|
||||
void glue(helper_movq_mm_T0, SUFFIX) (Reg *d, uint64_t val);
|
||||
|
||||
@@ -554,39 +554,6 @@ void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
|
||||
T0 = DF << SHIFT;
|
||||
}
|
||||
|
||||
/* port I/O */
|
||||
#if DATA_BITS <= 32
|
||||
void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
glue(cpu_out, SUFFIX)(env, T0, T1 & DATA_MASK);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
|
||||
{
|
||||
T1 = glue(cpu_in, SUFFIX)(env, T0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
|
||||
{
|
||||
T0 = glue(cpu_in, SUFFIX)(env, EDX & 0xffff);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
|
||||
{
|
||||
glue(cpu_out, SUFFIX)(env, EDX & 0xffff, T0);
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_check_io, SUFFIX), _T0)(void)
|
||||
{
|
||||
glue(glue(check_io, SUFFIX), _T0)();
|
||||
}
|
||||
|
||||
void OPPROTO glue(glue(op_check_io, SUFFIX), _DX)(void)
|
||||
{
|
||||
glue(glue(check_io, SUFFIX), _DX)();
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef DATA_BITS
|
||||
#undef SHIFT_MASK
|
||||
#undef SHIFT1_MASK
|
||||
|
||||
+1
-10
@@ -71,8 +71,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
|
||||
uint32_t int_vector;
|
||||
uint32_t int_state;
|
||||
uint8_t reserved_3[4];
|
||||
uint32_t exit_code;
|
||||
uint32_t exit_code_hi;
|
||||
uint64_t exit_code;
|
||||
uint64_t exit_info_1;
|
||||
uint64_t exit_info_2;
|
||||
uint32_t exit_int_info;
|
||||
@@ -323,14 +322,6 @@ struct __attribute__ ((__packed__)) vmcb {
|
||||
|
||||
/* function references */
|
||||
|
||||
void helper_stgi(void);
|
||||
void vmexit(uint64_t exit_code, uint64_t exit_info_1);
|
||||
int svm_check_intercept_param(uint32_t type, uint64_t param);
|
||||
static inline int svm_check_intercept(unsigned int type) {
|
||||
return svm_check_intercept_param(type, 0);
|
||||
}
|
||||
|
||||
|
||||
#define INTERCEPTED(mask) (env->intercept & mask)
|
||||
#define INTERCEPTEDw(var, mask) (env->intercept ## var & mask)
|
||||
#define INTERCEPTEDl(var, mask) (env->intercept ## var & mask)
|
||||
|
||||
+153
-147
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user