mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
fnop FPU exception support (aka FreeBSD FPU probe) - sysenter/sysexit support (untested, not enabled in cpuid)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@869 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
f66723fab9
commit
023fe10d24
4 changed files with 87 additions and 0 deletions
|
@ -167,6 +167,8 @@ void helper_divl_EAX_T0(uint32_t eip);
|
|||
void helper_idivl_EAX_T0(uint32_t eip);
|
||||
void helper_cmpxchg8b(void);
|
||||
void helper_cpuid(void);
|
||||
void helper_sysenter(void);
|
||||
void helper_sysexit(void);
|
||||
void helper_rdtsc(void);
|
||||
void helper_rdmsr(void);
|
||||
void helper_wrmsr(void);
|
||||
|
|
|
@ -1746,6 +1746,50 @@ void helper_lret_protected(int shift, int addend)
|
|||
helper_ret_protected(shift, 0, addend);
|
||||
}
|
||||
|
||||
void helper_sysenter(void)
|
||||
{
|
||||
if (env->sysenter_cs == 0) {
|
||||
raise_exception_err(EXCP0D_GPF, 0);
|
||||
}
|
||||
env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
|
||||
cpu_x86_set_cpl(env, 0);
|
||||
cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
|
||||
NULL, 0xffffffff,
|
||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
|
||||
DESC_S_MASK |
|
||||
DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
|
||||
NULL, 0xffffffff,
|
||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
|
||||
DESC_S_MASK |
|
||||
DESC_W_MASK | DESC_A_MASK);
|
||||
ESP = env->sysenter_esp;
|
||||
EIP = env->sysenter_eip;
|
||||
}
|
||||
|
||||
void helper_sysexit(void)
|
||||
{
|
||||
int cpl;
|
||||
|
||||
cpl = env->hflags & HF_CPL_MASK;
|
||||
if (env->sysenter_cs == 0 || cpl != 0) {
|
||||
raise_exception_err(EXCP0D_GPF, 0);
|
||||
}
|
||||
cpu_x86_set_cpl(env, 3);
|
||||
cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
|
||||
NULL, 0xffffffff,
|
||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
|
||||
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
|
||||
DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
|
||||
cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
|
||||
NULL, 0xffffffff,
|
||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
|
||||
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
|
||||
DESC_W_MASK | DESC_A_MASK);
|
||||
ESP = ECX;
|
||||
EIP = EDX;
|
||||
}
|
||||
|
||||
void helper_movl_crN_T0(int reg)
|
||||
{
|
||||
switch(reg) {
|
||||
|
|
|
@ -700,6 +700,16 @@ void OPPROTO op_cpuid(void)
|
|||
helper_cpuid();
|
||||
}
|
||||
|
||||
void OPPROTO op_sysenter(void)
|
||||
{
|
||||
helper_sysenter();
|
||||
}
|
||||
|
||||
void OPPROTO op_sysexit(void)
|
||||
{
|
||||
helper_sysexit();
|
||||
}
|
||||
|
||||
void OPPROTO op_rdmsr(void)
|
||||
{
|
||||
helper_rdmsr();
|
||||
|
|
|
@ -2973,6 +2973,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||
case 0x0a: /* grp d9/2 */
|
||||
switch(rm) {
|
||||
case 0: /* fnop */
|
||||
/* check exceptions (FreeBSD FPU probe) */
|
||||
if (s->cc_op != CC_OP_DYNAMIC)
|
||||
gen_op_set_cc_op(s->cc_op);
|
||||
gen_op_jmp_im(pc_start - s->cs_base);
|
||||
gen_op_fwait();
|
||||
break;
|
||||
default:
|
||||
goto illegal_op;
|
||||
|
@ -3881,6 +3886,32 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||
case 0x131: /* rdtsc */
|
||||
gen_op_rdtsc();
|
||||
break;
|
||||
case 0x134: /* sysenter */
|
||||
if (!s->pe) {
|
||||
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
||||
} else {
|
||||
if (s->cc_op != CC_OP_DYNAMIC) {
|
||||
gen_op_set_cc_op(s->cc_op);
|
||||
s->cc_op = CC_OP_DYNAMIC;
|
||||
}
|
||||
gen_op_jmp_im(pc_start - s->cs_base);
|
||||
gen_op_sysenter();
|
||||
gen_eob(s);
|
||||
}
|
||||
break;
|
||||
case 0x135: /* sysexit */
|
||||
if (!s->pe) {
|
||||
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
||||
} else {
|
||||
if (s->cc_op != CC_OP_DYNAMIC) {
|
||||
gen_op_set_cc_op(s->cc_op);
|
||||
s->cc_op = CC_OP_DYNAMIC;
|
||||
}
|
||||
gen_op_jmp_im(pc_start - s->cs_base);
|
||||
gen_op_sysexit();
|
||||
gen_eob(s);
|
||||
}
|
||||
break;
|
||||
case 0x1a2: /* cpuid */
|
||||
gen_op_cpuid();
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue