From ead1e7a2a36a1d5fd1c612554590c99a05a98ce4 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 20 Aug 2019 11:24:40 +0100 Subject: dev-arm: Rewrite ICC_BPR0/ICC_BPR1 handling The patch is fixing BPR reads in AA32, by removing the line Gicv3::GroupId group = misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S; Where a read to ICC_BPR0 will return a G1S group. The patch is also fixing Security banking accesses. Change-Id: I28f1d1244c44d4b8b202d3141f8380943c7c1c86 Signed-off-by: Giacomo Travaglini Reviewed-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20620 Maintainer: Andreas Sandberg Tested-by: kokoro --- src/dev/arm/gic_v3_cpu_interface.cc | 219 +++++++++++++++++------------------- src/dev/arm/gic_v3_cpu_interface.hh | 1 + 2 files changed, 102 insertions(+), 118 deletions(-) (limited to 'src/dev/arm') diff --git a/src/dev/arm/gic_v3_cpu_interface.cc b/src/dev/arm/gic_v3_cpu_interface.cc index b8752dd91..cc630b4d2 100644 --- a/src/dev/arm/gic_v3_cpu_interface.cc +++ b/src/dev/arm/gic_v3_cpu_interface.cc @@ -304,102 +304,45 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) // Binary Point Register 0 case MISCREG_ICC_BPR0: - case MISCREG_ICC_BPR0_EL1: + case MISCREG_ICC_BPR0_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { return readMiscReg(MISCREG_ICV_BPR0_EL1); } - M5_FALLTHROUGH; + value = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1); + break; + } // Binary Point Register 1 case MISCREG_ICC_BPR1: case MISCREG_ICC_BPR1_EL1: { - if ((currEL() == EL1) && !inSecureState() && hcr_imo) { - return readMiscReg(MISCREG_ICV_BPR1_EL1); - } - - Gicv3::GroupId group = - misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S; - - if (group == Gicv3::G1S && !inSecureState()) { - group = Gicv3::G1NS; - } - - ICC_CTLR_EL1 icc_ctlr_el1_s = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); - - if ((group == Gicv3::G1S) && !isEL3OrMon() && - icc_ctlr_el1_s.CBPR) { - group = Gicv3::G0S; - } - - bool sat_inc = false; - - ICC_CTLR_EL1 icc_ctlr_el1_ns = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); - - if ((group == Gicv3::G1NS) && (currEL() < EL3) && - icc_ctlr_el1_ns.CBPR) { - // Reads return BPR0 + 1 saturated to 7, WI - group = Gicv3::G0S; - sat_inc = true; - } - - uint8_t bpr; - - if (group == Gicv3::G0S) { - bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1); - } else { - bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1); - bpr = std::max(bpr, group == Gicv3::G1S ? - GIC_MIN_BPR : GIC_MIN_BPR_NS); - } - - if (sat_inc) { - bpr++; + value = bpr1(isSecureBelowEL3() ? Gicv3::G1S : Gicv3::G1NS); + break; + } - if (bpr > 7) { - bpr = 7; - } - } + // Virtual Binary Point Register 0 + case MISCREG_ICV_BPR0_EL1: { + ICH_VMCR_EL2 ich_vmcr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - value = bpr; - break; + value = ich_vmcr_el2.VBPR0; + break; } // Virtual Binary Point Register 1 - case MISCREG_ICV_BPR0_EL1: case MISCREG_ICV_BPR1_EL1: { - Gicv3::GroupId group = - misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS; - ICH_VMCR_EL2 ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - bool sat_inc = false; - - if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) { - // bpr0 + 1 saturated to 7, WI - group = Gicv3::G0S; - sat_inc = true; - } - - uint8_t vbpr; + ICH_VMCR_EL2 ich_vmcr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - if (group == Gicv3::G0S) { - vbpr = ich_vmcr_el2.VBPR0; - } else { - vbpr = ich_vmcr_el2.VBPR1; - } - - if (sat_inc) { - vbpr++; - - if (vbpr > 7) { - vbpr = 7; - } - } + if (ich_vmcr_el2.VCBPR) { + // bpr0 + 1 saturated to 7, WI + value = ich_vmcr_el2.VBPR0 + 1; + value = value < 7 ? value : 7; + } else { + value = ich_vmcr_el2.VBPR1; + } - value = vbpr; - break; + break; } // Interrupt Priority Mask Register @@ -1093,51 +1036,48 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) // Binary Point Register 0 case MISCREG_ICC_BPR0: - case MISCREG_ICC_BPR0_EL1: + case MISCREG_ICC_BPR0_EL1: { + if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { + return setMiscReg(MISCREG_ICV_BPR0_EL1, val); + } + break; + } // Binary Point Register 1 case MISCREG_ICC_BPR1: case MISCREG_ICC_BPR1_EL1: { - if ((currEL() == EL1) && !inSecureState()) { - if (misc_reg == MISCREG_ICC_BPR0_EL1 && hcr_fmo) { - return setMiscReg(MISCREG_ICV_BPR0_EL1, val); - } else if (misc_reg == MISCREG_ICC_BPR1_EL1 && hcr_imo) { - return setMiscReg(MISCREG_ICV_BPR1_EL1, val); - } - } - - Gicv3::GroupId group = - misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S; - - if (group == Gicv3::G1S && !inSecureState()) { - group = Gicv3::G1NS; - } - - ICC_CTLR_EL1 icc_ctlr_el1_s = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); - - if ((group == Gicv3::G1S) && !isEL3OrMon() && - icc_ctlr_el1_s.CBPR) { - group = Gicv3::G0S; - } + if ((currEL() == EL1) && !inSecureState() && hcr_imo) { + return setMiscReg(MISCREG_ICV_BPR1_EL1, val); + } - ICC_CTLR_EL1 icc_ctlr_el1_ns = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); + val &= 0x7; - if ((group == Gicv3::G1NS) && (currEL() < EL3) && - icc_ctlr_el1_ns.CBPR) { - // BPR0 + 1 saturated to 7, WI - return; - } + if (isSecureBelowEL3()) { + // group == Gicv3::G1S + ICC_CTLR_EL1 icc_ctlr_el1_s = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); - uint8_t min_val = (group == Gicv3::G1NS) ? - GIC_MIN_BPR_NS : GIC_MIN_BPR; - val &= 0x7; + val = val > GIC_MIN_BPR ? val : GIC_MIN_BPR; + if (haveEL(EL3) && !isEL3OrMon() && icc_ctlr_el1_s.CBPR) { + isa->setMiscRegNoEffect(MISCREG_ICC_BPR0_EL1, val); + } else { + isa->setMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_S, val); + } + return; + } else { + // group == Gicv3::G1NS + ICC_CTLR_EL1 icc_ctlr_el1_ns = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); - if (val < min_val) { - val = min_val; - } + val = val > GIC_MIN_BPR_NS ? val : GIC_MIN_BPR_NS; + if (haveEL(EL3) && !isEL3OrMon() && icc_ctlr_el1_ns.CBPR) { + // Non secure writes from EL1 and EL2 are ignored + } else { + isa->setMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_NS, val); + } + return; + } - break; + break; } // Virtual Binary Point Register 0 @@ -1961,8 +1901,10 @@ Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) if (group == Gicv3::G0S) { bpr = readMiscReg(MISCREG_ICC_BPR0_EL1) & 0x7; + } else if (group == Gicv3::G1S) { + bpr = bpr1(Gicv3::G1S) & 0x7; } else { - bpr = readMiscReg(MISCREG_ICC_BPR1_EL1) & 0x7; + bpr = bpr1(Gicv3::G1NS) & 0x7; } if (group == Gicv3::G1NS) { @@ -2556,6 +2498,47 @@ Gicv3CPUInterface::maintenanceInterruptStatus() const return ich_misr_el2; } +RegVal +Gicv3CPUInterface::bpr1(Gicv3::GroupId group) +{ + bool hcr_imo = getHCREL2IMO(); + if ((currEL() == EL1) && !inSecureState() && hcr_imo) { + return readMiscReg(MISCREG_ICV_BPR1_EL1); + } + + RegVal bpr = 0; + + if (group == Gicv3::G1S) { + ICC_CTLR_EL1 icc_ctlr_el1_s = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); + + if (!isEL3OrMon() && icc_ctlr_el1_s.CBPR) { + bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1); + } else { + bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_S); + bpr = bpr > GIC_MIN_BPR ? bpr : GIC_MIN_BPR; + } + } else if (group == Gicv3::G1NS) { + ICC_CTLR_EL1 icc_ctlr_el1_ns = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); + + // Check if EL3 is implemented and this is a non secure accesses at + // EL1 and EL2 + if (haveEL(EL3) && !isEL3OrMon() && icc_ctlr_el1_ns.CBPR) { + // Reads return BPR0 + 1 saturated to 7, WI + bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1) + 1; + bpr = bpr < 7 ? bpr : 7; + } else { + bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_NS); + bpr = bpr > GIC_MIN_BPR_NS ? bpr : GIC_MIN_BPR_NS; + } + } else { + panic("Should be used with G1S and G1NS only\n"); + } + + return bpr; +} + void Gicv3CPUInterface::serialize(CheckpointOut & cp) const { diff --git a/src/dev/arm/gic_v3_cpu_interface.hh b/src/dev/arm/gic_v3_cpu_interface.hh index ed432bce5..56a66952c 100644 --- a/src/dev/arm/gic_v3_cpu_interface.hh +++ b/src/dev/arm/gic_v3_cpu_interface.hh @@ -336,6 +336,7 @@ class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable void virtualIncrementEOICount(); bool virtualIsEOISplitMode() const; void virtualUpdate(); + RegVal bpr1(Gicv3::GroupId group); public: -- cgit v1.2.3