VirtualBox

Changeset 99078 in vbox for trunk


Ignore:
Timestamp:
Mar 21, 2023 11:03:33 AM (19 months ago)
Author:
vboxsync
Message:

VMM/NEMR3Native-darwin-armv8.cpp: Implement MMIO data abort handling, bugref:10390

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin-armv8.cpp

    r99070 r99078  
    5050#include "dtrace/VBoxVMM.h"
    5151
     52#include <iprt/armv8.h>
    5253#include <iprt/asm.h>
    5354#include <iprt/ldr.h>
     
    214215
    215216/**
     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 */
     222static 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/**
    216282 * Unmaps the given guest physical address range (page aligned).
    217283 *
     
    802868
    803869/**
    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 */
     875DECLINLINE(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 */
     902DECLINLINE(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 */
     941DECLINLINE(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).
    805954 *
    806955 * @returns VBox strict status code.
     
    808957 * @param   pVCpu           The cross context virtual CPU structure of the
    809958 *                          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 */
     964static 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 */
     1022static 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.
    8101054 */
    8111055static VBOXSTRICTRC nemR3DarwinHandleExit(PVM pVM, PVMCPU pVCpu)
     
    8251069        case HV_EXIT_REASON_CANCELED:
    8261070            return VINF_EM_RAW_INTERRUPT;
     1071        case HV_EXIT_REASON_EXCEPTION:
     1072            return nemR3DarwinHandleExitException(pVM, pVCpu, pExit);
    8271073        default:
    8281074            AssertReleaseFailed();
     
    8631109static VBOXSTRICTRC nemR3DarwinPreRunGuest(PVM pVM, PVMCPU pVCpu, bool fSingleStepping)
    8641110{
     1111#ifdef LOG_ENABLED
     1112    if (LogIs3Enabled())
     1113        nemR3DarwinLogState(pVM, pVCpu);
     1114#endif
     1115
    8651116    /** @todo */ RT_NOREF(fSingleStepping);
    8661117    int rc = nemR3DarwinExportGuestState(pVM, pVCpu);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette