diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index 446f2afd18..54045f2fb1 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -1026,6 +1026,13 @@ ArmStaticInst::sveAccessTrap(ExceptionLevel el) const Fault ArmStaticInst::checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const { + // We first check if we are in streaming mode or not. If we are in + // streaming mode, we actually check the SME traps, not the SVE traps! + SVCR svcr_sm_check = tc->readMiscReg(MISCREG_SVCR); + if (svcr_sm_check.sm) { + return checkSmeEnabled(tc, cpsr, cpacr); + } + const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el; // Check if access disabled in CPACR_EL1 if (el <= EL1 && !ELIsInHost(tc, el)) { @@ -1073,6 +1080,126 @@ ArmStaticInst::checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const return NoFault; } +Fault +ArmStaticInst::smeAccessTrap(ExceptionLevel el, uint32_t iss) const +{ + switch (el) { + case EL1: + return std::make_shared( + machInst, iss, ExceptionClass::TRAPPED_SME); + case EL2: + return std::make_shared( + machInst, iss, ExceptionClass::TRAPPED_SME); + case EL3: + return std::make_shared( + machInst, iss, ExceptionClass::TRAPPED_SME); + + default: + panic("Illegal EL in smeAccessTrap\n"); + } +} + +Fault +ArmStaticInst::checkSmeEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const +{ + const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el; + // Check if access disabled in CPACR_EL1 + if (el <= EL1 && !ELIsInHost(tc, el)) { + if ((el == EL0 && cpacr.smen == 0x1) || + (!(cpacr.smen & 0x1))) + return smeAccessTrap(EL1); + + if ((el == EL0 && cpacr.fpen == 0x1) || + (!(cpacr.fpen & 0x1))) + return advSIMDFPAccessTrap64(EL1); + } + + // Check if access disabled in CPTR_EL2 + if (el <= EL2 && EL2Enabled(tc)) { + CPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL2); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) { + if (((cptr_en_check.smen & 0x1) == 0x0) || + (cptr_en_check.smen == 0x1 && el == EL0 && + hcr.tge == 0x1)) { + return smeAccessTrap(EL2); + } + if (((cptr_en_check.fpen & 0x1) == 0x0) || + (cptr_en_check.fpen == 0x1 && el == EL0 && + hcr.tge == 0x1)) { + return advSIMDFPAccessTrap64(EL2); + } + } else { + if (cptr_en_check.tsm == 1) + return smeAccessTrap(EL2); + if (cptr_en_check.tfp == 1) + return advSIMDFPAccessTrap64(EL2); + } + } + + // Check if access disabled in CPTR_EL3 + if (ArmSystem::haveEL(tc, EL3)) { + CPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL3); + if (!cptr_en_check.esm) + return smeAccessTrap(EL3); + if (cptr_en_check.tfp) + return advSIMDFPAccessTrap64(EL3); + } + + return NoFault; +} + +Fault +ArmStaticInst::checkSmeAccess(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const +{ + const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el; + // Check if access disabled in CPACR_EL1 + if (el <= EL1 && !ELIsInHost(tc, el)) { + if ((el == EL0 && cpacr.smen == 0x1) || (!(cpacr.smen & 0x1))) { + return smeAccessTrap(EL1); + } + } + + // Check if access disabled in CPTR_EL2 + if (el <= EL2 && EL2Enabled(tc)) { + CPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL2); + HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2); + if (HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) { + if (((cptr_en_check.smen & 0x1) == 0x0) || + (cptr_en_check.smen == 0x1 && el == EL0 && + hcr.tge == 0x1)) { + return smeAccessTrap(EL2); + } + } else { + if (cptr_en_check.tsm == 1) + return smeAccessTrap(EL2); + } + } + + // Check if access disabled in CPTR_EL3 + if (ArmSystem::haveEL(tc, EL3)) { + CPTR cptr_en_check = tc->readMiscReg(MISCREG_CPTR_EL3); + if (!cptr_en_check.esm) + return smeAccessTrap(EL3); + } + + return NoFault; +} + +Fault +ArmStaticInst::checkSveSmeEnabled(ThreadContext *tc, CPSR cpsr, + CPACR cpacr) const +{ + // If we are not in streaming mode, check the SVE traps, else check the SME + // traps. + SVCR svcr = tc->readMiscReg(MISCREG_SVCR); + if (!svcr.sm) { + return checkSveEnabled(tc, cpsr, cpacr); + } else { + return checkSmeEnabled(tc, cpsr, cpacr); + } +} + static uint8_t getRestoredITBits(ThreadContext *tc, CPSR spsr) { diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index 3b67e6b253..cc96dd9269 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -513,6 +513,35 @@ class ArmStaticInst : public StaticInst */ Fault checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const; + + /** + * Trap an access to SME registers due to access control bits. + * + * @param el Target EL for the trap. + * @param iss ISS to be used for the trap. + */ + Fault smeAccessTrap(ExceptionLevel el, uint32_t iss = 0) const; + + /** + * Check if SME is enabled by checking the SME and FP bits of + * CPACR_EL1, CPTR_EL2, and CPTR_EL3 + */ + Fault checkSmeEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const; + + /** + * Check an SME access against CPACR_EL1, CPTR_EL2, and CPTR_EL3. + * This is purely used from the management instructions as it should + * be possible to call SMSTART/SMSTOP without having the floating + * point flags correctly set up. + */ + Fault checkSmeAccess(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const; + + /** + * Check an SVE access against CPACR_EL1, CPTR_EL2, and CPTR_EL3, but + * choosing the correct set of traps to check based on Streaming Mode + */ + Fault checkSveSmeEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const; + /** * Get the new PSTATE from a SPSR register in preparation for an * exception return. diff --git a/src/arch/arm/isa/templates/sve.isa b/src/arch/arm/isa/templates/sve.isa index 87316f1440..fc38a2b979 100644 --- a/src/arch/arm/isa/templates/sve.isa +++ b/src/arch/arm/isa/templates/sve.isa @@ -36,7 +36,9 @@ let {{ sveEnabledCheckCode = ''' if (FullSystem) { - fault = this->checkSveEnabled(xc->tcBase(), Cpsr, Cpacr64); + // Check an SVE inst against the appropriate traps/enables based + // on the Streaming Mode. + fault = this->checkSveSmeEnabled(xc->tcBase(), Cpsr, Cpacr64); if (fault != NoFault) { return fault; } diff --git a/src/arch/arm/types.hh b/src/arch/arm/types.hh index 50db9bc9af..2251d57c0b 100644 --- a/src/arch/arm/types.hh +++ b/src/arch/arm/types.hh @@ -323,6 +323,7 @@ namespace ArmISA SMC_64 = 0x17, TRAPPED_MSR_MRS_64 = 0x18, TRAPPED_SVE = 0x19, + TRAPPED_SME = 0x1D, PREFETCH_ABORT_TO_HYP = 0x20, PREFETCH_ABORT_LOWER_EL = 0x20, // AArch64 alias PREFETCH_ABORT_FROM_HYP = 0x21,