From: Giacomo Travaglini Date: Tue, 20 Aug 2019 11:26:17 +0000 (+0100) Subject: dev-arm: Fix SGI generation X-Git-Tag: v19.0.0.0~592 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1768c47bc4fc00e89601ad03c9091c9b949a6c97;p=gem5.git dev-arm: Fix SGI generation The patch is fixing the following aspects of SGIs * The conditons over which an SGI can be forwarded to a PE * SGIs in AArch32 (see below) It is in fact refactoring SGI generation under a common method in the cpu interface. It is abandoning the implicit fallthrough mechanism not only for cosmetic reasons, but also because checking "misc_reg ==" was only working if the register was an AArch64 one (e.g. MISCREG_ICC_SGI0R_EL1) and not the AArch32 counterpart (MISCREG_SGI0R). Change-Id: I6fedfb80388666f4f1d20f6abef378a9f093aa83 Signed-off-by: Giacomo Travaglini Reviewed-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20610 Maintainer: Andreas Sandberg Tested-by: kokoro --- diff --git a/src/dev/arm/gic_v3_cpu_interface.cc b/src/dev/arm/gic_v3_cpu_interface.cc index 348819316..97d914568 100644 --- a/src/dev/arm/gic_v3_cpu_interface.cc +++ b/src/dev/arm/gic_v3_cpu_interface.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2019 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2018 Metempsy Technology Consulting * All rights reserved. * @@ -1416,68 +1428,25 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) // Software Generated Interrupt Group 0 Register case MISCREG_ICC_SGI0R: case MISCREG_ICC_SGI0R_EL1: + generateSGI(val, Gicv3::G0S); + break; // Software Generated Interrupt Group 1 Register case MISCREG_ICC_SGI1R: - case MISCREG_ICC_SGI1R_EL1: + case MISCREG_ICC_SGI1R_EL1: { + Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS; + + generateSGI(val, group); + break; + } // Alias Software Generated Interrupt Group 1 Register case MISCREG_ICC_ASGI1R: case MISCREG_ICC_ASGI1R_EL1: { - bool ns = !inSecureState(); - Gicv3::GroupId group; - - if (misc_reg == MISCREG_ICC_SGI1R_EL1) { - group = ns ? Gicv3::G1NS : Gicv3::G1S; - } else if (misc_reg == MISCREG_ICC_ASGI1R_EL1) { - group = ns ? Gicv3::G1S : Gicv3::G1NS; - } else { - group = Gicv3::G0S; - } - - if (distributor->DS && group == Gicv3::G1S) { - group = Gicv3::G0S; - } - - uint8_t aff3 = bits(val, 55, 48); - uint8_t aff2 = bits(val, 39, 32); - uint8_t aff1 = bits(val, 23, 16);; - uint16_t target_list = bits(val, 15, 0); - uint32_t int_id = bits(val, 27, 24); - bool irm = bits(val, 40, 40); - uint8_t rs = bits(val, 47, 44); - - for (int i = 0; i < gic->getSystem()->numContexts(); i++) { - Gicv3Redistributor * redistributor_i = - gic->getRedistributor(i); - uint32_t affinity_i = redistributor_i->getAffinity(); - - if (irm) { - // Interrupts routed to all PEs in the system, - // excluding "self" - if (affinity_i == redistributor->getAffinity()) { - continue; - } - } else { - // Interrupts routed to the PEs specified by - // Aff3.Aff2.Aff1. - if ((affinity_i >> 8) != - ((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))) { - continue; - } - } + Gicv3::GroupId group = inSecureState() ? Gicv3::G1NS : Gicv3::G1S; - redistributor_i->sendSGI(int_id, group, ns); - } - - break; + generateSGI(val, group); + break; } // System Register Enable Register EL1 @@ -1789,6 +1758,50 @@ Gicv3CPUInterface::virtualDropPriority() return 0xff; } +void +Gicv3CPUInterface::generateSGI(RegVal val, Gicv3::GroupId group) +{ + uint8_t aff3 = bits(val, 55, 48); + uint8_t aff2 = bits(val, 39, 32); + uint8_t aff1 = bits(val, 23, 16);; + uint16_t target_list = bits(val, 15, 0); + uint32_t int_id = bits(val, 27, 24); + bool irm = bits(val, 40, 40); + uint8_t rs = bits(val, 47, 44); + + bool ns = !inSecureState(); + + for (int i = 0; i < gic->getSystem()->numContexts(); i++) { + Gicv3Redistributor * redistributor_i = + gic->getRedistributor(i); + uint32_t affinity_i = redistributor_i->getAffinity(); + + if (irm) { + // Interrupts routed to all PEs in the system, + // excluding "self" + if (affinity_i == redistributor->getAffinity()) { + continue; + } + } else { + // Interrupts routed to the PEs specified by + // Aff3.Aff2.Aff1. + if ((affinity_i >> 8) != + ((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))) { + continue; + } + } + + redistributor_i->sendSGI(int_id, group, ns); + } +} + void Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group) { diff --git a/src/dev/arm/gic_v3_cpu_interface.hh b/src/dev/arm/gic_v3_cpu_interface.hh index e6dcb51ff..5c66fd75f 100644 --- a/src/dev/arm/gic_v3_cpu_interface.hh +++ b/src/dev/arm/gic_v3_cpu_interface.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2019 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2018 Metempsy Technology Consulting * All rights reserved. * @@ -286,6 +298,7 @@ class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable protected: void activateIRQ(uint32_t intid, Gicv3::GroupId group); + void generateSGI(RegVal val, Gicv3::GroupId group); int currEL() const; void deactivateIRQ(uint32_t intid, Gicv3::GroupId group); void dropPriority(Gicv3::GroupId group); diff --git a/src/dev/arm/gic_v3_redistributor.cc b/src/dev/arm/gic_v3_redistributor.cc index 37f169f19..71e74bfb8 100644 --- a/src/dev/arm/gic_v3_redistributor.cc +++ b/src/dev/arm/gic_v3_redistributor.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2019 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2018 Metempsy Technology Consulting * All rights reserved. * @@ -730,26 +742,31 @@ Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns) assert(int_id < Gicv3::SGI_MAX); Gicv3::GroupId int_group = getIntGroup(int_id); - // asked for secure group 1 - // configured as group 0 - // send group 0 - if (int_group == Gicv3::G0S && group == Gicv3::G1S) { - group = Gicv3::G0S; - } - - if (group == Gicv3::G0S and int_group != Gicv3::G0S) { - return; - } + bool forward = false; - if (ns && distributor->DS == 0) { + if (ns) { + // Non-Secure EL1 and EL2 access int nsaccess = irqNsacr[int_id]; + if (int_group == Gicv3::G0S) { - if ((int_group == Gicv3::G0S && nsaccess < 1) || - (int_group == Gicv3::G1S && nsaccess < 2)) { - return; + forward = distributor->DS || (nsaccess >= 1); + + } else if (int_group == Gicv3::G1S) { + forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) && + nsaccess == 2); + } else { + // G1NS + forward = group == Gicv3::G1NS; } + } else { + // Secure EL1 and EL3 access + forward = (group == int_group) || + (group == Gicv3::G1S && int_group == Gicv3::G0S && + distributor->DS); } + if (!forward) return; + irqPending[int_id] = true; DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): " "int_id %d (SGI) pending bit set\n", int_id);