summaryrefslogtreecommitdiff
path: root/src/dev/arm
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2019-08-20 11:24:40 +0100
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2019-09-06 11:53:49 +0000
commitead1e7a2a36a1d5fd1c612554590c99a05a98ce4 (patch)
tree387cacbdff712f8c2e7e375ab2bbdc60407cc372 /src/dev/arm
parent51022bfe0eeaef5f08d6ace98ebfb1917d1b3331 (diff)
downloadgem5-ead1e7a2a36a1d5fd1c612554590c99a05a98ce4.tar.xz
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 <giacomo.travaglini@arm.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20620 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'src/dev/arm')
-rw-r--r--src/dev/arm/gic_v3_cpu_interface.cc219
-rw-r--r--src/dev/arm/gic_v3_cpu_interface.hh1
2 files changed, 102 insertions, 118 deletions
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: