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,6 +167,8 @@ void helper_divl_EAX_T0(uint32_t eip); | ||
167 | void helper_idivl_EAX_T0(uint32_t eip); | 167 | void helper_idivl_EAX_T0(uint32_t eip); |
168 | void helper_cmpxchg8b(void); | 168 | void helper_cmpxchg8b(void); |
169 | void helper_cpuid(void); | 169 | void helper_cpuid(void); |
170 | +void helper_sysenter(void); | ||
171 | +void helper_sysexit(void); | ||
170 | void helper_rdtsc(void); | 172 | void helper_rdtsc(void); |
171 | void helper_rdmsr(void); | 173 | void helper_rdmsr(void); |
172 | void helper_wrmsr(void); | 174 | void helper_wrmsr(void); |
target-i386/helper.c
@@ -1746,6 +1746,50 @@ void helper_lret_protected(int shift, int addend) | @@ -1746,6 +1746,50 @@ void helper_lret_protected(int shift, int addend) | ||
1746 | helper_ret_protected(shift, 0, addend); | 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 | void helper_movl_crN_T0(int reg) | 1793 | void helper_movl_crN_T0(int reg) |
1750 | { | 1794 | { |
1751 | switch(reg) { | 1795 | switch(reg) { |
target-i386/op.c
@@ -700,6 +700,16 @@ void OPPROTO op_cpuid(void) | @@ -700,6 +700,16 @@ void OPPROTO op_cpuid(void) | ||
700 | helper_cpuid(); | 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 | void OPPROTO op_rdmsr(void) | 713 | void OPPROTO op_rdmsr(void) |
704 | { | 714 | { |
705 | helper_rdmsr(); | 715 | helper_rdmsr(); |
target-i386/translate.c
@@ -2973,6 +2973,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2973,6 +2973,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2973 | case 0x0a: /* grp d9/2 */ | 2973 | case 0x0a: /* grp d9/2 */ |
2974 | switch(rm) { | 2974 | switch(rm) { |
2975 | case 0: /* fnop */ | 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 | break; | 2981 | break; |
2977 | default: | 2982 | default: |
2978 | goto illegal_op; | 2983 | goto illegal_op; |
@@ -3881,6 +3886,32 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3881,6 +3886,32 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3881 | case 0x131: /* rdtsc */ | 3886 | case 0x131: /* rdtsc */ |
3882 | gen_op_rdtsc(); | 3887 | gen_op_rdtsc(); |
3883 | break; | 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 | case 0x1a2: /* cpuid */ | 3915 | case 0x1a2: /* cpuid */ |
3885 | gen_op_cpuid(); | 3916 | gen_op_cpuid(); |
3886 | break; | 3917 | break; |