- Timestamp:
- Jul 24, 2013 5:21:12 PM (12 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
r47350 r47379 2723 2723 2724 2724 /** 2725 * Implements SYSCALL (AMD and Intel64). 2726 * 2727 * @param enmEffOpSize The effective operand size. 2728 */ 2729 IEM_CIMPL_DEF_0(iemCImpl_syscall) 2730 { 2731 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 2732 2733 /* 2734 * Check preconditions. 2735 * 2736 * Note that CPUs described in the documentation may load a few odd values 2737 * into CS and SS than we allow here. This has yet to be checked on real 2738 * hardware. 2739 */ 2740 if (!(pCtx->msrEFER & MSR_K6_EFER_SCE)) 2741 { 2742 Log(("syscall: Not enabled in EFER -> #UD\n")); 2743 return iemRaiseUndefinedOpcode(pIemCpu); 2744 } 2745 if (!(pCtx->cr0 & X86_CR0_PE)) 2746 { 2747 Log(("syscall: Protected mode is required -> #GP(0)\n")); 2748 return iemRaiseGeneralProtectionFault0(pIemCpu); 2749 } 2750 if (IEM_IS_GUEST_CPU_INTEL(pIemCpu) && !CPUMIsGuestInLongModeEx(pCtx)) 2751 { 2752 Log(("syscall: Only available in long mode on intel -> #UD\n")); 2753 return iemRaiseUndefinedOpcode(pIemCpu); 2754 } 2755 2756 /** @todo verify RPL ignoring and CS=0xfff8 (i.e. SS == 0). */ 2757 /** @todo what about LDT selectors? Shouldn't matter, really. */ 2758 uint16_t uNewCs = (pCtx->msrSTAR >> MSR_K6_STAR_SYSCALL_CS_SS_SHIFT) & X86_SEL_MASK_OFF_RPL; 2759 uint16_t uNewSs = uNewCs + 8; 2760 if (uNewCs == 0 || uNewSs == 0) 2761 { 2762 Log(("syscall: msrSTAR.CS = 0 or SS = 0 -> #GP(0)\n")); 2763 return iemRaiseGeneralProtectionFault0(pIemCpu); 2764 } 2765 2766 /* Long mode and legacy mode differs. */ 2767 if (CPUMIsGuestInLongModeEx(pCtx)) 2768 { 2769 uint64_t uNewRip = pIemCpu->enmCpuMode == IEMMODE_64BIT ? pCtx->msrLSTAR : pCtx-> msrCSTAR; 2770 2771 /* This test isn't in the docs, but I'm not trusting the guys writing 2772 the MSRs to have validated the values as canonical like they should. */ 2773 if (!IEM_IS_CANONICAL(uNewRip)) 2774 { 2775 Log(("syscall: Only available in long mode on intel -> #UD\n")); 2776 return iemRaiseUndefinedOpcode(pIemCpu); 2777 } 2778 2779 /* 2780 * Commit it. 2781 */ 2782 Log(("syscall: %04x:%016RX64 [efl=%#llx] -> %04x:%016RX64\n", pCtx->cs, pCtx->rip, pCtx->rflags.u, uNewCs, uNewRip)); 2783 pCtx->rcx = pCtx->rip + cbInstr; 2784 pCtx->rip = uNewRip; 2785 2786 pCtx->rflags.u &= ~X86_EFL_RF; 2787 pCtx->r11 = pCtx->rflags.u; 2788 pCtx->rflags.u &= ~pCtx->msrSFMASK; 2789 pCtx->rflags.u |= X86_EFL_1; 2790 2791 pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_L | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC; 2792 pCtx->ss.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_L | X86DESCATTR_DT | X86_SEL_TYPE_RW_ACC; 2793 } 2794 else 2795 { 2796 /* 2797 * Commit it. 2798 */ 2799 Log(("syscall: %04x:%08RX32 [efl=%#x] -> %04x:%08RX32\n", 2800 pCtx->cs, pCtx->eip, pCtx->eflags.u, uNewCs, (uint32_t)(pCtx->msrSTAR & MSR_K6_STAR_SYSCALL_EIP_MASK))); 2801 pCtx->rcx = pCtx->eip + cbInstr; 2802 pCtx->rip = pCtx->msrSTAR & MSR_K6_STAR_SYSCALL_EIP_MASK; 2803 pCtx->rflags.u &= ~(X86_EFL_VM | X86_EFL_IF | X86_EFL_RF); 2804 2805 pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC; 2806 pCtx->ss.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_RW_ACC; 2807 } 2808 pCtx->cs.Sel = uNewCs; 2809 pCtx->cs.ValidSel = uNewCs; 2810 pCtx->cs.u64Base = 0; 2811 pCtx->cs.u32Limit = UINT32_MAX; 2812 pCtx->cs.fFlags = CPUMSELREG_FLAGS_VALID; 2813 2814 pCtx->ss.Sel = uNewSs; 2815 pCtx->ss.ValidSel = uNewSs; 2816 pCtx->ss.u64Base = 0; 2817 pCtx->ss.u32Limit = UINT32_MAX; 2818 pCtx->ss.fFlags = CPUMSELREG_FLAGS_VALID; 2819 2820 return VINF_SUCCESS; 2821 } 2822 2823 2824 /** 2825 * Implements SYSRET (AMD and Intel64). 2826 */ 2827 IEM_CIMPL_DEF_0(iemCImpl_sysret) 2828 2829 { 2830 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 2831 2832 /* 2833 * Check preconditions. 2834 * 2835 * Note that CPUs described in the documentation may load a few odd values 2836 * into CS and SS than we allow here. This has yet to be checked on real 2837 * hardware. 2838 */ 2839 if (!(pCtx->msrEFER & MSR_K6_EFER_SCE)) 2840 { 2841 Log(("sysret: Not enabled in EFER -> #UD\n")); 2842 return iemRaiseUndefinedOpcode(pIemCpu); 2843 } 2844 if (IEM_IS_GUEST_CPU_INTEL(pIemCpu) && !CPUMIsGuestInLongModeEx(pCtx)) 2845 { 2846 Log(("sysret: Only available in long mode on intel -> #UD\n")); 2847 return iemRaiseUndefinedOpcode(pIemCpu); 2848 } 2849 if (!(pCtx->cr0 & X86_CR0_PE)) 2850 { 2851 Log(("sysret: Protected mode is required -> #GP(0)\n")); 2852 return iemRaiseGeneralProtectionFault0(pIemCpu); 2853 } 2854 if (pIemCpu->uCpl != 0) 2855 { 2856 Log(("sysret: CPL must be 0 not %u -> #GP(0)\n", pIemCpu->uCpl)); 2857 return iemRaiseGeneralProtectionFault0(pIemCpu); 2858 } 2859 2860 /** @todo Does SYSRET verify CS != 0 and SS != 0? Neither is valid in ring-3. */ 2861 uint16_t uNewCs = (pCtx->msrSTAR >> MSR_K6_STAR_SYSRET_CS_SS_SHIFT) & X86_SEL_MASK_OFF_RPL; 2862 uint16_t uNewSs = uNewCs + 8; 2863 if (pIemCpu->enmEffOpSize == IEMMODE_64BIT) 2864 uNewCs += 16; 2865 if (uNewCs == 0 || uNewSs == 0) 2866 { 2867 Log(("sysret: msrSTAR.CS = 0 or SS = 0 -> #GP(0)\n")); 2868 return iemRaiseGeneralProtectionFault0(pIemCpu); 2869 } 2870 2871 /* 2872 * Commit it. 2873 */ 2874 if (CPUMIsGuestInLongModeEx(pCtx)) 2875 { 2876 if (pIemCpu->enmEffOpSize == IEMMODE_64BIT) 2877 { 2878 Log(("sysret: %04x:%016RX64 [efl=%#llx] -> %04x:%016RX64 [r11=%#llx]\n", 2879 pCtx->cs, pCtx->rip, pCtx->rflags.u, uNewCs, pCtx->rcx, pCtx->r11)); 2880 /* Note! We disregard intel manual regarding the RCX cananonical 2881 check, ask intel+xen why AMD doesn't do it. */ 2882 pCtx->rip = pCtx->rcx; 2883 pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_L | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC 2884 | (3 << X86DESCATTR_DPL_SHIFT); 2885 } 2886 else 2887 { 2888 Log(("sysret: %04x:%016RX64 [efl=%#llx] -> %04x:%08RX32 [r11=%#llx]\n", 2889 pCtx->cs, pCtx->rip, pCtx->rflags.u, uNewCs, pCtx->ecx, pCtx->r11)); 2890 pCtx->rip = pCtx->ecx; 2891 pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC 2892 | (3 << X86DESCATTR_DPL_SHIFT); 2893 } 2894 /** @todo testcase: See what kind of flags we can make SYSRET restore and 2895 * what it really ignores. RF and VM are hinted at being zero, by AMD. */ 2896 pCtx->rflags.u = pCtx->r11 & (X86_EFL_POPF_BITS | X86_EFL_VIF | X86_EFL_VIP); 2897 pCtx->rflags.u |= X86_EFL_1; 2898 } 2899 else 2900 { 2901 Log(("sysret: %04x:%08RX32 [efl=%#x] -> %04x:%08RX32\n", pCtx->cs, pCtx->eip, pCtx->eflags.u, uNewCs, pCtx->ecx)); 2902 pCtx->rip = pCtx->rcx; 2903 pCtx->rflags.u |= X86_EFL_IF; 2904 pCtx->cs.Attr.u = X86DESCATTR_P | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_DT | X86_SEL_TYPE_ER_ACC 2905 | (3 << X86DESCATTR_DPL_SHIFT); 2906 } 2907 pCtx->cs.Sel = uNewCs | 3; 2908 pCtx->cs.ValidSel = uNewCs | 3; 2909 pCtx->cs.u64Base = 0; 2910 pCtx->cs.u32Limit = UINT32_MAX; 2911 pCtx->cs.fFlags = CPUMSELREG_FLAGS_VALID; 2912 2913 pCtx->ss.Sel = uNewSs | 3; 2914 pCtx->ss.ValidSel = uNewSs | 3; 2915 pCtx->ss.fFlags = CPUMSELREG_FLAGS_VALID; 2916 /* The SS hidden bits remains unchanged says AMD. To that I say "Yeah, right!". */ 2917 pCtx->ss.Attr.u |= (3 << X86DESCATTR_DPL_SHIFT); 2918 /** @todo Testcase: verify that SS.u1Long and SS.u1DefBig are left unchanged 2919 * on sysret. */ 2920 2921 return VINF_SUCCESS; 2922 } 2923 2924 2925 /** 2725 2926 * Common worker for 'pop SReg', 'mov SReg, GReg' and 'lXs GReg, reg/mem'. 2726 2927 * … … 3648 3849 if ( (uOldCrX & X86_CR4_PAE) 3649 3850 && !(uNewCrX & X86_CR4_PAE) 3650 && (pCtx->msrEFER & MSR_K6_EFER_LMA) )3851 && CPUMIsGuestInLongModeEx(pCtx) ) 3651 3852 { 3652 3853 Log(("Trying to set clear CR4.PAE while long mode is active\n")); -
trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
r47350 r47379 1101 1101 /** Opcode 0x0f 0x03. */ 1102 1102 FNIEMOP_STUB(iemOp_lsl_Gv_Ew); 1103 1104 1103 1105 /** Opcode 0x0f 0x04. */ 1104 FNIEMOP_STUB(iemOp_syscall); 1106 FNIEMOP_DEF(iemOp_syscall) 1107 { 1108 IEMOP_MNEMONIC("syscall"); 1109 IEMOP_HLP_NO_LOCK_PREFIX(); 1110 return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_syscall); 1111 } 1105 1112 1106 1113 … … 1115 1122 1116 1123 /** Opcode 0x0f 0x06. */ 1117 FNIEMOP_STUB(iemOp_sysret); 1124 FNIEMOP_DEF(iemOp_sysret) 1125 { 1126 IEMOP_MNEMONIC("sysret"); 1127 IEMOP_HLP_NO_LOCK_PREFIX(); 1128 return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_sysret); 1129 } 1130 1131 1118 1132 /** Opcode 0x0f 0x08. */ 1119 1133 FNIEMOP_STUB(iemOp_invd);
Note:
See TracChangeset
for help on using the changeset viewer.