Commit 023fe10d24acd124d0b7c5c5ac8edd41d6cc08f2
1 parent
f66723fa
fnop FPU exception support (aka FreeBSD FPU probe) - sysenter/sysexit support (u…
…ntested, not enabled in cpuid) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@869 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
87 additions
and
0 deletions
target-i386/exec.h
... | ... | @@ -167,6 +167,8 @@ void helper_divl_EAX_T0(uint32_t eip); |
167 | 167 | void helper_idivl_EAX_T0(uint32_t eip); |
168 | 168 | void helper_cmpxchg8b(void); |
169 | 169 | void helper_cpuid(void); |
170 | +void helper_sysenter(void); | |
171 | +void helper_sysexit(void); | |
170 | 172 | void helper_rdtsc(void); |
171 | 173 | void helper_rdmsr(void); |
172 | 174 | void helper_wrmsr(void); | ... | ... |
target-i386/helper.c
... | ... | @@ -1746,6 +1746,50 @@ void helper_lret_protected(int shift, int addend) |
1746 | 1746 | helper_ret_protected(shift, 0, addend); |
1747 | 1747 | } |
1748 | 1748 | |
1749 | +void helper_sysenter(void) | |
1750 | +{ | |
1751 | + if (env->sysenter_cs == 0) { | |
1752 | + raise_exception_err(EXCP0D_GPF, 0); | |
1753 | + } | |
1754 | + env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK); | |
1755 | + cpu_x86_set_cpl(env, 0); | |
1756 | + cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, | |
1757 | + NULL, 0xffffffff, | |
1758 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1759 | + DESC_S_MASK | | |
1760 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
1761 | + cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, | |
1762 | + NULL, 0xffffffff, | |
1763 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1764 | + DESC_S_MASK | | |
1765 | + DESC_W_MASK | DESC_A_MASK); | |
1766 | + ESP = env->sysenter_esp; | |
1767 | + EIP = env->sysenter_eip; | |
1768 | +} | |
1769 | + | |
1770 | +void helper_sysexit(void) | |
1771 | +{ | |
1772 | + int cpl; | |
1773 | + | |
1774 | + cpl = env->hflags & HF_CPL_MASK; | |
1775 | + if (env->sysenter_cs == 0 || cpl != 0) { | |
1776 | + raise_exception_err(EXCP0D_GPF, 0); | |
1777 | + } | |
1778 | + cpu_x86_set_cpl(env, 3); | |
1779 | + cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, | |
1780 | + NULL, 0xffffffff, | |
1781 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1782 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
1783 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
1784 | + cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, | |
1785 | + NULL, 0xffffffff, | |
1786 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1787 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
1788 | + DESC_W_MASK | DESC_A_MASK); | |
1789 | + ESP = ECX; | |
1790 | + EIP = EDX; | |
1791 | +} | |
1792 | + | |
1749 | 1793 | void helper_movl_crN_T0(int reg) |
1750 | 1794 | { |
1751 | 1795 | switch(reg) { | ... | ... |
target-i386/op.c
... | ... | @@ -700,6 +700,16 @@ void OPPROTO op_cpuid(void) |
700 | 700 | helper_cpuid(); |
701 | 701 | } |
702 | 702 | |
703 | +void OPPROTO op_sysenter(void) | |
704 | +{ | |
705 | + helper_sysenter(); | |
706 | +} | |
707 | + | |
708 | +void OPPROTO op_sysexit(void) | |
709 | +{ | |
710 | + helper_sysexit(); | |
711 | +} | |
712 | + | |
703 | 713 | void OPPROTO op_rdmsr(void) |
704 | 714 | { |
705 | 715 | helper_rdmsr(); | ... | ... |
target-i386/translate.c
... | ... | @@ -2973,6 +2973,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2973 | 2973 | case 0x0a: /* grp d9/2 */ |
2974 | 2974 | switch(rm) { |
2975 | 2975 | case 0: /* fnop */ |
2976 | + /* check exceptions (FreeBSD FPU probe) */ | |
2977 | + if (s->cc_op != CC_OP_DYNAMIC) | |
2978 | + gen_op_set_cc_op(s->cc_op); | |
2979 | + gen_op_jmp_im(pc_start - s->cs_base); | |
2980 | + gen_op_fwait(); | |
2976 | 2981 | break; |
2977 | 2982 | default: |
2978 | 2983 | goto illegal_op; |
... | ... | @@ -3881,6 +3886,32 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3881 | 3886 | case 0x131: /* rdtsc */ |
3882 | 3887 | gen_op_rdtsc(); |
3883 | 3888 | break; |
3889 | + case 0x134: /* sysenter */ | |
3890 | + if (!s->pe) { | |
3891 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | |
3892 | + } else { | |
3893 | + if (s->cc_op != CC_OP_DYNAMIC) { | |
3894 | + gen_op_set_cc_op(s->cc_op); | |
3895 | + s->cc_op = CC_OP_DYNAMIC; | |
3896 | + } | |
3897 | + gen_op_jmp_im(pc_start - s->cs_base); | |
3898 | + gen_op_sysenter(); | |
3899 | + gen_eob(s); | |
3900 | + } | |
3901 | + break; | |
3902 | + case 0x135: /* sysexit */ | |
3903 | + if (!s->pe) { | |
3904 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | |
3905 | + } else { | |
3906 | + if (s->cc_op != CC_OP_DYNAMIC) { | |
3907 | + gen_op_set_cc_op(s->cc_op); | |
3908 | + s->cc_op = CC_OP_DYNAMIC; | |
3909 | + } | |
3910 | + gen_op_jmp_im(pc_start - s->cs_base); | |
3911 | + gen_op_sysexit(); | |
3912 | + gen_eob(s); | |
3913 | + } | |
3914 | + break; | |
3884 | 3915 | case 0x1a2: /* cpuid */ |
3885 | 3916 | gen_op_cpuid(); |
3886 | 3917 | break; | ... | ... |