From: Jairo Balart Date: Sat, 16 Feb 2019 12:27:45 +0000 (+0100) Subject: dev-arm: cleanup of gicv3 CPU interface code and fixes X-Git-Tag: v19.0.0.0~1059 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=66c80fcb44dfbfb9dc70b972e33104f053bd3015;p=gem5.git dev-arm: cleanup of gicv3 CPU interface code and fixes Change-Id: I4643140f60da4dc9179b5bfed1e3ddd7c2f23091 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/16484 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini --- diff --git a/src/dev/arm/gic_v3_cpu_interface.cc b/src/dev/arm/gic_v3_cpu_interface.cc index 3f6c23f6e..8cbc77a0b 100644 --- a/src/dev/arm/gic_v3_cpu_interface.cc +++ b/src/dev/arm/gic_v3_cpu_interface.cc @@ -45,10 +45,6 @@ Gicv3CPUInterface::Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id) { } -Gicv3CPUInterface::~Gicv3CPUInterface() -{ -} - void Gicv3CPUInterface::init() { @@ -69,7 +65,7 @@ Gicv3CPUInterface::reset() } bool -Gicv3CPUInterface::getHCREL2FMO() +Gicv3CPUInterface::getHCREL2FMO() const { HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2); @@ -83,7 +79,7 @@ Gicv3CPUInterface::getHCREL2FMO() } bool -Gicv3CPUInterface::getHCREL2IMO() +Gicv3CPUInterface::getHCREL2IMO() const { HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2); @@ -104,6 +100,7 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) bool hcr_imo = getHCREL2IMO(); switch (misc_reg) { + // Active Priorities Group 1 Registers case MISCREG_ICC_AP1R0: case MISCREG_ICC_AP1R0_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_imo) { @@ -126,6 +123,7 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) // only implemented if supporting 7 or more bits of priority return 0; + // Active Priorities Group 0 Registers case MISCREG_ICC_AP0R0: case MISCREG_ICC_AP0R0_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { @@ -148,79 +146,53 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) // only implemented if supporting 7 or more bits of priority return 0; + // Interrupt Group 0 Enable register EL1 case MISCREG_ICC_IGRPEN0: case MISCREG_ICC_IGRPEN0_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { - return readMiscReg(MISCREG_ICV_IGRPEN0_EL1); + return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN0_EL1); } break; } - case MISCREG_ICV_IGRPEN0_EL1: { - RegVal ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - value = bits(ich_vmcr_el2, ICH_VMCR_EL2_VENG0_SHIFT); - break; - } - + // Interrupt Group 1 Enable register EL1 case MISCREG_ICC_IGRPEN1: case MISCREG_ICC_IGRPEN1_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_imo) { - return readMiscReg(MISCREG_ICV_IGRPEN1_EL1); + return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN1_EL1); } break; } - case MISCREG_ICV_IGRPEN1_EL1: { - RegVal ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - value = bits(ich_vmcr_el2, ICH_VMCR_EL2_VENG1_SHIFT); - break; - } - + // Interrupt Group 1 Enable register EL3 case MISCREG_ICC_MGRPEN1: - case MISCREG_ICC_IGRPEN1_EL3: { - // EnableGrp1S and EnableGrp1NS are aliased with - // ICC_IGRPEN1_EL1_S.Enable and ICC_IGRPEN1_EL1_NS.Enable - bool enable_grp_1s = - isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S) & - ICC_IGRPEN1_EL1_ENABLE; - bool enable_grp_1ns = - isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) & - ICC_IGRPEN1_EL1_ENABLE; - value = 0; - - if (enable_grp_1s) { - value |= ICC_IGRPEN1_EL3_ENABLEGRP1S; - } - - if (enable_grp_1ns) { - value |= ICC_IGRPEN1_EL3_ENABLEGRP1NS; - } - + case MISCREG_ICC_IGRPEN1_EL3: break; - } + // Running Priority Register case MISCREG_ICC_RPR: case MISCREG_ICC_RPR_EL1: { if ((currEL() == EL1) && !inSecureState() && - (hcr_imo || hcr_fmo)) { + (hcr_imo || hcr_fmo)) { return readMiscReg(MISCREG_ICV_RPR_EL1); } uint8_t rprio = highestActivePriority(); if (haveEL(EL3) && !inSecureState() && - (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { - /* NS GIC access and Group 0 is inaccessible to NS */ + (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { + // Spec section 4.8.1 + // For Non-secure access to ICC_RPR_EL1 when SCR_EL3.FIQ == 1 if ((rprio & 0x80) == 0) { - /* NS should not see priorities in the Secure half of the - * range */ + // If the current priority mask value is in the range of + // 0x00-0x7F a read access returns the value 0x0 rprio = 0; } else if (rprio != 0xff) { - /* Non-idle priority: show the Non-secure view of it */ + // If the current priority mask value is in the range of + // 0x80-0xFF a read access returns the Non-secure read of + // the current value rprio = (rprio << 1) & 0xff; } } @@ -229,11 +201,13 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // Virtual Running Priority Register case MISCREG_ICV_RPR_EL1: { value = virtualHighestActivePriority(); break; } + // Highest Priority Pending Interrupt Register 0 case MISCREG_ICC_HPPIR0: case MISCREG_ICC_HPPIR0_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { @@ -244,24 +218,26 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // Virtual Highest Priority Pending Interrupt Register 0 case MISCREG_ICV_HPPIR0_EL1: { value = Gicv3::INTID_SPURIOUS; int lr_idx = getHPPVILR(); if (lr_idx >= 0) { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); Gicv3::GroupId group = - lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; + ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; if (group == Gicv3::G0S) { - value = bits(lr, 31, 0); + value = ich_lr_el2.vINTID; } } break; } + // Highest Priority Pending Interrupt Register 1 case MISCREG_ICC_HPPIR1: case MISCREG_ICC_HPPIR1_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_imo) { @@ -272,24 +248,26 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // Virtual Highest Priority Pending Interrupt Register 1 case MISCREG_ICV_HPPIR1_EL1: { value = Gicv3::INTID_SPURIOUS; int lr_idx = getHPPVILR(); if (lr_idx >= 0) { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); Gicv3::GroupId group = - lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; + ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; if (group == Gicv3::G1NS) { - value = bits(lr, 31, 0); + value = ich_lr_el2.vINTID; } } break; } + // Binary Point Register 0 case MISCREG_ICC_BPR0: case MISCREG_ICC_BPR0_EL1: if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { @@ -298,13 +276,13 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) M5_FALLTHROUGH; + // 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); - } + 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; @@ -312,19 +290,21 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) group = Gicv3::G1NS; } - if ((group == Gicv3::G1S) && - !isEL3OrMon() && - (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S) - & ICC_CTLR_EL1_CBPR)) { + 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; - if ((group == Gicv3::G1NS) && - (currEL() < EL3) && - (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS) - & ICC_CTLR_EL1_CBPR)) { + 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; @@ -348,18 +328,19 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) value = bpr; 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; - RegVal ich_vmcr_el2 = + ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); bool sat_inc = false; - if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) { - // reads return bpr0 + 1 saturated to 7, writes ignored + if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) { + // bpr0 + 1 saturated to 7, WI group = Gicv3::G0S; sat_inc = true; } @@ -367,9 +348,9 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) uint8_t vbpr; if (group == Gicv3::G0S) { - vbpr = bits(ich_vmcr_el2, 23, 21); + vbpr = ich_vmcr_el2.VBPR0; } else { - vbpr = bits(ich_vmcr_el2, 20, 18); + vbpr = ich_vmcr_el2.VBPR1; } if (sat_inc) { @@ -384,38 +365,34 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // Interrupt Priority Mask Register case MISCREG_ICC_PMR: - case MISCREG_ICC_PMR_EL1: // Priority Mask Register - if ((currEL() == EL1) && !inSecureState() && - (hcr_imo || hcr_fmo)) { - return readMiscReg(MISCREG_ICV_PMR_EL1); + case MISCREG_ICC_PMR_EL1: + if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { + return isa->readMiscRegNoEffect(MISCREG_ICV_PMR_EL1); } if (haveEL(EL3) && !inSecureState() && - (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { - /* NS GIC access and Group 0 is inaccessible to NS */ + (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { + // Spec section 4.8.1 + // For Non-secure access to ICC_PMR_EL1 when SCR_EL3.FIQ == 1: if ((value & 0x80) == 0) { - /* NS should not see priorities in the Secure half of the - * range */ + // If the current priority mask value is in the range of + // 0x00-0x7F a read access returns the value 0x00. value = 0; } else if (value != 0xff) { - /* Non-idle priority: show the Non-secure view of it */ + // If the current priority mask value is in the range of + // 0x80-0xFF a read access returns the Non-secure read of the + // current value. value = (value << 1) & 0xff; } } break; - case MISCREG_ICV_PMR_EL1: { // Priority Mask Register - RegVal ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - - value = ich_vmcr_el2 >> ICH_VMCR_EL2_VPMR_SHIFT; - break; - } - + // Interrupt Acknowledge Register 0 case MISCREG_ICC_IAR0: - case MISCREG_ICC_IAR0_EL1: { // Interrupt Acknowledge Register 0 + case MISCREG_ICC_IAR0_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { return readMiscReg(MISCREG_ICV_IAR0_EL1); } @@ -437,27 +414,28 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // Virtual Interrupt Acknowledge Register 0 case MISCREG_ICV_IAR0_EL1: { int lr_idx = getHPPVILR(); uint32_t int_id = Gicv3::INTID_SPURIOUS; if (lr_idx >= 0) { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - if (!(lr & ICH_LR_EL2_GROUP) && hppviCanPreempt(lr_idx)) { - int_id = value = bits(lr, 31, 0); + if (!ich_lr_el2.Group && hppviCanPreempt(lr_idx)) { + int_id = ich_lr_el2.vINTID; if (int_id < Gicv3::INTID_SECURE || - int_id > Gicv3::INTID_SPURIOUS) { + int_id > Gicv3::INTID_SPURIOUS) { virtualActivateIRQ(lr_idx); } else { // Bogus... Pseudocode says: // - Move from pending to invalid... // - Return de bogus id... - lr &= ~ICH_LR_EL2_STATE_PENDING_BIT; + ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID; isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, - lr); + ich_lr_el2); } } } @@ -467,8 +445,9 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // Interrupt Acknowledge Register 1 case MISCREG_ICC_IAR1: - case MISCREG_ICC_IAR1_EL1: { // Interrupt Acknowledge Register 1 + case MISCREG_ICC_IAR1_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_imo) { return readMiscReg(MISCREG_ICV_IAR1_EL1); } @@ -482,14 +461,6 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) if (int_id < Gicv3::INTID_SECURE) { activateIRQ(int_id, hppi.group); } - - // LPIs are not activated and when acked their pending - // bit is cleared - if (int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) - { - redistributor->setClrLPI(int_id, false); - } - } else { int_id = Gicv3::INTID_SPURIOUS; } @@ -498,27 +469,28 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // Virtual Interrupt Acknowledge Register 1 case MISCREG_ICV_IAR1_EL1: { int lr_idx = getHPPVILR(); uint32_t int_id = Gicv3::INTID_SPURIOUS; if (lr_idx >= 0) { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - if (lr & ICH_LR_EL2_GROUP && hppviCanPreempt(lr_idx)) { - int_id = value = bits(lr, 31, 0); + if (ich_lr_el2.Group && hppviCanPreempt(lr_idx)) { + int_id = ich_lr_el2.vINTID; if (int_id < Gicv3::INTID_SECURE || - int_id > Gicv3::INTID_SPURIOUS) { + int_id > Gicv3::INTID_SPURIOUS) { virtualActivateIRQ(lr_idx); } else { // Bogus... Pseudocode says: // - Move from pending to invalid... // - Return de bogus id... - lr &= ~ICH_LR_EL2_STATE_PENDING_BIT; + ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID; isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, - lr); + ich_lr_el2); } } } @@ -528,268 +500,211 @@ Gicv3CPUInterface::readMiscReg(int misc_reg) break; } + // System Register Enable Register EL1 case MISCREG_ICC_SRE: - case MISCREG_ICC_SRE_EL1: { // System Register Enable Register - bool dfb; - bool dib; - - if (haveEL(EL3) && !distributor->DS) { - // DIB is RO alias of ICC_SRE_EL3.DIB - // DFB is RO alias of ICC_SRE_EL3.DFB - RegVal icc_sre_el3 = - isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3); - dfb = icc_sre_el3 & ICC_SRE_EL3_DFB; - dib = icc_sre_el3 & ICC_SRE_EL3_DIB; - } else if (haveEL(EL3) && distributor->DS) { - // DIB is RW alias of ICC_SRE_EL3.DIB - // DFB is RW alias of ICC_SRE_EL3.DFB - RegVal icc_sre_el3 = - isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3); - dfb = icc_sre_el3 & ICC_SRE_EL3_DFB; - dib = icc_sre_el3 & ICC_SRE_EL3_DIB; - } else if ((!haveEL(EL3) || distributor->DS) and haveEL(EL2)) { - // DIB is RO alias of ICC_SRE_EL2.DIB - // DFB is RO alias of ICC_SRE_EL2.DFB - RegVal icc_sre_el2 = - isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL2); - dfb = icc_sre_el2 & ICC_SRE_EL2_DFB; - dib = icc_sre_el2 & ICC_SRE_EL2_DIB; - } else { - dfb = value & ICC_SRE_EL1_DFB; - dib = value & ICC_SRE_EL1_DIB; - } - - value = ICC_SRE_EL1_SRE; - - if (dfb) { - value |= ICC_SRE_EL1_DFB; - } - - if (dib) { - value |= ICC_SRE_EL1_DIB; - } - + case MISCREG_ICC_SRE_EL1: { + /* + * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) + * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) + * SRE [0] == 1 (Only system register interface supported, RAO/WI) + */ + ICC_SRE_EL1 icc_sre_el1 = 0; + icc_sre_el1.SRE = 1; + icc_sre_el1.DIB = 1; + icc_sre_el1.DFB = 1; + value = icc_sre_el1; break; } + // System Register Enable Register EL2 case MISCREG_ICC_HSRE: - case MISCREG_ICC_SRE_EL2: // System Register Enable Register + case MISCREG_ICC_SRE_EL2: { /* * Enable [3] == 1 - * (Secure EL1 accesses to Secure ICC_SRE_EL1 do not trap to EL2, - * RAO/WI) + * (EL1 accesses to ICC_SRE_EL1 do not trap to EL2, RAO/WI) * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) * SRE [0] == 1 (Only system register interface supported, RAO/WI) */ - value = ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_DIB | ICC_SRE_EL2_DFB | - ICC_SRE_EL2_SRE; + ICC_SRE_EL2 icc_sre_el2 = 0; + icc_sre_el2.SRE = 1; + icc_sre_el2.DIB = 1; + icc_sre_el2.DFB = 1; + icc_sre_el2.Enable = 1; + value = icc_sre_el2; break; + } + // System Register Enable Register EL3 case MISCREG_ICC_MSRE: - case MISCREG_ICC_SRE_EL3: // System Register Enable Register + case MISCREG_ICC_SRE_EL3: { /* * Enable [3] == 1 - * (Secure EL1 accesses to Secure ICC_SRE_EL1 do not trap to EL3, - * RAO/WI) + * (EL1 accesses to ICC_SRE_EL1 do not trap to EL3. + * EL2 accesses to ICC_SRE_EL1 and ICC_SRE_EL2 do not trap to EL3. + * RAO/WI) * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) * SRE [0] == 1 (Only system register interface supported, RAO/WI) */ - value = ICC_SRE_EL3_ENABLE | ICC_SRE_EL3_DIB | ICC_SRE_EL3_DFB | - ICC_SRE_EL3_SRE; + ICC_SRE_EL3 icc_sre_el3 = 0; + icc_sre_el3.SRE = 1; + icc_sre_el3.DIB = 1; + icc_sre_el3.DFB = 1; + icc_sre_el3.Enable = 1; + value = icc_sre_el3; break; + } + // Control Register case MISCREG_ICC_CTLR: - case MISCREG_ICC_CTLR_EL1: { // Control Register - if ((currEL() == EL1) && !inSecureState() && - (hcr_imo || hcr_fmo)) { + case MISCREG_ICC_CTLR_EL1: { + if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { return readMiscReg(MISCREG_ICV_CTLR_EL1); } - // Add value for RO bits + // Enforce value for RO bits + // ExtRange [19], INTIDs in the range 1024..8191 not supported + // RSS [18], SGIs with affinity level 0 values of 0-255 are supported + // A3V [15], supports non-zero values of the Aff3 field in SGI + // generation System registers + // SEIS [14], does not support generation of SEIs (deprecated) // IDbits [13:11], 001 = 24 bits | 000 = 16 bits // PRIbits [10:8], number of priority bits implemented, minus one - value |= ICC_CTLR_EL1_RSS | ICC_CTLR_EL1_A3V | - (1 << 11) | ((PRIORITY_BITS - 1) << 8); + ICC_CTLR_EL1 icc_ctlr_el1 = value; + icc_ctlr_el1.ExtRange = 0; + icc_ctlr_el1.RSS = 1; + icc_ctlr_el1.A3V = 1; + icc_ctlr_el1.SEIS = 0; + icc_ctlr_el1.IDbits = 1; + icc_ctlr_el1.PRIbits = PRIORITY_BITS - 1; + value = icc_ctlr_el1; break; } + // Virtual Control Register case MISCREG_ICV_CTLR_EL1: { - value = ICC_CTLR_EL1_A3V | (1 << ICC_CTLR_EL1_IDBITS_SHIFT) | - (7 << ICC_CTLR_EL1_PRIBITS_SHIFT); - RegVal ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - - if (ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM) { - value |= ICC_CTLR_EL1_EOIMODE; - } - - if (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR) { - value |= ICC_CTLR_EL1_CBPR; - } - + ICV_CTLR_EL1 icv_ctlr_el1 = value; + icv_ctlr_el1.RSS = 0; + icv_ctlr_el1.A3V = 1; + icv_ctlr_el1.SEIS = 0; + icv_ctlr_el1.IDbits = 1; + icv_ctlr_el1.PRIbits = 7; + value = icv_ctlr_el1; break; } + // Control Register case MISCREG_ICC_MCTLR: case MISCREG_ICC_CTLR_EL3: { - // Add value for RO bits - // RSS [18] - // A3V [15] + // Enforce value for RO bits + // ExtRange [19], INTIDs in the range 1024..8191 not supported + // RSS [18], SGIs with affinity level 0 values of 0-255 are supported + // nDS [17], supports disabling of security + // A3V [15], supports non-zero values of the Aff3 field in SGI + // generation System registers + // SEIS [14], does not support generation of SEIs (deprecated) // IDbits [13:11], 001 = 24 bits | 000 = 16 bits // PRIbits [10:8], number of priority bits implemented, minus one - value |= ICC_CTLR_EL3_RSS | ICC_CTLR_EL3_A3V | (0 << 11) | - ((PRIORITY_BITS - 1) << 8); - // Aliased bits... - RegVal icc_ctlr_el1_ns = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); - RegVal icc_ctlr_el1_s = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); - - if (icc_ctlr_el1_ns & ICC_CTLR_EL1_EOIMODE) { - value |= ICC_CTLR_EL3_EOIMODE_EL1NS; - } - - if (icc_ctlr_el1_ns & ICC_CTLR_EL1_CBPR) { - value |= ICC_CTLR_EL3_CBPR_EL1NS; - } - - if (icc_ctlr_el1_s & ICC_CTLR_EL1_EOIMODE) { - value |= ICC_CTLR_EL3_EOIMODE_EL1S; - } - - if (icc_ctlr_el1_s & ICC_CTLR_EL1_CBPR) { - value |= ICC_CTLR_EL3_CBPR_EL1S; - } - + ICC_CTLR_EL3 icc_ctlr_el3 = value; + icc_ctlr_el3.ExtRange = 0; + icc_ctlr_el3.RSS = 1; + icc_ctlr_el3.nDS = 0; + icc_ctlr_el3.A3V = 1; + icc_ctlr_el3.SEIS = 0; + icc_ctlr_el3.IDbits = 0; + icc_ctlr_el3.PRIbits = PRIORITY_BITS - 1; + value = icc_ctlr_el3; break; } + // Hyp Control Register case MISCREG_ICH_HCR: case MISCREG_ICH_HCR_EL2: break; + // Hyp Active Priorities Group 0 Registers case MISCREG_ICH_AP0R0: case MISCREG_ICH_AP0R0_EL2: break; + // Hyp Active Priorities Group 1 Registers case MISCREG_ICH_AP1R0: case MISCREG_ICH_AP1R0_EL2: break; + // Maintenance Interrupt State Register case MISCREG_ICH_MISR: - case MISCREG_ICH_MISR_EL2: { - value = 0; - // Scan list registers and fill in the U, NP and EOI bits - eoiMaintenanceInterruptStatus((uint32_t *) &value); - RegVal ich_hcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); - RegVal ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - - if (ich_hcr_el2 & - (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) { - value |= ICH_MISR_EL2_LRENP; - } - - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) && - (ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) { - value |= ICH_MISR_EL2_VGRP0E; - } - - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) && - !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { - value |= ICH_MISR_EL2_VGRP0D; - } - - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) && - (ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { - value |= ICH_MISR_EL2_VGRP1E; - } + case MISCREG_ICH_MISR_EL2: + value = maintenanceInterruptStatus(); + break; - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) && - !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { - value |= ICH_MISR_EL2_VGRP1D; - } + // VGIC Type Register + case MISCREG_ICH_VTR: + case MISCREG_ICH_VTR_EL2: { + ICH_VTR_EL2 ich_vtr_el2 = value; - break; - } + ich_vtr_el2.ListRegs = VIRTUAL_NUM_LIST_REGS - 1; + ich_vtr_el2.A3V = 1; + ich_vtr_el2.IDbits = 1; + ich_vtr_el2.PREbits = VIRTUAL_PREEMPTION_BITS - 1; + ich_vtr_el2.PRIbits = VIRTUAL_PRIORITY_BITS - 1; - case MISCREG_ICH_VTR: - case MISCREG_ICH_VTR_EL2: - /* - * PRIbits [31:29] - * PREbits [28:26] - * IDbits [25:23] - * SEIS [22] == 0 (SEI Support) - * A3V [21] == 1 - * (Non-zero values supported for Affinity 3 in SGI genearion) - * nV4 [20] == 0 - * (Support for direct injection of virtual interrupts) - * TDS [19] == 0 (Implementation supports ICH_HCR_EL2.TDIR) - * ListRegs [4:0] - */ - value = (16 - 1) << 0 | - (5 - 1) << 26 | - (5 - 1) << 29; - value = - ((VIRTUAL_NUM_LIST_REGS - 1) << ICH_VTR_EL2_LISTREGS_SHIFT) | - // ICH_VTR_EL2_TDS | - // ICH_VTR_EL2_NV4 | - ICH_VTR_EL2_A3V | - (1 << ICH_VTR_EL2_IDBITS_SHIFT) | - ((VIRTUAL_PREEMPTION_BITS - 1) << ICH_VTR_EL2_PREBITS_SHIFT) | - ((VIRTUAL_PRIORITY_BITS - 1) << ICH_VTR_EL2_PRIBITS_SHIFT); + value = ich_vtr_el2; break; + } + // End of Interrupt Status Register case MISCREG_ICH_EISR: case MISCREG_ICH_EISR_EL2: - value = eoiMaintenanceInterruptStatus(nullptr); + value = eoiMaintenanceInterruptStatus(); break; + // Empty List Register Status Register case MISCREG_ICH_ELRSR: case MISCREG_ICH_ELRSR_EL2: value = 0; for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - if ((lr & ICH_LR_EL2_STATE_MASK) == 0 && - ((lr & ICH_LR_EL2_HW) != 0 || - (lr & ICH_LR_EL2_EOI) == 0)) { + if ((ich_lr_el2.State == ICH_LR_EL2_STATE_INVALID) && + (ich_lr_el2.HW || !ich_lr_el2.EOI)) { value |= (1 << lr_idx); } } break; + // List Registers case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: // AArch32 (maps to AArch64 MISCREG_ICH_LR_EL2 high half part) value = value >> 32; break; + // List Registers case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: // AArch32 (maps to AArch64 MISCREG_ICH_LR_EL2 low half part) value = value & 0xffffffff; break; + // List Registers case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: break; + // Virtual Machine Control Register case MISCREG_ICH_VMCR: case MISCREG_ICH_VMCR_EL2: break; default: - panic("Gicv3CPUInterface::readMiscReg(): " - "unknown register %d (%s)", - misc_reg, miscRegName[misc_reg]); + panic("Gicv3CPUInterface::readMiscReg(): unknown register %d (%s)", + misc_reg, miscRegName[misc_reg]); } - DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): " - "register %s value %#x\n", miscRegName[misc_reg], value); + DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): register %s value %#x\n", + miscRegName[misc_reg], value); return value; } @@ -797,12 +712,13 @@ void Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) { bool do_virtual_update = false; - DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): " - "register %s value %#x\n", miscRegName[misc_reg], val); + DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): register %s value %#x\n", + miscRegName[misc_reg], val); bool hcr_fmo = getHCREL2FMO(); bool hcr_imo = getHCREL2IMO(); switch (misc_reg) { + // Active Priorities Group 1 Registers case MISCREG_ICC_AP1R0: case MISCREG_ICC_AP1R0_EL1: if ((currEL() == EL1) && !inSecureState() && hcr_imo) { @@ -824,6 +740,7 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) // only implemented if supporting 7 or more bits of priority break; + // Active Priorities Group 0 Registers case MISCREG_ICC_AP0R0: case MISCREG_ICC_AP0R0_EL1: if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { @@ -845,6 +762,7 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) // only implemented if supporting 7 or more bits of priority break; + // End Of Interrupt Register 0 case MISCREG_ICC_EOIR0: case MISCREG_ICC_EOIR0_EL1: { // End Of Interrupt Register 0 if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { @@ -873,6 +791,7 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Virtual End Of Interrupt Register 0 case MISCREG_ICV_EOIR0_EL1: { int int_id = val & 0xffffff; @@ -894,14 +813,14 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) // No LR found matching virtualIncrementEOICount(); } else { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); Gicv3::GroupId lr_group = - lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; - uint8_t lr_group_prio = bits(lr, 55, 48) & 0xf8; + ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; + uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8; if (lr_group == Gicv3::G0S && lr_group_prio == drop_prio) { - //JAIRO if (!virtualIsEOISplitMode()) + //if (!virtualIsEOISplitMode()) { virtualDeactivateIRQ(lr_idx); } @@ -912,8 +831,9 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // End Of Interrupt Register 1 case MISCREG_ICC_EOIR1: - case MISCREG_ICC_EOIR1_EL1: { // End Of Interrupt Register 1 + case MISCREG_ICC_EOIR1_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_imo) { return setMiscReg(MISCREG_ICV_EOIR1_EL1, val); } @@ -925,8 +845,7 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) return; } - Gicv3::GroupId group = - inSecureState() ? Gicv3::G1S : Gicv3::G1NS; + Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS; if (highestActiveGroup() == Gicv3::G0S) { return; @@ -936,7 +855,7 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) if (highestActiveGroup() == Gicv3::G1S && !inSecureState()) { return; } else if (highestActiveGroup() == Gicv3::G1NS && - !(!inSecureState() or (currEL() == EL3))) { + !(!inSecureState() or (currEL() == EL3))) { return; } } @@ -950,12 +869,13 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Virtual End Of Interrupt Register 1 case MISCREG_ICV_EOIR1_EL1: { int int_id = val & 0xffffff; // avoid deactivation for special interrupts if (int_id >= Gicv3::INTID_SECURE && - int_id <= Gicv3::INTID_SPURIOUS) { + int_id <= Gicv3::INTID_SPURIOUS) { return; } @@ -968,14 +888,14 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) int lr_idx = virtualFindActive(int_id); if (lr_idx < 0) { - // No LR found matching + // No matching LR found virtualIncrementEOICount(); } else { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); Gicv3::GroupId lr_group = - lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; - uint8_t lr_group_prio = bits(lr, 55, 48) & 0xf8; + ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; + uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8; if (lr_group == Gicv3::G1NS && lr_group_prio == drop_prio) { if (!virtualIsEOISplitMode()) { @@ -988,28 +908,29 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Deactivate Interrupt Register case MISCREG_ICC_DIR: - case MISCREG_ICC_DIR_EL1: { // Deactivate Interrupt Register + case MISCREG_ICC_DIR_EL1: { if ((currEL() == EL1) && !inSecureState() && - (hcr_imo || hcr_fmo)) { + (hcr_imo || hcr_fmo)) { return setMiscReg(MISCREG_ICV_DIR_EL1, val); } int int_id = val & 0xffffff; - // avoid deactivation for special interrupts + // The following checks are as per spec pseudocode + // aarch64/support/ICC_DIR_EL1 + + // Check for spurious ID if (int_id >= Gicv3::INTID_SECURE) { return; } + // EOI mode is not set, so don't deactivate if (!isEOISplitMode()) { return; } - /* - * Check whether we're allowed to deactivate. - * These checks are correspond to the spec's pseudocode. - */ Gicv3::GroupId group = int_id >= 32 ? distributor->getIntGroup(int_id) : redistributor->getIntGroup(int_id); @@ -1040,12 +961,12 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) case EL1: if (!isSecureBelowEL3()) { if (single_sec_state && irq_is_grp0 && - !route_fiq_to_el3 && !route_fiq_to_el2) { + !route_fiq_to_el3 && !route_fiq_to_el2) { break; } if (!irq_is_secure && !irq_is_grp0 && - !route_irq_to_el3 && !route_irq_to_el2) { + !route_irq_to_el3 && !route_irq_to_el2) { break; } } else { @@ -1054,8 +975,8 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) } if (!irq_is_grp0 && - (!irq_is_secure || !single_sec_state) && - !route_irq_to_el3) { + (!irq_is_secure || !single_sec_state) && + !route_irq_to_el3) { break; } } @@ -1070,12 +991,13 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Deactivate Virtual Interrupt Register case MISCREG_ICV_DIR_EL1: { int int_id = val & 0xffffff; // avoid deactivation for special interrupts if (int_id >= Gicv3::INTID_SECURE && - int_id <= Gicv3::INTID_SPURIOUS) { + int_id <= Gicv3::INTID_SPURIOUS) { return; } @@ -1086,7 +1008,7 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) int lr_idx = virtualFindActive(int_id); if (lr_idx < 0) { - // No LR found matching + // No matching LR found virtualIncrementEOICount(); } else { virtualDeactivateIRQ(lr_idx); @@ -1096,10 +1018,12 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Binary Point Register 0 case MISCREG_ICC_BPR0: - case MISCREG_ICC_BPR0_EL1: // Binary Point Register 0 + case MISCREG_ICC_BPR0_EL1: + // Binary Point Register 1 case MISCREG_ICC_BPR1: - case MISCREG_ICC_BPR1_EL1: { // Binary Point Register 1 + 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); @@ -1115,18 +1039,20 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) group = Gicv3::G1NS; } - if ((group == Gicv3::G1S) && - !isEL3OrMon() && - (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S) & - ICC_CTLR_EL1_CBPR)) { + 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 ((group == Gicv3::G1NS) && - (currEL() < EL3) && - (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS) & - ICC_CTLR_EL1_CBPR)) { - // Reads return BPR0 + 1 saturated to 7, WI + 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) { + // BPR0 + 1 saturated to 7, WI return; } @@ -1141,15 +1067,17 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Virtual Binary Point Register 0 case MISCREG_ICV_BPR0_EL1: + // Virtual Binary Point Register 1 case MISCREG_ICV_BPR1_EL1: { Gicv3::GroupId group = misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS; - RegVal ich_vmcr_el2 = + ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) { - // reads return bpr0 + 1 saturated to 7, writes ignored + if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) { + // BPR0 + 1 saturated to 7, WI return; } @@ -1164,13 +1092,9 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) } if (group == Gicv3::G0S) { - ich_vmcr_el2 = insertBits(ich_vmcr_el2, - ICH_VMCR_EL2_VBPR0_SHIFT + 2, ICH_VMCR_EL2_VBPR0_SHIFT, - val); + ich_vmcr_el2.VBPR0 = val; } else { - ich_vmcr_el2 = insertBits(ich_vmcr_el2, - ICH_VMCR_EL2_VBPR1_SHIFT + 2, ICH_VMCR_EL2_VBPR1_SHIFT, - val); + ich_vmcr_el2.VBPR1 = val; } isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); @@ -1178,124 +1102,185 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Control Register EL1 case MISCREG_ICC_CTLR: - case MISCREG_ICC_CTLR_EL1: { // Control Register - if ((currEL() == EL1) && !inSecureState() && - (hcr_imo || hcr_fmo)) { + case MISCREG_ICC_CTLR_EL1: { + if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { return setMiscReg(MISCREG_ICV_CTLR_EL1, val); } /* + * ExtRange is RO. * RSS is RO. * A3V is RO. * SEIS is RO. * IDbits is RO. * PRIbits is RO. - * If EL3 is implemented and GICD_CTLR.DS == 0, then PMHE is RO. - * So, only CBPR[0] and EOIMODE[1] are RW. - * If EL3 is implemented and GICD_CTLR.DS == 0, then CBPR is RO. */ - uint64_t mask; - - if (haveEL(EL3) and distributor->DS == 0) { - mask = ICC_CTLR_EL1_EOIMODE; - } else if (haveEL(EL3) and distributor->DS == 1) { - mask = ICC_CTLR_EL1_PMHE | ICC_CTLR_EL1_CBPR | - ICC_CTLR_EL1_EOIMODE; - } else { - mask = ICC_CTLR_EL1_CBPR | ICC_CTLR_EL1_EOIMODE; - } - - RegVal old_val = + ICC_CTLR_EL1 requested_icc_ctlr_el1 = val; + ICC_CTLR_EL1 icc_ctlr_el1 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1); - old_val &= ~mask; - val = old_val | (val & mask); - break; - } - case MISCREG_ICV_CTLR_EL1: { - RegVal ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - ich_vmcr_el2 = insertBits(ich_vmcr_el2, ICH_VMCR_EL2_VCBPR_SHIFT, - val & ICC_CTLR_EL1_CBPR ? 1 : 0); - ich_vmcr_el2 = insertBits(ich_vmcr_el2, ICH_VMCR_EL2_VEOIM_SHIFT, - val & ICC_CTLR_EL1_EOIMODE ? 1 : 0); - isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); - do_virtual_update = true; - break; - } + ICC_CTLR_EL3 icc_ctlr_el3 = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); - case MISCREG_ICC_MCTLR: - case MISCREG_ICC_CTLR_EL3: { - RegVal icc_ctlr_el1_s = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); - RegVal icc_ctlr_el1_ns = - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); + // The following could be refactored but it is following + // spec description section 9.2.6 point by point. - // ICC_CTLR_EL1(NS).EOImode is an alias of - // ICC_CTLR_EL3.EOImode_EL1NS - if (val & ICC_CTLR_EL3_EOIMODE_EL1NS) { - icc_ctlr_el1_ns |= ICC_CTLR_EL1_EOIMODE; - } else { - icc_ctlr_el1_ns &= ~ICC_CTLR_EL1_EOIMODE; - } + // PMHE + if (haveEL(EL3)) { + // PMHE is alias of ICC_CTLR_EL3.PMHE - // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS - if (val & ICC_CTLR_EL3_CBPR_EL1NS) { - icc_ctlr_el1_ns |= ICC_CTLR_EL1_CBPR; + if (distributor->DS == 0) { + // PMHE is RO + } else if (distributor->DS == 1) { + // PMHE is RW + icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE; + icc_ctlr_el3.PMHE = icc_ctlr_el1.PMHE; + } } else { - icc_ctlr_el1_ns &= ~ICC_CTLR_EL1_CBPR; + // PMHE is RW (by implementation choice) + icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE; } - // ICC_CTLR_EL1(S).EOImode is an alias of ICC_CTLR_EL3.EOImode_EL1S - if (val & ICC_CTLR_EL3_EOIMODE_EL1S) { - icc_ctlr_el1_s |= ICC_CTLR_EL1_EOIMODE; + // EOImode + icc_ctlr_el1.EOImode = requested_icc_ctlr_el1.EOImode; + + if (inSecureState()) { + // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1S + icc_ctlr_el3.EOImode_EL1S = icc_ctlr_el1.EOImode; } else { - icc_ctlr_el1_s &= ~ICC_CTLR_EL1_EOIMODE; + // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1NS + icc_ctlr_el3.EOImode_EL1NS = icc_ctlr_el1.EOImode; } - // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S - if (val & ICC_CTLR_EL3_CBPR_EL1S) { - icc_ctlr_el1_s |= ICC_CTLR_EL1_CBPR; + // CBPR + if (haveEL(EL3)) { + // CBPR is alias of ICC_CTLR_EL3.CBPR_EL1{S,NS} + + if (distributor->DS == 0) { + // CBPR is RO + } else { + // CBPR is RW + icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR; + + if (inSecureState()) { + icc_ctlr_el3.CBPR_EL1S = icc_ctlr_el1.CBPR; + } else { + icc_ctlr_el3.CBPR_EL1NS = icc_ctlr_el1.CBPR; + } + } } else { - icc_ctlr_el1_s &= ~ICC_CTLR_EL1_CBPR; + // CBPR is RW + icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR; } - isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s); - isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS, icc_ctlr_el1_ns); - // Only ICC_CTLR_EL3_EOIMODE_EL3 is writable - RegVal old_icc_ctlr_el3 = + isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL3, icc_ctlr_el3); + + val = icc_ctlr_el1; + break; + } + + // Virtual Control Register + case MISCREG_ICV_CTLR_EL1: { + ICV_CTLR_EL1 requested_icv_ctlr_el1 = val; + ICV_CTLR_EL1 icv_ctlr_el1 = + isa->readMiscRegNoEffect(MISCREG_ICV_CTLR_EL1); + icv_ctlr_el1.EOImode = requested_icv_ctlr_el1.EOImode; + icv_ctlr_el1.CBPR = requested_icv_ctlr_el1.CBPR; + val = icv_ctlr_el1; + + // Aliases + // ICV_CTLR_EL1.CBPR aliases ICH_VMCR_EL2.VCBPR. + // ICV_CTLR_EL1.EOImode aliases ICH_VMCR_EL2.VEOIM. + ICH_VMCR_EL2 ich_vmcr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); + ich_vmcr_el2.VCBPR = icv_ctlr_el1.CBPR; + ich_vmcr_el2.VEOIM = icv_ctlr_el1.EOImode; + isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); + break; + } + + // Control Register EL3 + case MISCREG_ICC_MCTLR: + case MISCREG_ICC_CTLR_EL3: { + /* + * ExtRange is RO. + * RSS is RO. + * nDS is RO. + * A3V is RO. + * SEIS is RO. + * IDbits is RO. + * PRIbits is RO. + * PMHE is RAO/WI, priority-based routing is always used. + */ + ICC_CTLR_EL3 requested_icc_ctlr_el3 = val; + + // Aliases + if (haveEL(EL3)) + { + ICC_CTLR_EL1 icc_ctlr_el1_s = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); + ICC_CTLR_EL1 icc_ctlr_el1_ns = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); + + // ICC_CTLR_EL1(NS).EOImode is an alias of + // ICC_CTLR_EL3.EOImode_EL1NS + icc_ctlr_el1_ns.EOImode = requested_icc_ctlr_el3.EOImode_EL1NS; + // ICC_CTLR_EL1(S).EOImode is an alias of + // ICC_CTLR_EL3.EOImode_EL1S + icc_ctlr_el1_s.EOImode = requested_icc_ctlr_el3.EOImode_EL1S; + // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS + icc_ctlr_el1_ns.CBPR = requested_icc_ctlr_el3.CBPR_EL1NS; + // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S + icc_ctlr_el1_s.CBPR = requested_icc_ctlr_el3.CBPR_EL1S; + + isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s); + isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS, + icc_ctlr_el1_ns); + } + + ICC_CTLR_EL3 icc_ctlr_el3 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); - old_icc_ctlr_el3 &= ~(ICC_CTLR_EL3_EOIMODE_EL3 | ICC_CTLR_EL3_RM); - val = old_icc_ctlr_el3 | - (val & (ICC_CTLR_EL3_EOIMODE_EL3 | ICC_CTLR_EL3_RM)); + + icc_ctlr_el3.RM = requested_icc_ctlr_el3.RM; + icc_ctlr_el3.EOImode_EL1NS = requested_icc_ctlr_el3.EOImode_EL1NS; + icc_ctlr_el3.EOImode_EL1S = requested_icc_ctlr_el3.EOImode_EL1S; + icc_ctlr_el3.EOImode_EL3 = requested_icc_ctlr_el3.EOImode_EL3; + icc_ctlr_el3.CBPR_EL1NS = requested_icc_ctlr_el3.CBPR_EL1NS; + icc_ctlr_el3.CBPR_EL1S = requested_icc_ctlr_el3.CBPR_EL1S; + + val = icc_ctlr_el3; break; } + // Priority Mask Register case MISCREG_ICC_PMR: - case MISCREG_ICC_PMR_EL1: { // Priority Mask Register - if ((currEL() == EL1) && !inSecureState() && - (hcr_imo || hcr_fmo)) { - return setMiscReg(MISCREG_ICV_PMR_EL1, val); + case MISCREG_ICC_PMR_EL1: { + if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { + return isa->setMiscRegNoEffect(MISCREG_ICV_PMR_EL1, val); } val &= 0xff; SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); if (haveEL(EL3) && !inSecureState() && (scr_el3.fiq)) { - /* - * NS access and Group 0 is inaccessible to NS: return the - * NS view of the current priority - */ + // Spec section 4.8.1 + // For Non-secure access to ICC_PMR_EL1 SCR_EL3.FIQ == 1: RegVal old_icc_pmr_el1 = isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1); if (!(old_icc_pmr_el1 & 0x80)) { - /* Current PMR in the secure range, don't allow NS to - * change it */ + // If the current priority mask value is in the range of + // 0x00-0x7F then WI return; } + // If the current priority mask value is in the range of + // 0x80-0xFF then a write access to ICC_PMR_EL1 succeeds, + // based on the Non-secure read of the priority mask value + // written to the register. + val = (val >> 1) | 0x80; } @@ -1303,21 +1288,9 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } - case MISCREG_ICV_PMR_EL1: { // Priority Mask Register - RegVal ich_vmcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - ich_vmcr_el2 = insertBits( - ich_vmcr_el2, - ICH_VMCR_EL2_VPMR_SHIFT + ICH_VMCR_EL2_VPMR_LENGTH - 1, - ICH_VMCR_EL2_VPMR_SHIFT, val); - - isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); - virtualUpdate(); - return; - } - + // Interrupt Group 0 Enable Register EL1 case MISCREG_ICC_IGRPEN0: - case MISCREG_ICC_IGRPEN0_EL1: { // Interrupt Group 0 Enable Register + case MISCREG_ICC_IGRPEN0_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { return setMiscReg(MISCREG_ICV_IGRPEN0_EL1, val); } @@ -1325,57 +1298,83 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // Virtual Interrupt Group 0 Enable register case MISCREG_ICV_IGRPEN0_EL1: { bool enable = val & 0x1; - RegVal ich_vmcr_el2 = + ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - ich_vmcr_el2 = insertBits(ich_vmcr_el2, - ICH_VMCR_EL2_VENG0_SHIFT, enable); + ich_vmcr_el2.VENG0 = enable; isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); virtualUpdate(); return; } + // Interrupt Group 1 Enable register EL1 case MISCREG_ICC_IGRPEN1: - case MISCREG_ICC_IGRPEN1_EL1: { // Interrupt Group 1 Enable Register + case MISCREG_ICC_IGRPEN1_EL1: { if ((currEL() == EL1) && !inSecureState() && hcr_imo) { return setMiscReg(MISCREG_ICV_IGRPEN1_EL1, val); } + if (haveEL(EL3)) { + ICC_IGRPEN1_EL1 icc_igrpen1_el1 = val; + ICC_IGRPEN1_EL3 icc_igrpen1_el3 = + isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3); + + if (inSecureState()) { + // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1S + icc_igrpen1_el3.EnableGrp1S = icc_igrpen1_el1.Enable; + } else { + // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1NS + icc_igrpen1_el3.EnableGrp1NS = icc_igrpen1_el1.Enable; + } + + isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3, + icc_igrpen1_el3); + } + break; } + // Virtual Interrupt Group 1 Enable register case MISCREG_ICV_IGRPEN1_EL1: { bool enable = val & 0x1; - RegVal ich_vmcr_el2 = + ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - ich_vmcr_el2 = insertBits(ich_vmcr_el2, - ICH_VMCR_EL2_VENG1_SHIFT, enable); + ich_vmcr_el2.VENG1 = enable; isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); virtualUpdate(); return; } + // Interrupt Group 1 Enable register case MISCREG_ICC_MGRPEN1: case MISCREG_ICC_IGRPEN1_EL3: { - // EnableGrp1S and EnableGrp1NS are aliased with - // ICC_IGRPEN1_EL1_S.Enable and ICC_IGRPEN1_EL1_NS.Enable - bool enable_grp_1s = val & ICC_IGRPEN1_EL3_ENABLEGRP1S; - bool enable_grp_1ns = val & ICC_IGRPEN1_EL3_ENABLEGRP1NS; - isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S, enable_grp_1s); - isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS, enable_grp_1ns); - return; + ICC_IGRPEN1_EL3 icc_igrpen1_el3 = val; + ICC_IGRPEN1_EL1 icc_igrpen1_el1 = + isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1); + + if (inSecureState()) { + // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1S + icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1S; + } else { + // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1NS + icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1NS; + } + + isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1, icc_igrpen1_el1); + break; } - // Software Generated Interrupt Group 0 Register + // Software Generated Interrupt Group 0 Register case MISCREG_ICC_SGI0R: case MISCREG_ICC_SGI0R_EL1: - // Software Generated Interrupt Group 1 Register + // Software Generated Interrupt Group 1 Register case MISCREG_ICC_SGI1R: case MISCREG_ICC_SGI1R_EL1: - // Alias Software Generated Interrupt Group 1 Register + // Alias Software Generated Interrupt Group 1 Register case MISCREG_ICC_ASGI1R: case MISCREG_ICC_ASGI1R_EL1: { bool ns = !inSecureState(); @@ -1416,14 +1415,14 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) // Interrupts routed to the PEs specified by // Aff3.Aff2.Aff1. if ((affinity_i >> 8) != - ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) { + ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) { continue; } uint8_t aff0_i = bits(affinity_i, 7, 0); if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 && - ((0x1 << (aff0_i - rs * 16)) & target_list))) { + ((0x1 << (aff0_i - rs * 16)) & target_list))) { continue; } } @@ -1434,72 +1433,89 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // System Register Enable Register EL1 case MISCREG_ICC_SRE: - case MISCREG_ICC_SRE_EL1: { // System Register Enable Register EL1 - if (!(val & ICC_SRE_EL1_SRE)) { - warn("Gicv3CPUInterface::setMiscReg(): " - "ICC_SRE_EL*.SRE is RAO/WI, legacy not supported!\n"); - } - - bool dfb = val & ICC_SRE_EL1_DFB; - bool dib = val & ICC_SRE_EL1_DIB; - - if (haveEL(EL3) && !distributor->DS) { - // DIB is RO alias of ICC_SRE_EL3.DIB - // DFB is RO alias of ICC_SRE_EL3.DFB - } else if (haveEL(EL3) && distributor->DS) { - // DIB is RW alias of ICC_SRE_EL3.DIB - // DFB is RW alias of ICC_SRE_EL3.DFB - RegVal icc_sre_el3 = - isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3); - icc_sre_el3 = insertBits(icc_sre_el3, ICC_SRE_EL3_DFB, dfb); - icc_sre_el3 = insertBits(icc_sre_el3, ICC_SRE_EL3_DIB, dib); - isa->setMiscRegNoEffect(MISCREG_ICC_SRE_EL3, icc_sre_el3); - } else if ((!haveEL(EL3) || distributor->DS) and haveEL(EL2)) { - // DIB is RO alias of ICC_SRE_EL2.DIB - // DFB is RO alias of ICC_SRE_EL2.DFB - } else { - isa->setMiscRegNoEffect(misc_reg, val); - } - - return; - } - + case MISCREG_ICC_SRE_EL1: + // System Register Enable Register EL2 case MISCREG_ICC_HSRE: - case MISCREG_ICC_SRE_EL2: // System Register Enable Register EL2 + case MISCREG_ICC_SRE_EL2: + // System Register Enable Register EL3 case MISCREG_ICC_MSRE: - case MISCREG_ICC_SRE_EL3: // System Register Enable Register EL3 - if (!(val & (1 << 0))) { - warn("Gicv3CPUInterface::setMiscReg(): " - "ICC_SRE_EL*.SRE is RAO/WI, legacy not supported!\n"); - } - + case MISCREG_ICC_SRE_EL3: // All bits are RAO/WI - break; + return; + // Hyp Control Register case MISCREG_ICH_HCR: - case MISCREG_ICH_HCR_EL2: - val &= ICH_HCR_EL2_EN | ICH_HCR_EL2_UIE | ICH_HCR_EL2_LRENPIE | - ICH_HCR_EL2_NPIE | ICH_HCR_EL2_VGRP0EIE | - ICH_HCR_EL2_VGRP0DIE | ICH_HCR_EL2_VGRP1EIE | - ICH_HCR_EL2_VGRP1DIE | ICH_HCR_EL2_TC | ICH_HCR_EL2_TALL0 | - ICH_HCR_EL2_TALL1 | ICH_HCR_EL2_TDIR | - ICH_HCR_EL2_EOICOUNT_MASK; + case MISCREG_ICH_HCR_EL2: { + ICH_HCR_EL2 requested_ich_hcr_el2 = val; + ICH_HCR_EL2 ich_hcr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); + + if (requested_ich_hcr_el2.EOIcount >= ich_hcr_el2.EOIcount) + { + // EOIcount - Permitted behaviors are: + // - Increment EOIcount. + // - Leave EOIcount unchanged. + ich_hcr_el2.EOIcount = requested_ich_hcr_el2.EOIcount; + } + + ich_hcr_el2.TDIR = requested_ich_hcr_el2.TDIR; + ich_hcr_el2.TSEI = requested_ich_hcr_el2.TSEI; + ich_hcr_el2.TALL1 = requested_ich_hcr_el2.TALL1;; + ich_hcr_el2.TALL0 = requested_ich_hcr_el2.TALL0;; + ich_hcr_el2.TC = requested_ich_hcr_el2.TC; + ich_hcr_el2.VGrp1DIE = requested_ich_hcr_el2.VGrp1DIE; + ich_hcr_el2.VGrp1EIE = requested_ich_hcr_el2.VGrp1EIE; + ich_hcr_el2.VGrp0DIE = requested_ich_hcr_el2.VGrp0DIE; + ich_hcr_el2.VGrp0EIE = requested_ich_hcr_el2.VGrp0EIE; + ich_hcr_el2.NPIE = requested_ich_hcr_el2.NPIE; + ich_hcr_el2.LRENPIE = requested_ich_hcr_el2.LRENPIE; + ich_hcr_el2.UIE = requested_ich_hcr_el2.UIE; + ich_hcr_el2.En = requested_ich_hcr_el2.En; + val = ich_hcr_el2; do_virtual_update = true; break; + } - case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: + // List Registers + case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: { // AArch32 (maps to AArch64 MISCREG_ICH_LR_EL2 high half part) - { - // Enforce RES0 bits in priority field, 5 of 8 bits used - val = insertBits(val, ICH_LRC_PRIORITY_SHIFT + 2, - ICH_LRC_PRIORITY_SHIFT, 0); - RegVal old_val = isa->readMiscRegNoEffect(misc_reg); - val = (old_val & 0xffffffff) | (val << 32); - do_virtual_update = true; - break; + ICH_LRC requested_ich_lrc = val; + ICH_LRC ich_lrc = isa->readMiscRegNoEffect(misc_reg); + + ich_lrc.State = requested_ich_lrc.State; + ich_lrc.HW = requested_ich_lrc.HW; + ich_lrc.Group = requested_ich_lrc.Group; + + // Priority, bits [23:16] + // At least five bits must be implemented. + // Unimplemented bits are RES0 and start from bit[16] up to bit[18]. + // We implement 5 bits. + ich_lrc.Priority = (requested_ich_lrc.Priority & 0xf8) | + (ich_lrc.Priority & 0x07); + + // pINTID, bits [12:0] + // When ICH_LR.HW is 0 this field has the following meaning: + // - Bits[12:10] : RES0. + // - Bit[9] : EOI. + // - Bits[8:0] : RES0. + // When ICH_LR.HW is 1: + // - This field is only required to implement enough bits to hold a + // valid value for the implemented INTID size. Any unused higher + // order bits are RES0. + if (requested_ich_lrc.HW == 0) { + ich_lrc.EOI = requested_ich_lrc.EOI; + } else { + ich_lrc.pINTID = requested_ich_lrc.pINTID; } + val = ich_lrc; + do_virtual_update = true; + break; + } + + // List Registers case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: { // AArch32 (maps to AArch64 MISCREG_ICH_LR_EL2 low half part) RegVal old_val = isa->readMiscRegNoEffect(misc_reg); @@ -1508,45 +1524,90 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) break; } + // List Registers case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: { // AArch64 - // Enforce RES0 bits in priority field, 5 of 8 bits used - val = insertBits(val, ICH_LR_EL2_PRIORITY_SHIFT + 2, - ICH_LR_EL2_PRIORITY_SHIFT, 0); + ICH_LR_EL2 requested_ich_lr_el2 = val; + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(misc_reg); + + ich_lr_el2.State = requested_ich_lr_el2.State; + ich_lr_el2.HW = requested_ich_lr_el2.HW; + ich_lr_el2.Group = requested_ich_lr_el2.Group; + + // Priority, bits [55:48] + // At least five bits must be implemented. + // Unimplemented bits are RES0 and start from bit[48] up to bit[50]. + // We implement 5 bits. + ich_lr_el2.Priority = (requested_ich_lr_el2.Priority & 0xf8) | + (ich_lr_el2.Priority & 0x07); + + // pINTID, bits [44:32] + // When ICH_LR_EL2.HW is 0 this field has the following meaning: + // - Bits[44:42] : RES0. + // - Bit[41] : EOI. + // - Bits[40:32] : RES0. + // When ICH_LR_EL2.HW is 1: + // - This field is only required to implement enough bits to hold a + // valid value for the implemented INTID size. Any unused higher + // order bits are RES0. + if (requested_ich_lr_el2.HW == 0) { + ich_lr_el2.EOI = requested_ich_lr_el2.EOI; + } else { + ich_lr_el2.pINTID = requested_ich_lr_el2.pINTID; + } + + // vINTID, bits [31:0] + // It is IMPLEMENTATION DEFINED how many bits are implemented, + // though at least 16 bits must be implemented. + // Unimplemented bits are RES0. + ich_lr_el2.vINTID = requested_ich_lr_el2.vINTID; + + val = ich_lr_el2; do_virtual_update = true; break; } + // Virtual Machine Control Register case MISCREG_ICH_VMCR: case MISCREG_ICH_VMCR_EL2: { - val &= ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1 | - ICH_VMCR_EL2_VCBPR | ICH_VMCR_EL2_VEOIM | - ICH_VMCR_EL2_VBPR1_MASK | ICH_VMCR_EL2_VBPR0_MASK | - ICH_VMCR_EL2_VPMR_MASK; - val |= ICH_VMCR_EL2_VFIQEN; // RES1 - // Check VBPRs against minimun allowed value - uint8_t vbpr0 = bits(val, 23, 21); - uint8_t vbpr1 = bits(val, 20, 18); + ICH_VMCR_EL2 requested_ich_vmcr_el2 = val; + ICH_VMCR_EL2 ich_vmcr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); + ich_vmcr_el2.VPMR = requested_ich_vmcr_el2.VPMR; uint8_t min_vpr0 = 7 - VIRTUAL_PREEMPTION_BITS; + + if (requested_ich_vmcr_el2.VBPR0 < min_vpr0) { + ich_vmcr_el2.VBPR0 = min_vpr0; + } else { + ich_vmcr_el2.VBPR0 = requested_ich_vmcr_el2.VBPR0; + } + uint8_t min_vpr1 = min_vpr0 + 1; - vbpr0 = vbpr0 < min_vpr0 ? min_vpr0 : vbpr0; - vbpr1 = vbpr1 < min_vpr1 ? min_vpr1 : vbpr1; - val = insertBits(val, ICH_VMCR_EL2_VBPR0_SHIFT + 2, - ICH_VMCR_EL2_VBPR0_SHIFT, vbpr0); - val = insertBits(val, ICH_VMCR_EL2_VBPR1_SHIFT + 2, - ICH_VMCR_EL2_VBPR1_SHIFT, vbpr1); + + if (requested_ich_vmcr_el2.VBPR1 < min_vpr1) { + ich_vmcr_el2.VBPR1 = min_vpr1; + } else { + ich_vmcr_el2.VBPR1 = requested_ich_vmcr_el2.VBPR1; + } + + ich_vmcr_el2.VEOIM = requested_ich_vmcr_el2.VEOIM; + ich_vmcr_el2.VCBPR = requested_ich_vmcr_el2.VCBPR; + ich_vmcr_el2.VENG1 = requested_ich_vmcr_el2.VENG1; + ich_vmcr_el2.VENG0 = requested_ich_vmcr_el2.VENG0; + val = ich_vmcr_el2; break; } + // Hyp Active Priorities Group 0 Registers case MISCREG_ICH_AP0R0 ... MISCREG_ICH_AP0R3: case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_AP0R3_EL2: + // Hyp Active Priorities Group 1 Registers case MISCREG_ICH_AP1R0 ... MISCREG_ICH_AP1R3: case MISCREG_ICH_AP1R0_EL2 ... MISCREG_ICH_AP1R3_EL2: break; default: - panic("Gicv3CPUInterface::setMiscReg(): " - "unknown register %d (%s)", - misc_reg, miscRegName[misc_reg]); + panic("Gicv3CPUInterface::setMiscReg(): unknown register %d (%s)", + misc_reg, miscRegName[misc_reg]); } isa->setMiscRegNoEffect(misc_reg, val); @@ -1557,14 +1618,15 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) } int -Gicv3CPUInterface::virtualFindActive(uint32_t int_id) +Gicv3CPUInterface::virtualFindActive(uint32_t int_id) const { for (uint32_t lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { - RegVal lr = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - uint32_t lr_intid = bits(lr, 31, 0); - if ((lr & ICH_LR_EL2_STATE_ACTIVE_BIT) && lr_intid == int_id) { + if (((ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE) || + (ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE_PENDING)) && + (ich_lr_el2.vINTID == int_id)) { return lr_idx; } } @@ -1573,7 +1635,7 @@ Gicv3CPUInterface::virtualFindActive(uint32_t int_id) } uint32_t -Gicv3CPUInterface::getHPPIR0() +Gicv3CPUInterface::getHPPIR0() const { if (hppi.prio == 0xff) { return Gicv3::INTID_SPURIOUS; @@ -1582,9 +1644,7 @@ Gicv3CPUInterface::getHPPIR0() bool irq_is_secure = !distributor->DS && hppi.group != Gicv3::G1NS; if ((hppi.group != Gicv3::G0S) && isEL3OrMon()) { - /* Indicate to EL3 that there's a Group 1 interrupt for the - * other state pending. - */ + // interrupt for the other state pending return irq_is_secure ? Gicv3::INTID_SECURE : Gicv3::INTID_NONSECURE; } @@ -1601,15 +1661,14 @@ Gicv3CPUInterface::getHPPIR0() } uint32_t -Gicv3CPUInterface::getHPPIR1() +Gicv3CPUInterface::getHPPIR1() const { if (hppi.prio == 0xff) { return Gicv3::INTID_SPURIOUS; } - //if ((currEL() == EL3) && ICC_CTLR_EL3_RM) - if ((currEL() == EL3) && - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3) & ICC_CTLR_EL3_RM) { + ICC_CTLR_EL3 icc_ctlr_el3 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); + if ((currEL() == EL3) && icc_ctlr_el3.RM) { if (hppi.group == Gicv3::G0S) { return Gicv3::INTID_SECURE; } else if (hppi.group == Gicv3::G1NS) { @@ -1646,7 +1705,6 @@ Gicv3CPUInterface::dropPriority(Gicv3::GroupId group) apr = isa->readMiscRegNoEffect(apr_misc_reg); if (apr) { - /* Clear the lowest set bit */ apr &= apr - 1; isa->setMiscRegNoEffect(apr_misc_reg, apr); } @@ -1657,14 +1715,6 @@ Gicv3CPUInterface::dropPriority(Gicv3::GroupId group) uint8_t Gicv3CPUInterface::virtualDropPriority() { - /* Drop the priority of the currently active virtual interrupt - * (favouring group 0 if there is a set active bit at - * the same priority for both group 0 and group 1). - * Return the priority value for the bit we just cleared, - * or 0xff if no bits were set in the AP registers at all. - * Note that though the ich_apr[] are uint64_t only the low - * 32 bits are actually relevant. - */ int apr_max = 1 << (VIRTUAL_PREEMPTION_BITS - 5); for (int i = 0; i < apr_max; i++) { @@ -1679,12 +1729,10 @@ Gicv3CPUInterface::virtualDropPriority() int vapr1_count = ctz32(vapr1); if (vapr0_count <= vapr1_count) { - /* Clear the lowest set bit */ vapr0 &= vapr0 - 1; isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0); return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1); } else { - /* Clear the lowest set bit */ vapr1 &= vapr1 - 1; isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1); return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1); @@ -1723,10 +1771,10 @@ void Gicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx) { // Update active priority registers. - RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + + ICH_LR_EL2 ich_lr_el = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; - uint8_t prio = bits(lr, 55, 48) & 0xf8; + Gicv3::GroupId group = ich_lr_el.Group ? Gicv3::G1NS : Gicv3::G0S; + uint8_t prio = ich_lr_el.Priority & 0xf8; int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS); int reg_no = apr_bit / 32; int reg_bit = apr_bit % 32; @@ -1736,9 +1784,8 @@ Gicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx) apr |= (1 << reg_bit); isa->setMiscRegNoEffect(apr_idx, apr); // Move interrupt state from pending to active. - lr &= ~ICH_LR_EL2_STATE_PENDING_BIT; - lr |= ICH_LR_EL2_STATE_ACTIVE_BIT; - isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr); + ich_lr_el.State = ICH_LR_EL2_STATE_ACTIVE; + isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el); } void @@ -1760,55 +1807,38 @@ Gicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group) void Gicv3CPUInterface::virtualDeactivateIRQ(int lr_idx) { - RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - if (lr & ICH_LR_EL2_HW) { + if (ich_lr_el2.HW) { // Deactivate the associated physical interrupt - int pintid = bits(lr, 41, 32); - - if (pintid < Gicv3::INTID_SECURE) { - Gicv3::GroupId group = - pintid >= 32 ? distributor->getIntGroup(pintid) : - redistributor->getIntGroup(pintid); - deactivateIRQ(pintid, group); + if (ich_lr_el2.pINTID < Gicv3::INTID_SECURE) { + Gicv3::GroupId group = ich_lr_el2.pINTID >= 32 ? + distributor->getIntGroup(ich_lr_el2.pINTID) : + redistributor->getIntGroup(ich_lr_el2.pINTID); + deactivateIRQ(ich_lr_el2.pINTID, group); } } // Remove the active bit - lr &= ~ICH_LR_EL2_STATE_ACTIVE_BIT; - isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr); + ich_lr_el2.State = ich_lr_el2.State & ~ICH_LR_EL2_STATE_ACTIVE; + isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el2); } /* - * Return a mask word which clears the subpriority bits from - * a priority value for an interrupt in the specified group. - * This depends on the BPR value. For CBPR0 (S or NS): - * a BPR of 0 means the group priority bits are [7:1]; - * a BPR of 1 means they are [7:2], and so on down to - * ... - * a BPR of 7 meaning no group priority bits at all. - * For CBPR1 NS: - * a BPR of 0 is impossible (the minimum value is 1) - * a BPR of 1 means the group priority bits are [7:1]; - * a BPR of 2 means they are [7:2], and so on down to - * ... - * a BPR of 7 meaning the group priority is [7]. - * - * Which BPR to use depends on the group of the interrupt and - * the current ICC_CTLR.CBPR settings. - * - * This corresponds to the GroupBits() pseudocode from 4.8.2. + * Returns the priority group field for the current BPR value for the group. + * GroupBits() Pseudocode from spec. */ uint32_t -Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) +Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) const { - if ((group == Gicv3::G1S && - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S) - & ICC_CTLR_EL1_CBPR) || - (group == Gicv3::G1NS && - isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS) - & ICC_CTLR_EL1_CBPR)) { + ICC_CTLR_EL1 icc_ctlr_el1_s = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); + ICC_CTLR_EL1 icc_ctlr_el1_ns = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); + + if ((group == Gicv3::G1S && icc_ctlr_el1_s.CBPR) || + (group == Gicv3::G1NS && icc_ctlr_el1_ns.CBPR)) { group = Gicv3::G0S; } @@ -1829,21 +1859,21 @@ Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) } uint32_t -Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) +Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) const { - RegVal ich_vmcr_el2 = + ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) { + if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) { group = Gicv3::G0S; } int bpr; if (group == Gicv3::G0S) { - bpr = bits(ich_vmcr_el2, 23, 21); + bpr = ich_vmcr_el2.VBPR0; } else { - bpr = bits(ich_vmcr_el2, 20, 18); + bpr = ich_vmcr_el2.VBPR1; } if (group == Gicv3::G1NS) { @@ -1855,26 +1885,28 @@ Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) } bool -Gicv3CPUInterface::isEOISplitMode() +Gicv3CPUInterface::isEOISplitMode() const { if (isEL3OrMon()) { - return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3) & - ICC_CTLR_EL3_EOIMODE_EL3; + ICC_CTLR_EL3 icc_ctlr_el3 = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); + return icc_ctlr_el3.EOImode_EL3; } else { - return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1) & - ICC_CTLR_EL1_EOIMODE; + ICC_CTLR_EL1 icc_ctlr_el1 = + isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1); + return icc_ctlr_el1.EOImode; } } bool -Gicv3CPUInterface::virtualIsEOISplitMode() +Gicv3CPUInterface::virtualIsEOISplitMode() const { - RegVal ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - return ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM; + ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); + return ich_vmcr_el2.VEOIM; } int -Gicv3CPUInterface::highestActiveGroup() +Gicv3CPUInterface::highestActiveGroup() const { int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1)); int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S)); @@ -1937,11 +1969,11 @@ Gicv3CPUInterface::virtualUpdate() int lr_idx = getHPPVILR(); if (lr_idx >= 0) { - RegVal ich_lr_el2 = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); if (hppviCanPreempt(lr_idx)) { - if (ich_lr_el2 & ICH_LR_EL2_GROUP) { + if (ich_lr_el2.Group) { signal_IRQ = true; } else { signal_FIQ = true; @@ -1949,9 +1981,9 @@ Gicv3CPUInterface::virtualUpdate() } } - RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); + ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); - if (ich_hcr_el2 & ICH_HCR_EL2_EN) { + if (ich_hcr_el2.En) { if (maintenanceInterruptStatus()) { redistributor->sendPPInt(25); } @@ -1974,14 +2006,14 @@ Gicv3CPUInterface::virtualUpdate() } } -// Returns the intex of the LR with the HPPI +// Returns the index of the LR with the HPPI int -Gicv3CPUInterface::getHPPVILR() +Gicv3CPUInterface::getHPPVILR() const { int idx = -1; - RegVal ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); + ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); - if (!(ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) { + if (!ich_vmcr_el2.VENG0 && !ich_vmcr_el2.VENG1) { // VG0 and VG1 disabled... return idx; } @@ -1989,27 +2021,26 @@ Gicv3CPUInterface::getHPPVILR() uint8_t highest_prio = 0xff; for (int i = 0; i < 16; i++) { - RegVal ich_lri_el2 = + ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i); - uint8_t state = bits(ich_lri_el2, 63, 62); - if (state != Gicv3::INT_PENDING) { + if (ich_lr_el2.State != Gicv3::INT_PENDING) { continue; } - if (ich_lri_el2 & ICH_LR_EL2_GROUP) { + if (ich_lr_el2.Group) { // VG1 - if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { + if (!ich_vmcr_el2.VENG1) { continue; } } else { // VG0 - if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) { + if (!ich_vmcr_el2.VENG0) { continue; } } - uint8_t prio = bits(ich_lri_el2, 55, 48); + uint8_t prio = ich_lr_el2.Priority; if (prio < highest_prio) { highest_prio = prio; @@ -2021,16 +2052,17 @@ Gicv3CPUInterface::getHPPVILR() } bool -Gicv3CPUInterface::hppviCanPreempt(int lr_idx) +Gicv3CPUInterface::hppviCanPreempt(int lr_idx) const { - RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - - if (!(isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2) & ICH_HCR_EL2_EN)) { + ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); + if (!ich_hcr_el2.En) { // virtual interface is disabled return false; } - uint8_t prio = bits(lr, 55, 48); + ICH_LR_EL2 ich_lr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); + uint8_t prio = ich_lr_el2.Priority; uint8_t vpmr = bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24); @@ -2045,7 +2077,7 @@ Gicv3CPUInterface::hppviCanPreempt(int lr_idx) return true; } - Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; + Gicv3::GroupId group = ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; uint32_t prio_mask = virtualGroupPriorityMask(group); if ((prio & prio_mask) < (rprio & prio_mask)) { @@ -2056,7 +2088,7 @@ Gicv3CPUInterface::hppviCanPreempt(int lr_idx) } uint8_t -Gicv3CPUInterface::virtualHighestActivePriority() +Gicv3CPUInterface::virtualHighestActivePriority() const { uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5); @@ -2087,12 +2119,9 @@ Gicv3CPUInterface::virtualIncrementEOICount() isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2); } -/* - * Should we signal the interrupt as IRQ or FIQ? - * see spec section 4.6.2 - */ +// spec section 4.6.2 ArmISA::InterruptTypes -Gicv3CPUInterface::intSignalType(Gicv3::GroupId group) +Gicv3CPUInterface::intSignalType(Gicv3::GroupId group) const { bool is_fiq = false; @@ -2122,7 +2151,7 @@ Gicv3CPUInterface::intSignalType(Gicv3::GroupId group) } bool -Gicv3CPUInterface::hppiCanPreempt() +Gicv3CPUInterface::hppiCanPreempt() const { if (hppi.prio == 0xff) { // there is no pending interrupt @@ -2155,7 +2184,7 @@ Gicv3CPUInterface::hppiCanPreempt() } uint8_t -Gicv3CPUInterface::highestActivePriority() +Gicv3CPUInterface::highestActivePriority() const { uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) | isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) | @@ -2170,29 +2199,26 @@ Gicv3CPUInterface::highestActivePriority() } bool -Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group) +Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group) const { switch (group) { - case Gicv3::G0S: - return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1) & - ICC_IGRPEN0_EL1_ENABLE; + case Gicv3::G0S: { + ICC_IGRPEN0_EL1 icc_igrpen0_el1 = + isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1); + return icc_igrpen0_el1.Enable; + } - case Gicv3::G1S: - //if (distributor->DS) - //{ - // return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) & - // ICC_IGRPEN1_EL1_ENABLE; - //} - //else - //{ - return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S) & - ICC_IGRPEN1_EL1_ENABLE; - - //} + case Gicv3::G1S: { + ICC_IGRPEN1_EL1 icc_igrpen1_el1_s = + isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S); + return icc_igrpen1_el1_s.Enable; + } - case Gicv3::G1NS: - return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) & - ICC_IGRPEN1_EL1_ENABLE; + case Gicv3::G1NS: { + ICC_IGRPEN1_EL1 icc_igrpen1_el1_ns = + isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS); + return icc_igrpen1_el1_ns.Enable; + } default: panic("Gicv3CPUInterface::groupEnable(): invalid group!\n"); @@ -2200,7 +2226,7 @@ Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group) } bool -Gicv3CPUInterface::inSecureState() +Gicv3CPUInterface::inSecureState() const { if (!gic->getSystem()->haveSecurity()) { return false; @@ -2212,7 +2238,7 @@ Gicv3CPUInterface::inSecureState() } int -Gicv3CPUInterface::currEL() +Gicv3CPUInterface::currEL() const { CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode); @@ -2237,7 +2263,7 @@ Gicv3CPUInterface::currEL() } bool -Gicv3CPUInterface::haveEL(ExceptionLevel el) +Gicv3CPUInterface::haveEL(ExceptionLevel el) const { switch (el) { case EL0: @@ -2257,21 +2283,21 @@ Gicv3CPUInterface::haveEL(ExceptionLevel el) } bool -Gicv3CPUInterface::isSecureBelowEL3() +Gicv3CPUInterface::isSecureBelowEL3() const { SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); return haveEL(EL3) && scr.ns == 0; } bool -Gicv3CPUInterface::isAA64() +Gicv3CPUInterface::isAA64() const { CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); return opModeIs64((OperatingMode)(uint8_t) cpsr.mode); } bool -Gicv3CPUInterface::isEL3OrMon() +Gicv3CPUInterface::isEL3OrMon() const { if (haveEL(EL3)) { CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); @@ -2287,95 +2313,126 @@ Gicv3CPUInterface::isEL3OrMon() return false; } -uint32_t -Gicv3CPUInterface::eoiMaintenanceInterruptStatus(uint32_t * misr) +// Computes ICH_EISR_EL2 +uint64_t +Gicv3CPUInterface::eoiMaintenanceInterruptStatus() const { - /* Return a set of bits indicating the EOI maintenance interrupt status - * for each list register. The EOI maintenance interrupt status is - * 1 if LR.State == 0 && LR.HW == 0 && LR.EOI == 1 - * (see the GICv3 spec for the ICH_EISR_EL2 register). - * If misr is not NULL then we should also collect the information - * about the MISR.EOI, MISR.NP and MISR.U bits. - */ - uint32_t value = 0; - int valid_count = 0; - bool seen_pending = false; + // ICH_EISR_EL2 + // Bits [63:16] - RES0 + // Status, bit [n], for n = 0 to 15 + // EOI maintenance interrupt status bit for List register : + // 0 if List register , ICH_LR_EL2, does not have an EOI + // maintenance interrupt. + // 1 if List register , ICH_LR_EL2, has an EOI maintenance + // interrupt that has not been handled. + // + // For any ICH_LR_EL2, the corresponding status bit is set to 1 if all + // of the following are true: + // - ICH_LR_EL2.State is 0b00 (ICH_LR_EL2_STATE_INVALID). + // - ICH_LR_EL2.HW is 0. + // - ICH_LR_EL2.EOI (bit [41]) is 1. + + uint64_t value = 0; for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { - RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); + ICH_LR_EL2 ich_lr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - if ((lr & (ICH_LR_EL2_STATE_MASK | ICH_LR_EL2_HW | ICH_LR_EL2_EOI)) == - ICH_LR_EL2_EOI) { + if ((ich_lr_el2.State == ICH_LR_EL2_STATE_INVALID) && + !ich_lr_el2.HW && ich_lr_el2.EOI) { value |= (1 << lr_idx); } + } - if ((lr & ICH_LR_EL2_STATE_MASK)) { - valid_count++; - } + return value; +} - if (bits(lr, ICH_LR_EL2_STATE_SHIFT + ICH_LR_EL2_STATE_LENGTH, - ICH_LR_EL2_STATE_SHIFT) == ICH_LR_EL2_STATE_PENDING) { - seen_pending = true; - } +Gicv3CPUInterface::ICH_MISR_EL2 +Gicv3CPUInterface::maintenanceInterruptStatus() const +{ + // Comments are copied from SPEC section 9.4.7 (ID012119) + ICH_MISR_EL2 ich_misr_el2 = 0; + ICH_HCR_EL2 ich_hcr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); + ICH_VMCR_EL2 ich_vmcr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); + + // End Of Interrupt. [bit 0] + // This maintenance interrupt is asserted when at least one bit in + // ICH_EISR_EL2 is 1. + + if (eoiMaintenanceInterruptStatus()) { + ich_misr_el2.EOI = 1; } - if (misr) { - RegVal ich_hcr_el2 = - isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); + // Underflow. [bit 1] + // This maintenance interrupt is asserted when ICH_HCR_EL2.UIE==1 and + // zero or one of the List register entries are marked as a valid + // interrupt, that is, if the corresponding ICH_LR_EL2.State bits + // do not equal 0x0. + uint32_t num_valid_interrupts = 0; + uint32_t num_pending_interrupts = 0; - if (valid_count < 2 && (ich_hcr_el2 & ICH_HCR_EL2_UIE)) { - *misr |= ICH_MISR_EL2_U; - } + for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { + ICH_LR_EL2 ich_lr_el2 = + isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); - if (!seen_pending && (ich_hcr_el2 & ICH_HCR_EL2_NPIE)) { - *misr |= ICH_MISR_EL2_NP; + if (ich_lr_el2.State != ICH_LR_EL2_STATE_INVALID) { + num_valid_interrupts++; } - if (value) { - *misr |= ICH_MISR_EL2_EOI; + if (ich_lr_el2.State == ICH_LR_EL2_STATE_PENDING) { + num_pending_interrupts++; } } - return value; -} + if (ich_hcr_el2.UIE && (num_valid_interrupts < 2)) { + ich_misr_el2.U = 1; + } -uint32_t -Gicv3CPUInterface::maintenanceInterruptStatus() -{ - /* Return a set of bits indicating the maintenance interrupt status - * (as seen in the ICH_MISR_EL2 register). - */ - uint32_t value = 0; - /* Scan list registers and fill in the U, NP and EOI bits */ - eoiMaintenanceInterruptStatus(&value); - RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); - RegVal ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); + // List Register Entry Not Present. [bit 2] + // This maintenance interrupt is asserted when ICH_HCR_EL2.LRENPIE==1 + // and ICH_HCR_EL2.EOIcount is non-zero. + if (ich_hcr_el2.LRENPIE && ich_hcr_el2.EOIcount) { + ich_misr_el2.LRENP = 1; + } - if (ich_hcr_el2 & (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) { - value |= ICH_MISR_EL2_LRENP; + // No Pending. [bit 3] + // This maintenance interrupt is asserted when ICH_HCR_EL2.NPIE==1 and + // no List register is in pending state. + if (ich_hcr_el2.NPIE && (num_pending_interrupts == 0)) { + ich_misr_el2.NP = 1; } - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) && - (ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) { - value |= ICH_MISR_EL2_VGRP0E; + // vPE Group 0 Enabled. [bit 4] + // This maintenance interrupt is asserted when + // ICH_HCR_EL2.VGrp0EIE==1 and ICH_VMCR_EL2.VENG0==1. + if (ich_hcr_el2.VGrp0EIE && ich_vmcr_el2.VENG0) { + ich_misr_el2.VGrp0E = 1; } - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) && - !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { - value |= ICH_MISR_EL2_VGRP0D; + // vPE Group 0 Disabled. [bit 5] + // This maintenance interrupt is asserted when + // ICH_HCR_EL2.VGrp0DIE==1 and ICH_VMCR_EL2.VENG0==0. + if (ich_hcr_el2.VGrp0DIE && !ich_vmcr_el2.VENG0) { + ich_misr_el2.VGrp0D = 1; } - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) && - (ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { - value |= ICH_MISR_EL2_VGRP1E; + // vPE Group 1 Enabled. [bit 6] + // This maintenance interrupt is asserted when + // ICH_HCR_EL2.VGrp1EIE==1 and ICH_VMCR_EL2.VENG1==is 1. + if (ich_hcr_el2.VGrp1EIE && ich_vmcr_el2.VENG1) { + ich_misr_el2.VGrp1E = 1; } - if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) && - !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { - value |= ICH_MISR_EL2_VGRP1D; + // vPE Group 1 Disabled. [bit 7] + // This maintenance interrupt is asserted when + // ICH_HCR_EL2.VGrp1DIE==1 and ICH_VMCR_EL2.VENG1==is 0. + if (ich_hcr_el2.VGrp1DIE && !ich_vmcr_el2.VENG1) { + ich_misr_el2.VGrp1D = 1; } - return value; + return ich_misr_el2; } void diff --git a/src/dev/arm/gic_v3_cpu_interface.hh b/src/dev/arm/gic_v3_cpu_interface.hh index 3752f55e1..271be87a7 100644 --- a/src/dev/arm/gic_v3_cpu_interface.hh +++ b/src/dev/arm/gic_v3_cpu_interface.hh @@ -34,15 +34,15 @@ #include "arch/arm/isa_device.hh" #include "dev/arm/gic_v3.hh" -class Gicv3Redistributor; class Gicv3Distributor; +class Gicv3Redistributor; class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable { private: - friend class Gicv3Redistributor; friend class Gicv3Distributor; + friend class Gicv3Redistributor; protected: @@ -51,61 +51,91 @@ class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable Gicv3Distributor * distributor; uint32_t cpuId; - static const uint32_t ICC_SRE_EL1_SRE = 1 << 0; - static const uint32_t ICC_SRE_EL1_DFB = 1 << 1; - static const uint32_t ICC_SRE_EL1_DIB = 1 << 2; - - static const uint32_t ICC_SRE_EL2_SRE = 1 << 0; - static const uint32_t ICC_SRE_EL2_DFB = 1 << 1; - static const uint32_t ICC_SRE_EL2_DIB = 1 << 2; - static const uint32_t ICC_SRE_EL2_ENABLE = 1 << 3; - - static const uint32_t ICC_SRE_EL3_SRE = 1 << 0; - static const uint32_t ICC_SRE_EL3_DFB = 1 << 1; - static const uint32_t ICC_SRE_EL3_DIB = 1 << 2; - static const uint32_t ICC_SRE_EL3_ENABLE = 1 << 3; - - static const uint32_t ICC_CTLR_EL3_CBPR_EL1S = 1 << 0; - static const uint32_t ICC_CTLR_EL3_CBPR_EL1NS = 1 << 1; - static const uint32_t ICC_CTLR_EL3_EOIMODE_EL3 = 1 << 2; - static const uint32_t ICC_CTLR_EL3_EOIMODE_EL1S = 1 << 3; - static const uint32_t ICC_CTLR_EL3_EOIMODE_EL1NS = 1 << 4; - static const uint32_t ICC_CTLR_EL3_RM = 1 << 5; - static const uint32_t ICC_CTLR_EL3_PMHE = 1 << 6; - static const uint32_t ICC_CTLR_EL3_PRIBITS_SHIFT = 8; - static const uint32_t ICC_CTLR_EL3_IDBITS_SHIFT = 11; - static const uint32_t ICC_CTLR_EL3_SEIS = 1 << 14; - static const uint32_t ICC_CTLR_EL3_A3V = 1 << 15; - static const uint32_t ICC_CTLR_EL3_nDS = 1 << 17; - static const uint32_t ICC_CTLR_EL3_RSS = 1 << 18; - - static const uint32_t ICC_CTLR_EL1_CBPR = 1 << 0; - static const uint32_t ICC_CTLR_EL1_EOIMODE = 1 << 1; - static const uint32_t ICC_CTLR_EL1_PMHE = 1 << 6; - static const uint32_t ICC_CTLR_EL1_SEIS = 1 << 14; - static const uint32_t ICC_CTLR_EL1_A3V = 1 << 15; - static const uint32_t ICC_CTLR_EL1_RSS = 1 << 18; - static const uint32_t ICC_CTLR_EL1_PRIBITS_SHIFT = 8; - static const uint32_t ICC_CTLR_EL1_PRIBITS_MASK = - 7U << ICC_CTLR_EL1_PRIBITS_SHIFT; - static const uint32_t ICC_CTLR_EL1_IDBITS_SHIFT = 11; - - static const uint32_t ICC_IGRPEN0_EL1_ENABLE = 1 << 0; - static const uint32_t ICC_IGRPEN1_EL1_ENABLE = 1 << 0; - - static const uint32_t ICC_IGRPEN1_EL3_ENABLEGRP1NS = 1 << 0; - static const uint32_t ICC_IGRPEN1_EL3_ENABLEGRP1S = 1 << 1; + BitUnion64(ICC_CTLR_EL1) + Bitfield<63, 20> res0_3; + Bitfield<19> ExtRange; + Bitfield<18> RSS; + Bitfield<17, 16> res0_2; + Bitfield<15> A3V; + Bitfield<14> SEIS; + Bitfield<13, 11> IDbits; + Bitfield<10, 8> PRIbits; + Bitfield<7> res0_1; + Bitfield<6> PMHE; + Bitfield<5, 2> res0_0; + Bitfield<1> EOImode; + Bitfield<0> CBPR; + EndBitUnion(ICC_CTLR_EL1) + + BitUnion64(ICC_CTLR_EL3) + Bitfield<63, 20> res0_2; + Bitfield<19> ExtRange; + Bitfield<18> RSS; + Bitfield<17> nDS; + Bitfield<16> res0_1; + Bitfield<15> A3V; + Bitfield<14> SEIS; + Bitfield<13, 11> IDbits; + Bitfield<10, 8> PRIbits; + Bitfield<7> res0_0; + Bitfield<6> PMHE; + Bitfield<5> RM; + Bitfield<4> EOImode_EL1NS; + Bitfield<3> EOImode_EL1S; + Bitfield<2> EOImode_EL3; + Bitfield<1> CBPR_EL1NS; + Bitfield<0> CBPR_EL1S; + EndBitUnion(ICC_CTLR_EL3) + + BitUnion64(ICC_IGRPEN0_EL1) + Bitfield<63, 1> res0; + Bitfield<0> Enable; + EndBitUnion(ICC_IGRPEN0_EL1) + + BitUnion64(ICC_IGRPEN1_EL1) + Bitfield<63, 1> res0; + Bitfield<0> Enable; + EndBitUnion(ICC_IGRPEN1_EL1) + + BitUnion64(ICC_IGRPEN1_EL3) + Bitfield<63, 2> res0; + Bitfield<1> EnableGrp1S; + Bitfield<0> EnableGrp1NS; + EndBitUnion(ICC_IGRPEN1_EL3) + + BitUnion64(ICC_SRE_EL1) + Bitfield<63, 3> res0; + Bitfield<2> DIB; + Bitfield<1> DFB; + Bitfield<0> SRE; + EndBitUnion(ICC_SRE_EL1) + + BitUnion64(ICC_SRE_EL2) + Bitfield<63, 4> res0; + Bitfield<3> Enable; + Bitfield<2> DIB; + Bitfield<1> DFB; + Bitfield<0> SRE; + EndBitUnion(ICC_SRE_EL2) + + BitUnion64(ICC_SRE_EL3) + Bitfield<63, 4> res0; + Bitfield<3> Enable; + Bitfield<2> DIB; + Bitfield<1> DFB; + Bitfield<0> SRE; + EndBitUnion(ICC_SRE_EL3) static const uint8_t PRIORITY_BITS = 5; - /* Minimum BPR for Secure, or when security not enabled */ + // Minimum BPR for Secure, or when security not enabled static const uint8_t GIC_MIN_BPR = 2; - /* Minimum BPR for Nonsecure when security is enabled */ + // Minimum BPR for Nonsecure when security is enabled static const uint8_t GIC_MIN_BPR_NS = GIC_MIN_BPR + 1; - static const uint8_t VIRTUAL_PRIORITY_BITS = 5; + static const uint8_t VIRTUAL_PRIORITY_BITS = 5; static const uint8_t VIRTUAL_PREEMPTION_BITS = 5; - static const uint8_t VIRTUAL_NUM_LIST_REGS = 16; + static const uint8_t VIRTUAL_NUM_LIST_REGS = 16; static const uint8_t GIC_MIN_VBPR = 7 - VIRTUAL_PREEMPTION_BITS; @@ -119,19 +149,19 @@ class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable // GIC CPU interface memory mapped control registers (legacy) enum { - GICC_CTLR = 0x0000, - GICC_PMR = 0x0004, - GICC_BPR = 0x0008, - GICC_IAR = 0x000C, - GICC_EOIR = 0x0010, - GICC_RPR = 0x0014, - GICC_HPPI = 0x0018, - GICC_ABPR = 0x001C, - GICC_AIAR = 0x0020, - GICC_AEOIR = 0x0024, - GICC_AHPPIR = 0x0028, + GICC_CTLR = 0x0000, + GICC_PMR = 0x0004, + GICC_BPR = 0x0008, + GICC_IAR = 0x000C, + GICC_EOIR = 0x0010, + GICC_RPR = 0x0014, + GICC_HPPI = 0x0018, + GICC_ABPR = 0x001C, + GICC_AIAR = 0x0020, + GICC_AEOIR = 0x0024, + GICC_AHPPIR = 0x0028, GICC_STATUSR = 0x002C, - GICC_IIDR = 0x00FC, + GICC_IIDR = 0x00FC, }; static const AddrRange GICC_APR; @@ -139,163 +169,166 @@ class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable // GIC CPU virtual interface memory mapped control registers (legacy) enum { - GICH_HCR = 0x0000, - GICH_VTR = 0x0004, - GICH_VMCR = 0x0008, - GICH_MISR = 0x0010, - GICH_EISR = 0x0020, + GICH_HCR = 0x0000, + GICH_VTR = 0x0004, + GICH_VMCR = 0x0008, + GICH_MISR = 0x0010, + GICH_EISR = 0x0020, GICH_ELRSR = 0x0030, }; static const AddrRange GICH_APR; static const AddrRange GICH_LR; - static const uint32_t ICH_HCR_EL2_EN = 1 << 0; - static const uint32_t ICH_HCR_EL2_UIE = 1 << 1; - static const uint32_t ICH_HCR_EL2_LRENPIE = 1 << 2; - static const uint32_t ICH_HCR_EL2_NPIE = 1 << 3; - static const uint32_t ICH_HCR_EL2_VGRP0EIE = 1 << 4; - static const uint32_t ICH_HCR_EL2_VGRP0DIE = 1 << 5; - static const uint32_t ICH_HCR_EL2_VGRP1EIE = 1 << 6; - static const uint32_t ICH_HCR_EL2_VGRP1DIE = 1 << 7; - static const uint32_t ICH_HCR_EL2_TC = 1 << 10; - static const uint32_t ICH_HCR_EL2_TALL0 = 1 << 11; - static const uint32_t ICH_HCR_EL2_TALL1 = 1 << 12; - static const uint32_t ICH_HCR_EL2_TSEI = 1 << 13; - static const uint32_t ICH_HCR_EL2_TDIR = 1 << 14; - static const uint32_t ICH_HCR_EL2_EOICOUNT_MASK = 0x1fU << 27; - - static const uint64_t ICH_LR_EL2_VINTID_SHIFT = 0; - static const uint64_t ICH_LR_EL2_VINTID_LENGTH = 32; - static const uint64_t ICH_LR_EL2_VINTID_MASK = - (0xffffffffULL << ICH_LR_EL2_VINTID_SHIFT); - static const uint64_t ICH_LR_EL2_PINTID_SHIFT = 32; - static const uint64_t ICH_LR_EL2_PINTID_LENGTH = 10; - static const uint64_t ICH_LR_EL2_PINTID_MASK = - (0x3ffULL << ICH_LR_EL2_PINTID_SHIFT); - /* Note that EOI shares with the top bit of the pINTID field */ - static const uint64_t ICH_LR_EL2_EOI = (1ULL << 41); - static const uint64_t ICH_LR_EL2_PRIORITY_SHIFT = 48; - static const uint64_t ICH_LR_EL2_PRIORITY_LENGTH = 8; - static const uint64_t ICH_LR_EL2_PRIORITY_MASK = - (0xffULL << ICH_LR_EL2_PRIORITY_SHIFT); - static const uint64_t ICH_LR_EL2_GROUP = (1ULL << 60); - static const uint64_t ICH_LR_EL2_HW = (1ULL << 61); - static const uint64_t ICH_LR_EL2_STATE_SHIFT = 62; - static const uint64_t ICH_LR_EL2_STATE_LENGTH = 2; - static const uint64_t ICH_LR_EL2_STATE_MASK = - (3ULL << ICH_LR_EL2_STATE_SHIFT); - /* values for the state field: */ - static const uint64_t ICH_LR_EL2_STATE_INVALID = 0; - static const uint64_t ICH_LR_EL2_STATE_PENDING = 1; - static const uint64_t ICH_LR_EL2_STATE_ACTIVE = 2; + BitUnion64(ICH_HCR_EL2) + Bitfield<63, 32> res0_2; + Bitfield<31, 27> EOIcount; + Bitfield<26, 15> res0_1; + Bitfield<14> TDIR; + Bitfield<13> TSEI; + Bitfield<12> TALL1; + Bitfield<11> TALL0; + Bitfield<10> TC; + Bitfield<9, 8> res0_0; + Bitfield<7> VGrp1DIE; + Bitfield<6> VGrp1EIE; + Bitfield<5> VGrp0DIE; + Bitfield<4> VGrp0EIE; + Bitfield<3> NPIE; + Bitfield<2> LRENPIE; + Bitfield<1> UIE; + Bitfield<0> En; + EndBitUnion(ICH_HCR_EL2) + + BitUnion64(ICH_LR_EL2) + Bitfield<63, 62> State; + Bitfield<61> HW; + Bitfield<60> Group; + Bitfield<59, 56> res0_1; + Bitfield<55, 48> Priority; + Bitfield<47, 45> res0_0; + Bitfield<44, 32> pINTID; + Bitfield<41> EOI; + Bitfield<31, 0> vINTID; + EndBitUnion(ICH_LR_EL2) + + static const uint64_t ICH_LR_EL2_STATE_INVALID = 0; + static const uint64_t ICH_LR_EL2_STATE_PENDING = 1; + static const uint64_t ICH_LR_EL2_STATE_ACTIVE = 2; static const uint64_t ICH_LR_EL2_STATE_ACTIVE_PENDING = 3; - static const uint64_t ICH_LR_EL2_STATE_PENDING_BIT = - (1ULL << ICH_LR_EL2_STATE_SHIFT); - static const uint64_t ICH_LR_EL2_STATE_ACTIVE_BIT = - (2ULL << ICH_LR_EL2_STATE_SHIFT); - - static const uint64_t ICH_LRC_PRIORITY_SHIFT = - ICH_LR_EL2_PRIORITY_SHIFT - 32; - static const uint64_t ICH_LRC_PRIORITY_LENGTH = - ICH_LR_EL2_PRIORITY_LENGTH; - - static const uint32_t ICH_MISR_EL2_EOI = (1 << 0); - static const uint32_t ICH_MISR_EL2_U = (1 << 1); - static const uint32_t ICH_MISR_EL2_LRENP = (1 << 2); - static const uint32_t ICH_MISR_EL2_NP = (1 << 3); - static const uint32_t ICH_MISR_EL2_VGRP0E = (1 << 4); - static const uint32_t ICH_MISR_EL2_VGRP0D = (1 << 5); - static const uint32_t ICH_MISR_EL2_VGRP1E = (1 << 6); - static const uint32_t ICH_MISR_EL2_VGRP1D = (1 << 7); - - static const uint32_t ICH_VMCR_EL2_VENG0_SHIFT = 0; - static const uint32_t ICH_VMCR_EL2_VENG0 = - (1 << ICH_VMCR_EL2_VENG0_SHIFT); - static const uint32_t ICH_VMCR_EL2_VENG1_SHIFT = 1; - static const uint32_t ICH_VMCR_EL2_VENG1 = - (1 << ICH_VMCR_EL2_VENG1_SHIFT); - static const uint32_t ICH_VMCR_EL2_VACKCTL = (1 << 2); - static const uint32_t ICH_VMCR_EL2_VFIQEN = (1 << 3); - static const uint32_t ICH_VMCR_EL2_VCBPR_SHIFT = 4; - static const uint32_t ICH_VMCR_EL2_VCBPR = - (1 << ICH_VMCR_EL2_VCBPR_SHIFT); - static const uint32_t ICH_VMCR_EL2_VEOIM_SHIFT = 9; - static const uint32_t ICH_VMCR_EL2_VEOIM = - (1 << ICH_VMCR_EL2_VEOIM_SHIFT); - static const uint32_t ICH_VMCR_EL2_VBPR1_SHIFT = 18; - static const uint32_t ICH_VMCR_EL2_VBPR1_LENGTH = 3; - static const uint32_t ICH_VMCR_EL2_VBPR1_MASK = - (0x7U << ICH_VMCR_EL2_VBPR1_SHIFT); - static const uint32_t ICH_VMCR_EL2_VBPR0_SHIFT = 21; - static const uint32_t ICH_VMCR_EL2_VBPR0_LENGTH = 3; - static const uint32_t ICH_VMCR_EL2_VBPR0_MASK = - (0x7U << ICH_VMCR_EL2_VBPR0_SHIFT); - static const uint32_t ICH_VMCR_EL2_VPMR_SHIFT = 24; - static const uint32_t ICH_VMCR_EL2_VPMR_LENGTH = 8; - static const uint32_t ICH_VMCR_EL2_VPMR_MASK = - (0xffU << ICH_VMCR_EL2_VPMR_SHIFT); - - static const uint32_t ICH_VTR_EL2_LISTREGS_SHIFT = 0; - static const uint32_t ICH_VTR_EL2_TDS = 1 << 19; - static const uint32_t ICH_VTR_EL2_NV4 = 1 << 20; - static const uint32_t ICH_VTR_EL2_A3V = 1 << 21; - static const uint32_t ICH_VTR_EL2_SEIS = 1 << 22; - static const uint32_t ICH_VTR_EL2_IDBITS_SHIFT = 23; - static const uint32_t ICH_VTR_EL2_PREBITS_SHIFT = 26; - static const uint32_t ICH_VTR_EL2_PRIBITS_SHIFT = 29; - public: + BitUnion32(ICH_LRC) + Bitfield<31, 30> State; + Bitfield<29> HW; + Bitfield<28> Group; + Bitfield<27, 24> res0_1; + Bitfield<23, 16> Priority; + Bitfield<15, 13> res0_0; + Bitfield<12, 0> pINTID; + Bitfield<9> EOI; + EndBitUnion(ICH_LRC) + + BitUnion64(ICH_MISR_EL2) + Bitfield<63, 8> res0; + Bitfield<7> VGrp1D; + Bitfield<6> VGrp1E; + Bitfield<5> VGrp0D; + Bitfield<4> VGrp0E; + Bitfield<3> NP; + Bitfield<2> LRENP; + Bitfield<1> U; + Bitfield<0> EOI; + EndBitUnion(ICH_MISR_EL2) + + BitUnion64(ICH_VMCR_EL2) + Bitfield<63, 32> res0_2; + Bitfield<31, 24> VPMR; + Bitfield<23, 21> VBPR0; + Bitfield<20, 18> VBPR1; + Bitfield<17, 10> res0_1; + Bitfield<9> VEOIM; + Bitfield<8, 5> res0_0; + Bitfield<4> VCBPR; + Bitfield<3> VFIQEn; + Bitfield<2> VAckCtl; + Bitfield<1> VENG1; + Bitfield<0> VENG0; + EndBitUnion(ICH_VMCR_EL2) + + BitUnion64(ICH_VTR_EL2) + Bitfield<63, 32> res0_1; + Bitfield<31, 29> PRIbits; + Bitfield<28, 26> PREbits; + Bitfield<25, 23> IDbits; + Bitfield<22> SEIS; + Bitfield<21> A3V; + Bitfield<20> res1; + Bitfield<19> TDS; + Bitfield<18, 5> res0_0; + Bitfield<4, 0> ListRegs; + EndBitUnion(ICH_VTR_EL2) + + BitUnion64(ICV_CTLR_EL1) + Bitfield<63, 19> res0_2; + Bitfield<18> RSS; + Bitfield<17, 16> res0_1; + Bitfield<15> A3V; + Bitfield<14> SEIS; + Bitfield<13, 11> IDbits; + Bitfield<10, 8> PRIbits; + Bitfield<7, 2> res0_0; + Bitfield<1> EOImode; + Bitfield<0> CBPR; + EndBitUnion(ICV_CTLR_EL1) - Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id); - ~Gicv3CPUInterface(); - void init(); - void initState(); + protected: + void activateIRQ(uint32_t intid, Gicv3::GroupId group); + int currEL() const; + void deactivateIRQ(uint32_t intid, Gicv3::GroupId group); + void dropPriority(Gicv3::GroupId group); + uint64_t eoiMaintenanceInterruptStatus() const; + bool getHCREL2FMO() const; + bool getHCREL2IMO() const; + uint32_t getHPPIR0() const; + uint32_t getHPPIR1() const; + int getHPPVILR() const; + bool groupEnabled(Gicv3::GroupId group) const; + uint32_t groupPriorityMask(Gicv3::GroupId group) const; + bool haveEL(ArmISA::ExceptionLevel el) const; + int highestActiveGroup() const; + uint8_t highestActivePriority() const; + bool hppiCanPreempt() const; + bool hppviCanPreempt(int lrIdx) const; + bool inSecureState() const; + ArmISA::InterruptTypes intSignalType(Gicv3::GroupId group) const; + bool isAA64() const; + bool isEL3OrMon() const; + bool isEOISplitMode() const; + bool isSecureBelowEL3() const; + ICH_MISR_EL2 maintenanceInterruptStatus() const; RegVal readMiscReg(int misc_reg) override; - void setMiscReg(int misc_reg, RegVal val) override; - void update(); - void virtualUpdate(); - + void reset(); void serialize(CheckpointOut & cp) const override; + void setMiscReg(int misc_reg, RegVal val) override; void unserialize(CheckpointIn & cp) override; - - protected: - - void reset(); - bool hppiCanPreempt(); - bool hppviCanPreempt(int lrIdx); - bool groupEnabled(Gicv3::GroupId group); - uint8_t highestActivePriority(); - uint8_t virtualHighestActivePriority(); - bool inSecureState(); - int currEL(); - bool haveEL(ArmISA::ExceptionLevel el); - void activateIRQ(uint32_t intid, Gicv3::GroupId group); + void update(); void virtualActivateIRQ(uint32_t lrIdx); - void deactivateIRQ(uint32_t intid, Gicv3::GroupId group); void virtualDeactivateIRQ(int lrIdx); - uint32_t groupPriorityMask(Gicv3::GroupId group); - uint32_t virtualGroupPriorityMask(Gicv3::GroupId group); - void dropPriority(Gicv3::GroupId group); uint8_t virtualDropPriority(); - ArmISA::InterruptTypes intSignalType(Gicv3::GroupId group); - bool isEOISplitMode(); - bool virtualIsEOISplitMode(); - bool isSecureBelowEL3(); - bool inSecureState2(); - uint32_t eoiMaintenanceInterruptStatus(uint32_t * misr); - uint32_t maintenanceInterruptStatus(); - int highestActiveGroup(); - bool getHCREL2FMO(); - bool getHCREL2IMO(); - uint32_t getHPPIR1(); - uint32_t getHPPIR0(); - int getHPPVILR(); - int virtualFindActive(uint32_t intid); + int virtualFindActive(uint32_t intid) const; + uint32_t virtualGroupPriorityMask(Gicv3::GroupId group) const; + uint8_t virtualHighestActivePriority() const; void virtualIncrementEOICount(); - bool isEL3OrMon(); - bool isAA64(); + bool virtualIsEOISplitMode() const; + void virtualUpdate(); + + public: + + Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id); + + void init(); + void initState(); }; #endif //__DEV_ARM_GICV3_CPU_INTERFACE_H__