diff options
Diffstat (limited to 'src/dev/arm/gic_v3_cpu_interface.cc')
-rw-r--r-- | src/dev/arm/gic_v3_cpu_interface.cc | 121 |
1 files changed, 67 insertions, 54 deletions
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.<target list> - 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 @@ -1790,6 +1759,50 @@ Gicv3CPUInterface::virtualDropPriority() } 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.<target list> + 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) { // Update active priority registers. |