- Timestamp:
- Mar 21, 2023 11:03:33 AM (19 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin-armv8.cpp
r99070 r99078 50 50 #include "dtrace/VBoxVMM.h" 51 51 52 #include <iprt/armv8.h> 52 53 #include <iprt/asm.h> 53 54 #include <iprt/ldr.h> … … 214 215 215 216 /** 217 * Returns a human readable string of the given exception class. 218 * 219 * @returns Pointer to the string matching the given EC. 220 * @param u32Ec The exception class to return the string for. 221 */ 222 static const char *nemR3DarwinEsrEl2EcStringify(uint32_t u32Ec) 223 { 224 switch (u32Ec) 225 { 226 #define ARMV8_EC_CASE(a_Ec) case a_Ec: return #a_Ec 227 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_UNKNOWN); 228 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_TRAPPED_WFX); 229 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_MCR_MRC_COPROC_15); 230 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_MCRR_MRRC_COPROC15); 231 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_MCR_MRC_COPROC_14); 232 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_LDC_STC); 233 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_SME_SVE_NEON); 234 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_VMRS); 235 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_PA_INSN); 236 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_LS64_EXCEPTION); 237 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_MRRC_COPROC14); 238 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_BTI_BRANCH_TARGET_EXCEPTION); 239 ARMV8_EC_CASE(ARMV8_ESR_EL2_ILLEGAL_EXECUTION_STATE); 240 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_SVC_INSN); 241 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_HVC_INSN); 242 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_SMC_INSN); 243 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH64_SVC_INSN); 244 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH64_HVC_INSN); 245 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH64_SMC_INSN); 246 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH64_TRAPPED_SYS_INSN); 247 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_SVE_TRAPPED); 248 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_PAUTH_NV_TRAPPED_ERET_ERETAA_ERETAB); 249 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_TME_TSTART_INSN_EXCEPTION); 250 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_FPAC_PA_INSN_FAILURE_EXCEPTION); 251 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_SME_TRAPPED_SME_ACCESS); 252 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_RME_GRANULE_PROT_CHECK_EXCEPTION); 253 ARMV8_EC_CASE(ARMV8_ESR_EL2_INSN_ABORT_FROM_LOWER_EL); 254 ARMV8_EC_CASE(ARMV8_ESR_EL2_INSN_ABORT_FROM_EL2); 255 ARMV8_EC_CASE(ARMV8_ESR_EL2_PC_ALIGNMENT_EXCEPTION); 256 ARMV8_EC_CASE(ARMV8_ESR_EL2_DATA_ABORT_FROM_LOWER_EL); 257 ARMV8_EC_CASE(ARMV8_ESR_EL2_DATA_ABORT_FROM_EL2); 258 ARMV8_EC_CASE(ARMV8_ESR_EL2_SP_ALIGNMENT_EXCEPTION); 259 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_MOPS_EXCEPTION); 260 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_TRAPPED_FP_EXCEPTION); 261 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH64_TRAPPED_FP_EXCEPTION); 262 ARMV8_EC_CASE(ARMV8_ESR_EL2_SERROR_INTERRUPT); 263 ARMV8_EC_CASE(ARMV8_ESR_EL2_BKPT_EXCEPTION_FROM_LOWER_EL); 264 ARMV8_EC_CASE(ARMV8_ESR_EL2_BKPT_EXCEPTION_FROM_EL2); 265 ARMV8_EC_CASE(ARMV8_ESR_EL2_SS_EXCEPTION_FROM_LOWER_EL); 266 ARMV8_EC_CASE(ARMV8_ESR_EL2_SS_EXCEPTION_FROM_EL2); 267 ARMV8_EC_CASE(ARMV8_ESR_EL2_WATCHPOINT_EXCEPTION_FROM_LOWER_EL); 268 ARMV8_EC_CASE(ARMV8_ESR_EL2_WATCHPOINT_EXCEPTION_FROM_EL2); 269 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_BKPT_INSN); 270 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH32_VEC_CATCH_EXCEPTION); 271 ARMV8_EC_CASE(ARMV8_ESR_EL2_EC_AARCH64_BRK_INSN); 272 #undef ARMV8_EC_CASE 273 default: 274 break; 275 } 276 277 return "<INVALID>"; 278 } 279 280 281 /** 216 282 * Unmaps the given guest physical address range (page aligned). 217 283 * … … 802 868 803 869 /** 804 * Handles an exit from hv_vcpu_run(). 870 * Returns the byte size from the given access SAS value. 871 * 872 * @returns Number of bytes to transfer. 873 * @param uSas The SAS value to convert. 874 */ 875 DECLINLINE(size_t) nemR3DarwinGetByteCountFromSas(uint8_t uSas) 876 { 877 switch (uSas) 878 { 879 case ARMV8_EC_ISS_DATA_ABRT_SAS_BYTE: return sizeof(uint8_t); 880 case ARMV8_EC_ISS_DATA_ABRT_SAS_HALFWORD: return sizeof(uint16_t); 881 case ARMV8_EC_ISS_DATA_ABRT_SAS_WORD: return sizeof(uint32_t); 882 case ARMV8_EC_ISS_DATA_ABRT_SAS_DWORD: return sizeof(uint64_t); 883 default: 884 AssertReleaseFailed(); 885 } 886 887 return 0; 888 } 889 890 891 /** 892 * Sets the given general purpose register to the given value. 893 * 894 * @returns nothing. 895 * @param pVCpu The cross context virtual CPU structure of the 896 * calling EMT. 897 * @param uReg The register index. 898 * @param f64BitReg Flag whether to operate on a 64-bit or 32-bit register. 899 * @param fSignExtend Flag whether to sign extend the value. 900 * @param u64Val The value. 901 */ 902 DECLINLINE(void) nemR3DarwinSetGReg(PVMCPU pVCpu, uint8_t uReg, bool f64BitReg, bool fSignExtend, uint64_t u64Val) 903 { 904 AssertReturnVoid(uReg < 31); 905 906 if (f64BitReg) 907 pVCpu->cpum.GstCtx.aGRegs[uReg].x = fSignExtend ? (int64_t)u64Val : u64Val; 908 else 909 pVCpu->cpum.GstCtx.aGRegs[uReg].w = fSignExtend ? (int32_t)u64Val : u64Val; /** @todo Does this clear the upper half on real hardware? */ 910 911 /* Mark the register as not extern anymore. */ 912 switch (uReg) 913 { 914 case 0: 915 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X0; 916 break; 917 case 1: 918 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X1; 919 break; 920 case 2: 921 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X2; 922 break; 923 case 3: 924 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X3; 925 break; 926 default: 927 AssertRelease(!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_X4_X28)); 928 /** @todo We need to import all missing registers in order to clear this flag (or just set it in HV from here). */ 929 } 930 } 931 932 933 /** 934 * Gets the given general purpose register and returns the value. 935 * 936 * @returns Value from the given register. 937 * @param pVCpu The cross context virtual CPU structure of the 938 * calling EMT. 939 * @param uReg The register index. 940 */ 941 DECLINLINE(uint64_t) nemR3DarwinGetGReg(PVMCPU pVCpu, uint8_t uReg) 942 { 943 AssertReturn(uReg < 31, 0); 944 945 /** @todo Import the register if extern. */ 946 AssertRelease(!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_GPRS_MASK)); 947 948 return pVCpu->cpum.GstCtx.aGRegs[uReg].x; 949 } 950 951 952 /** 953 * Works on the data abort exception (which will be a MMIO access most of the time). 805 954 * 806 955 * @returns VBox strict status code. … … 808 957 * @param pVCpu The cross context virtual CPU structure of the 809 958 * calling EMT. 959 * @param uIss The instruction specific syndrome value. 960 * @param fInsn32Bit Flag whether the exception was caused by a 32-bit or 16-bit instruction. 961 * @param GCPtrDataAbrt The virtual GC address causing the data abort. 962 * @param GCPhysDataAbrt The physical GC address which caused the data abort. 963 */ 964 static VBOXSTRICTRC nemR3DarwinHandleExitExceptionDataAbort(PVM pVM, PVMCPU pVCpu, uint32_t uIss, bool fInsn32Bit, 965 RTGCPTR GCPtrDataAbrt, RTGCPHYS GCPhysDataAbrt) 966 { 967 bool fIsv = RT_BOOL(uIss & ARMV8_EC_ISS_DATA_ABRT_ISV); 968 bool fL2Fault = RT_BOOL(uIss & ARMV8_EC_ISS_DATA_ABRT_S1PTW); 969 bool fWrite = RT_BOOL(uIss & ARMV8_EC_ISS_DATA_ABRT_WNR); 970 bool f64BitReg = RT_BOOL(uIss & ARMV8_EC_ISS_DATA_ABRT_SF); 971 bool fSignExtend = RT_BOOL(uIss & ARMV8_EC_ISS_DATA_ABRT_SSE); 972 uint8_t uReg = ARMV8_EC_ISS_DATA_ABRT_SRT_GET(uIss); 973 uint8_t uAcc = ARMV8_EC_ISS_DATA_ABRT_SAS_GET(uIss); 974 size_t cbAcc = nemR3DarwinGetByteCountFromSas(uAcc); 975 LogFlowFunc(("fIsv=%RTbool fL2Fault=%RTbool fWrite=%RTbool f64BitReg=%RTbool fSignExtend=%RTbool uReg=%u uAcc=%u GCPtrDataAbrt=%RGv GCPhysDataAbrt=%RGp\n", 976 fIsv, fL2Fault, fWrite, f64BitReg, fSignExtend, uReg, uAcc, GCPtrDataAbrt, GCPhysDataAbrt)); 977 978 AssertReturn(fIsv, VERR_NOT_SUPPORTED); /** @todo Implement using IEM when this should occur. */ 979 980 EMHistoryAddExit(pVCpu, 981 fWrite 982 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE) 983 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ), 984 pVCpu->cpum.GstCtx.Pc.u64, ASMReadTSC()); 985 986 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 987 uint64_t u64Val; 988 if (fWrite) 989 { 990 u64Val = nemR3DarwinGetGReg(pVCpu, uReg); 991 rcStrict = PGMPhysWrite(pVM, GCPhysDataAbrt, &u64Val, cbAcc, PGMACCESSORIGIN_HM); 992 Log4(("MmioExit/%u: %08RX64: WRITE %#x LB %u, %.*Rhxs -> rcStrict=%Rrc\n", 993 pVCpu->idCpu, pVCpu->cpum.GstCtx.Pc.u64, GCPhysDataAbrt, cbAcc, cbAcc, 994 &u64Val, VBOXSTRICTRC_VAL(rcStrict) )); 995 } 996 else 997 { 998 rcStrict = PGMPhysRead(pVM, GCPhysDataAbrt, &u64Val, cbAcc, PGMACCESSORIGIN_HM); 999 Log4(("MmioExit/%u: %08RX64: READ %#x LB %u -> %.*Rhxs rcStrict=%Rrc\n", 1000 pVCpu->idCpu, pVCpu->cpum.GstCtx.Pc.u64, GCPhysDataAbrt, cbAcc, cbAcc, 1001 &u64Val, VBOXSTRICTRC_VAL(rcStrict) )); 1002 if (rcStrict == VINF_SUCCESS) 1003 nemR3DarwinSetGReg(pVCpu, uReg, f64BitReg, fSignExtend, u64Val); 1004 } 1005 1006 if (rcStrict == VINF_SUCCESS) 1007 pVCpu->cpum.GstCtx.Pc.u64 += fInsn32Bit ? sizeof(uint32_t) : sizeof(uint16_t); 1008 1009 return rcStrict; 1010 } 1011 1012 1013 /** 1014 * Handles an exception VM exit. 1015 * 1016 * @returns VBox strict status code. 1017 * @param pVM The cross context VM structure. 1018 * @param pVCpu The cross context virtual CPU structure of the 1019 * calling EMT. 1020 * @param pExit Pointer to the exit information. 1021 */ 1022 static VBOXSTRICTRC nemR3DarwinHandleExitException(PVM pVM, PVMCPU pVCpu, const hv_vcpu_exit_t *pExit) 1023 { 1024 uint32_t uEc = ARMV8_ESR_EL2_EC_GET(pExit->exception.syndrome); 1025 uint32_t uIss = ARMV8_ESR_EL2_ISS_GET(pExit->exception.syndrome); 1026 bool fInsn32Bit = ARMV8_ESR_EL2_IL_IS_32BIT(pExit->exception.syndrome); 1027 1028 LogFlowFunc(("pVM=%p pVCpu=%p{.idCpu=%u} uEc=%u{%s} uIss=%#RX32 fInsn32Bit=%RTbool\n", 1029 pVM, pVCpu, pVCpu->idCpu, uEc, nemR3DarwinEsrEl2EcStringify(uEc), uIss, fInsn32Bit)); 1030 1031 switch (uEc) 1032 { 1033 case ARMV8_ESR_EL2_DATA_ABORT_FROM_LOWER_EL: 1034 return nemR3DarwinHandleExitExceptionDataAbort(pVM, pVCpu, uIss, fInsn32Bit, pExit->exception.virtual_address, 1035 pExit->exception.physical_address); 1036 case ARMV8_ESR_EL2_EC_UNKNOWN: 1037 default: 1038 LogRel(("NEM/Darwin: Unknown Exception Class in syndrome: uEc=%u{%s} uIss=%#RX32 fInsn32Bit=%RTbool\n", 1039 uEc, nemR3DarwinEsrEl2EcStringify(uEc), uIss, fInsn32Bit)); 1040 return VERR_NOT_IMPLEMENTED; 1041 } 1042 1043 return VINF_SUCCESS; 1044 } 1045 1046 1047 /** 1048 * Handles an exit from hv_vcpu_run(). 1049 * 1050 * @returns VBox strict status code. 1051 * @param pVM The cross context VM structure. 1052 * @param pVCpu The cross context virtual CPU structure of the 1053 * calling EMT. 810 1054 */ 811 1055 static VBOXSTRICTRC nemR3DarwinHandleExit(PVM pVM, PVMCPU pVCpu) … … 825 1069 case HV_EXIT_REASON_CANCELED: 826 1070 return VINF_EM_RAW_INTERRUPT; 1071 case HV_EXIT_REASON_EXCEPTION: 1072 return nemR3DarwinHandleExitException(pVM, pVCpu, pExit); 827 1073 default: 828 1074 AssertReleaseFailed(); … … 863 1109 static VBOXSTRICTRC nemR3DarwinPreRunGuest(PVM pVM, PVMCPU pVCpu, bool fSingleStepping) 864 1110 { 1111 #ifdef LOG_ENABLED 1112 if (LogIs3Enabled()) 1113 nemR3DarwinLogState(pVM, pVCpu); 1114 #endif 1115 865 1116 /** @todo */ RT_NOREF(fSingleStepping); 866 1117 int rc = nemR3DarwinExportGuestState(pVM, pVCpu);
Note:
See TracChangeset
for help on using the changeset viewer.

