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; | ... | ... |