1/* 2 * Copyright (c) 2018 Metempsy Technology Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Jairo Balart 29 */ 30 31#include "dev/arm/gic_v3_redistributor.hh" 32 33#include "arch/arm/utility.hh" 34#include "debug/GIC.hh" 35#include "dev/arm/gic_v3_cpu_interface.hh" 36#include "dev/arm/gic_v3_distributor.hh"
| 1/* 2 * Copyright (c) 2018 Metempsy Technology Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Jairo Balart 29 */ 30 31#include "dev/arm/gic_v3_redistributor.hh" 32 33#include "arch/arm/utility.hh" 34#include "debug/GIC.hh" 35#include "dev/arm/gic_v3_cpu_interface.hh" 36#include "dev/arm/gic_v3_distributor.hh"
|
| 37#include "mem/fs_translating_port_proxy.hh"
|
37 38const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400, 39 SGI_base + 0x041f); 40 41Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id) 42 : gic(gic), 43 distributor(nullptr), 44 cpuInterface(nullptr), 45 cpuId(cpu_id), 46 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 47 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 48 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 49 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 50 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 51 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 52 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 53 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX) 54{ 55} 56 57Gicv3Redistributor::~Gicv3Redistributor() 58{ 59} 60 61void 62Gicv3Redistributor::init() 63{ 64 distributor = gic->getDistributor(); 65 cpuInterface = gic->getCPUInterface(cpuId); 66} 67 68void 69Gicv3Redistributor::initState() 70{ 71 reset(); 72} 73 74void 75Gicv3Redistributor::reset() 76{ 77 peInLowPowerState = true; 78 std::fill(irqGroup.begin(), irqGroup.end(), 0); 79 std::fill(irqEnabled.begin(), irqEnabled.end(), false); 80 std::fill(irqPending.begin(), irqPending.end(), false); 81 std::fill(irqActive.begin(), irqActive.end(), false); 82 std::fill(irqPriority.begin(), irqPriority.end(), 0); 83 84 // SGIs have edge-triggered behavior 85 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) { 86 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED; 87 } 88 89 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 90 std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 91 DPG1S = false; 92 DPG1NS = false; 93 DPG0 = false;
| 38 39const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400, 40 SGI_base + 0x041f); 41 42Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id) 43 : gic(gic), 44 distributor(nullptr), 45 cpuInterface(nullptr), 46 cpuId(cpu_id), 47 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 48 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 49 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 50 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 51 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 52 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 53 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 54 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX) 55{ 56} 57 58Gicv3Redistributor::~Gicv3Redistributor() 59{ 60} 61 62void 63Gicv3Redistributor::init() 64{ 65 distributor = gic->getDistributor(); 66 cpuInterface = gic->getCPUInterface(cpuId); 67} 68 69void 70Gicv3Redistributor::initState() 71{ 72 reset(); 73} 74 75void 76Gicv3Redistributor::reset() 77{ 78 peInLowPowerState = true; 79 std::fill(irqGroup.begin(), irqGroup.end(), 0); 80 std::fill(irqEnabled.begin(), irqEnabled.end(), false); 81 std::fill(irqPending.begin(), irqPending.end(), false); 82 std::fill(irqActive.begin(), irqActive.end(), false); 83 std::fill(irqPriority.begin(), irqPriority.end(), 0); 84 85 // SGIs have edge-triggered behavior 86 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) { 87 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED; 88 } 89 90 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 91 std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 92 DPG1S = false; 93 DPG1NS = false; 94 DPG0 = false;
|
| 95 EnableLPIs = false; 96 lpiConfigurationTablePtr = 0; 97 lpiIDBits = 0; 98 lpiPendingTablePtr = 0;
|
94} 95 96uint64_t 97Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access) 98{ 99 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 100 uint64_t value = 0; 101 int first_intid = addr - GICR_IPRIORITYR.start(); 102 103 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 104 uint8_t prio = irqPriority[int_id]; 105 106 if (!distributor->DS && !is_secure_access) { 107 if (getIntGroup(int_id) != Gicv3::G1NS) { 108 // RAZ/WI for non-secure accesses for secure interrupts 109 continue; 110 } else { 111 // NS view 112 prio = (prio << 1) & 0xff; 113 } 114 } 115 116 value |= prio << (i * 8); 117 } 118 119 return value; 120 } 121 122 switch (addr) { 123 case GICR_CTLR: { // Control Register 124 uint64_t value = 0; 125 126 if (DPG1S) { 127 value |= GICR_CTLR_DPG1S; 128 } 129 130 if (DPG1NS) { 131 value |= GICR_CTLR_DPG1NS; 132 } 133 134 if (DPG0) { 135 value |= GICR_CTLR_DPG0; 136 } 137
| 99} 100 101uint64_t 102Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access) 103{ 104 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 105 uint64_t value = 0; 106 int first_intid = addr - GICR_IPRIORITYR.start(); 107 108 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 109 uint8_t prio = irqPriority[int_id]; 110 111 if (!distributor->DS && !is_secure_access) { 112 if (getIntGroup(int_id) != Gicv3::G1NS) { 113 // RAZ/WI for non-secure accesses for secure interrupts 114 continue; 115 } else { 116 // NS view 117 prio = (prio << 1) & 0xff; 118 } 119 } 120 121 value |= prio << (i * 8); 122 } 123 124 return value; 125 } 126 127 switch (addr) { 128 case GICR_CTLR: { // Control Register 129 uint64_t value = 0; 130 131 if (DPG1S) { 132 value |= GICR_CTLR_DPG1S; 133 } 134 135 if (DPG1NS) { 136 value |= GICR_CTLR_DPG1NS; 137 } 138 139 if (DPG0) { 140 value |= GICR_CTLR_DPG0; 141 } 142
|
| 143 if (EnableLPIs) { 144 value |= GICR_CTLR_ENABLE_LPIS; 145 } 146
|
138 return value; 139 } 140 141 case GICR_IIDR: // Implementer Identification Register 142 //return 0x43b; // r0p0 GIC-500 143 return 0; 144 145 case GICR_TYPER: { // Type Register 146 /* 147 * Affinity_Value [63:32] == X 148 * (The identity of the PE associated with this Redistributor) 149 * CommonLPIAff [25:24] == 01 150 * (All Redistributors with the same Aff3 value must share an 151 * LPI Configuration table) 152 * Processor_Number [23:8] == X 153 * (A unique identifier for the PE) 154 * DPGS [5] == 1 155 * (GICR_CTLR.DPG* bits are supported) 156 * Last [4] == X 157 * (This Redistributor is the highest-numbered Redistributor in 158 * a series of contiguous Redistributor pages)
| 147 return value; 148 } 149 150 case GICR_IIDR: // Implementer Identification Register 151 //return 0x43b; // r0p0 GIC-500 152 return 0; 153 154 case GICR_TYPER: { // Type Register 155 /* 156 * Affinity_Value [63:32] == X 157 * (The identity of the PE associated with this Redistributor) 158 * CommonLPIAff [25:24] == 01 159 * (All Redistributors with the same Aff3 value must share an 160 * LPI Configuration table) 161 * Processor_Number [23:8] == X 162 * (A unique identifier for the PE) 163 * DPGS [5] == 1 164 * (GICR_CTLR.DPG* bits are supported) 165 * Last [4] == X 166 * (This Redistributor is the highest-numbered Redistributor in 167 * a series of contiguous Redistributor pages)
|
159 * DirectLPI [3] == 0 160 * (direct injection of LPIs not supported)
| 168 * DirectLPI [3] == 1 169 * (direct injection of LPIs supported)
|
161 * VLPIS [1] == 0 162 * (virtual LPIs not supported)
| 170 * VLPIS [1] == 0 171 * (virtual LPIs not supported)
|
163 * PLPIS [0] == 0 164 * (physical LPIs not supported)
| 172 * PLPIS [0] == 1 173 * (physical LPIs supported)
|
165 */ 166 uint64_t affinity = getAffinity(); 167 int last = cpuId == (gic->getSystem()->numContexts() - 1); 168 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
| 174 */ 175 uint64_t affinity = getAffinity(); 176 int last = cpuId == (gic->getSystem()->numContexts() - 1); 177 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
|
169 (1 << 5) | (last << 4);
| 178 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
|
170 } 171 172 case GICR_WAKER: // Wake Register 173 if (!distributor->DS && !is_secure_access) { 174 // RAZ/WI for non-secure accesses 175 return 0; 176 } 177 178 if (peInLowPowerState) { 179 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep; 180 } else { 181 return 0; 182 } 183 184 case GICR_PIDR0: { // Peripheral ID0 Register 185 uint8_t part_0 = 0x92; // Part number, bits[7:0] 186 return part_0; 187 } 188 189 case GICR_PIDR1: { // Peripheral ID1 Register 190 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0] 191 uint8_t part_1 = 0x4; // Part number, bits[11:8] 192 return (des_0 << 4) | (part_1 << 0); 193 } 194 195 case GICR_PIDR2: { // Peripheral ID2 Register 196 uint8_t arch_rev = 0x3; // 0x3 GICv3 197 uint8_t jedec = 0x1; // JEP code 198 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4] 199 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0); 200 } 201 202 case GICR_PIDR3: // Peripheral ID3 Register 203 return 0x0; // Implementation defined 204 205 case GICR_PIDR4: { // Peripheral ID4 Register 206 uint8_t size = 0x4; // 64 KB software visible page 207 uint8_t des_2 = 0x4; // ARM implementation 208 return (size << 4) | (des_2 << 0); 209 } 210 211 case GICR_PIDR5: // Peripheral ID5 Register 212 case GICR_PIDR6: // Peripheral ID6 Register 213 case GICR_PIDR7: // Peripheral ID7 Register 214 return 0; // RES0 215 216 case GICR_IGROUPR0: { // Interrupt Group Register 0 217 uint64_t value = 0; 218 219 if (!distributor->DS && !is_secure_access) { 220 // RAZ/WI for non-secure accesses 221 return 0; 222 } 223 224 for (int int_id = 0; int_id < 8 * size; int_id++) { 225 value |= (irqGroup[int_id] << int_id); 226 } 227 228 return value; 229 } 230 231 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 232 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0 233 uint64_t value = 0; 234 235 for (int int_id = 0; int_id < 8 * size; int_id++) { 236 if (!distributor->DS && !is_secure_access) { 237 // RAZ/WI for non-secure accesses for secure interrupts 238 if (getIntGroup(int_id) != Gicv3::G1NS) { 239 continue; 240 } 241 } 242 243 if (irqEnabled[int_id]) { 244 value |= (1 << int_id); 245 } 246 } 247 248 return value; 249 } 250 251 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0 252 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0 253 uint64_t value = 0; 254 255 for (int int_id = 0; int_id < 8 * size; int_id++) { 256 if (!distributor->DS && !is_secure_access) { 257 // RAZ/WI for non-secure accesses for secure interrupts 258 if (getIntGroup(int_id) != Gicv3::G1NS) { 259 continue; 260 } 261 } 262 263 value |= (irqPending[int_id] << int_id); 264 } 265 266 return value; 267 } 268 269 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 270 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0 271 uint64_t value = 0; 272 273 for (int int_id = 0; int_id < 8 * size; int_id++) { 274 if (!distributor->DS && !is_secure_access) { 275 // RAZ/WI for non-secure accesses for secure interrupts 276 if (getIntGroup(int_id) != Gicv3::G1NS) { 277 continue; 278 } 279 } 280 281 value |= irqActive[int_id] << int_id; 282 } 283 284 return value; 285 } 286 287 case GICR_ICFGR0: // SGI Configuration Register 288 case GICR_ICFGR1: { // PPI Configuration Register 289 uint64_t value = 0; 290 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX; 291 292 for (int i = 0, int_id = first_int_id; i < 32; 293 i = i + 2, int_id++) { 294 if (!distributor->DS && !is_secure_access) { 295 // RAZ/WI for non-secure accesses for secure interrupts 296 if (getIntGroup(int_id) != Gicv3::G1NS) { 297 continue; 298 } 299 } 300 301 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 302 value |= (0x2) << i; 303 } 304 } 305 306 return value; 307 } 308 309 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 310 uint64_t value = 0; 311 312 if (distributor->DS) { 313 value = 0; 314 } else { 315 if (!is_secure_access) { 316 // RAZ/WI for non-secure accesses 317 value = 0; 318 } else { 319 for (int int_id = 0; int_id < 8 * size; int_id++) { 320 value |= irqGrpmod[int_id] << int_id; 321 } 322 } 323 } 324 325 return value; 326 } 327 328 case GICR_NSACR: { // Non-secure Access Control Register 329 uint64_t value = 0; 330 331 if (distributor->DS) { 332 // RAZ/WI 333 value = 0; 334 } else { 335 if (!is_secure_access) { 336 // RAZ/WI 337 value = 0; 338 } else { 339 for (int i = 0, int_id = 0; i < 8 * size; 340 i = i + 2, int_id++) { 341 value |= irqNsacr[int_id] << i; 342 } 343 } 344 } 345 346 return value; 347 } 348
| 179 } 180 181 case GICR_WAKER: // Wake Register 182 if (!distributor->DS && !is_secure_access) { 183 // RAZ/WI for non-secure accesses 184 return 0; 185 } 186 187 if (peInLowPowerState) { 188 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep; 189 } else { 190 return 0; 191 } 192 193 case GICR_PIDR0: { // Peripheral ID0 Register 194 uint8_t part_0 = 0x92; // Part number, bits[7:0] 195 return part_0; 196 } 197 198 case GICR_PIDR1: { // Peripheral ID1 Register 199 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0] 200 uint8_t part_1 = 0x4; // Part number, bits[11:8] 201 return (des_0 << 4) | (part_1 << 0); 202 } 203 204 case GICR_PIDR2: { // Peripheral ID2 Register 205 uint8_t arch_rev = 0x3; // 0x3 GICv3 206 uint8_t jedec = 0x1; // JEP code 207 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4] 208 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0); 209 } 210 211 case GICR_PIDR3: // Peripheral ID3 Register 212 return 0x0; // Implementation defined 213 214 case GICR_PIDR4: { // Peripheral ID4 Register 215 uint8_t size = 0x4; // 64 KB software visible page 216 uint8_t des_2 = 0x4; // ARM implementation 217 return (size << 4) | (des_2 << 0); 218 } 219 220 case GICR_PIDR5: // Peripheral ID5 Register 221 case GICR_PIDR6: // Peripheral ID6 Register 222 case GICR_PIDR7: // Peripheral ID7 Register 223 return 0; // RES0 224 225 case GICR_IGROUPR0: { // Interrupt Group Register 0 226 uint64_t value = 0; 227 228 if (!distributor->DS && !is_secure_access) { 229 // RAZ/WI for non-secure accesses 230 return 0; 231 } 232 233 for (int int_id = 0; int_id < 8 * size; int_id++) { 234 value |= (irqGroup[int_id] << int_id); 235 } 236 237 return value; 238 } 239 240 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 241 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0 242 uint64_t value = 0; 243 244 for (int int_id = 0; int_id < 8 * size; int_id++) { 245 if (!distributor->DS && !is_secure_access) { 246 // RAZ/WI for non-secure accesses for secure interrupts 247 if (getIntGroup(int_id) != Gicv3::G1NS) { 248 continue; 249 } 250 } 251 252 if (irqEnabled[int_id]) { 253 value |= (1 << int_id); 254 } 255 } 256 257 return value; 258 } 259 260 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0 261 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0 262 uint64_t value = 0; 263 264 for (int int_id = 0; int_id < 8 * size; int_id++) { 265 if (!distributor->DS && !is_secure_access) { 266 // RAZ/WI for non-secure accesses for secure interrupts 267 if (getIntGroup(int_id) != Gicv3::G1NS) { 268 continue; 269 } 270 } 271 272 value |= (irqPending[int_id] << int_id); 273 } 274 275 return value; 276 } 277 278 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 279 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0 280 uint64_t value = 0; 281 282 for (int int_id = 0; int_id < 8 * size; int_id++) { 283 if (!distributor->DS && !is_secure_access) { 284 // RAZ/WI for non-secure accesses for secure interrupts 285 if (getIntGroup(int_id) != Gicv3::G1NS) { 286 continue; 287 } 288 } 289 290 value |= irqActive[int_id] << int_id; 291 } 292 293 return value; 294 } 295 296 case GICR_ICFGR0: // SGI Configuration Register 297 case GICR_ICFGR1: { // PPI Configuration Register 298 uint64_t value = 0; 299 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX; 300 301 for (int i = 0, int_id = first_int_id; i < 32; 302 i = i + 2, int_id++) { 303 if (!distributor->DS && !is_secure_access) { 304 // RAZ/WI for non-secure accesses for secure interrupts 305 if (getIntGroup(int_id) != Gicv3::G1NS) { 306 continue; 307 } 308 } 309 310 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 311 value |= (0x2) << i; 312 } 313 } 314 315 return value; 316 } 317 318 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 319 uint64_t value = 0; 320 321 if (distributor->DS) { 322 value = 0; 323 } else { 324 if (!is_secure_access) { 325 // RAZ/WI for non-secure accesses 326 value = 0; 327 } else { 328 for (int int_id = 0; int_id < 8 * size; int_id++) { 329 value |= irqGrpmod[int_id] << int_id; 330 } 331 } 332 } 333 334 return value; 335 } 336 337 case GICR_NSACR: { // Non-secure Access Control Register 338 uint64_t value = 0; 339 340 if (distributor->DS) { 341 // RAZ/WI 342 value = 0; 343 } else { 344 if (!is_secure_access) { 345 // RAZ/WI 346 value = 0; 347 } else { 348 for (int i = 0, int_id = 0; i < 8 * size; 349 i = i + 2, int_id++) { 350 value |= irqNsacr[int_id] << i; 351 } 352 } 353 } 354 355 return value; 356 } 357
|
| 358 case GICR_PROPBASER: // Redistributor Properties Base Address Register 359 // OuterCache, bits [58:56] 360 // 000 Memory type defined in InnerCache field 361 // Physical_Address, bits [51:12] 362 // Bits [51:12] of the physical address containing the LPI 363 // Configuration table 364 // Shareability, bits [11:10] 365 // 00 Non-shareable 366 // InnerCache, bits [9:7] 367 // 000 Device-nGnRnE 368 // IDbits, bits [4:0] 369 // limited by GICD_TYPER.IDbits 370 return lpiConfigurationTablePtr | lpiIDBits; 371 372 // Redistributor LPI Pending Table Base Address Register 373 case GICR_PENDBASER: 374 // PTZ, bit [62] 375 // Pending Table Zero 376 // OuterCache, bits [58:56] 377 // 000 Memory type defined in InnerCache field 378 // Physical_Address, bits [51:16] 379 // Bits [51:16] of the physical address containing the LPI Pending 380 // table 381 // Shareability, bits [11:10] 382 // 00 Non-shareable 383 // InnerCache, bits [9:7] 384 // 000 Device-nGnRnE 385 return lpiPendingTablePtr; 386 387 // Redistributor Synchronize Register 388 case GICR_SYNCR: 389 return 0; 390
|
349 default: 350 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr); 351 break; 352 } 353} 354 355void 356Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size, 357 bool is_secure_access) 358{ 359 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 360 int first_intid = addr - GICR_IPRIORITYR.start(); 361 362 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 363 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 364 365 if (!distributor->DS && !is_secure_access) { 366 if (getIntGroup(int_id) != Gicv3::G1NS) { 367 // RAZ/WI for non-secure accesses for secure interrupts 368 continue; 369 } else { 370 // NS view 371 prio = 0x80 | (prio >> 1); 372 } 373 } 374 375 irqPriority[int_id] = prio; 376 DPRINTF(GIC, "Gicv3Redistributor::write(): " 377 "int_id %d priority %d\n", int_id, irqPriority[int_id]); 378 } 379 380 return; 381 } 382 383 switch (addr) { 384 case GICR_CTLR: {
| 391 default: 392 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr); 393 break; 394 } 395} 396 397void 398Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size, 399 bool is_secure_access) 400{ 401 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 402 int first_intid = addr - GICR_IPRIORITYR.start(); 403 404 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 405 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 406 407 if (!distributor->DS && !is_secure_access) { 408 if (getIntGroup(int_id) != Gicv3::G1NS) { 409 // RAZ/WI for non-secure accesses for secure interrupts 410 continue; 411 } else { 412 // NS view 413 prio = 0x80 | (prio >> 1); 414 } 415 } 416 417 irqPriority[int_id] = prio; 418 DPRINTF(GIC, "Gicv3Redistributor::write(): " 419 "int_id %d priority %d\n", int_id, irqPriority[int_id]); 420 } 421 422 return; 423 } 424 425 switch (addr) { 426 case GICR_CTLR: {
|
385 // GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0
| 427 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0 428 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
|
386 DPG1S = data & GICR_CTLR_DPG1S; 387 DPG1NS = data & GICR_CTLR_DPG1NS; 388 DPG0 = data & GICR_CTLR_DPG0; 389 break; 390 } 391 392 case GICR_WAKER: // Wake Register 393 if (!distributor->DS && !is_secure_access) { 394 // RAZ/WI for non-secure accesses 395 return; 396 } 397 398 if (not peInLowPowerState and 399 (data & GICR_WAKER_ProcessorSleep)) { 400 DPRINTF(GIC, "Gicv3Redistributor::write(): " 401 "PE entering in low power state\n"); 402 } else if (peInLowPowerState and 403 not(data & GICR_WAKER_ProcessorSleep)) { 404 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n"); 405 } 406 407 peInLowPowerState = data & GICR_WAKER_ProcessorSleep; 408 break; 409 410 case GICR_IGROUPR0: // Interrupt Group Register 0 411 if (!distributor->DS && !is_secure_access) { 412 // RAZ/WI for non-secure accesses 413 return; 414 } 415 416 for (int int_id = 0; int_id < 8 * size; int_id++) { 417 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0; 418 DPRINTF(GIC, "Gicv3Redistributor::write(): " 419 "int_id %d group %d\n", int_id, irqGroup[int_id]); 420 } 421 422 break; 423 424 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 425 for (int int_id = 0; int_id < 8 * size; int_id++) { 426 if (!distributor->DS && !is_secure_access) { 427 // RAZ/WI for non-secure accesses for secure interrupts 428 if (getIntGroup(int_id) != Gicv3::G1NS) { 429 continue; 430 } 431 } 432 433 bool enable = data & (1 << int_id) ? 1 : 0; 434 435 if (enable) { 436 irqEnabled[int_id] = true; 437 } 438 439 DPRINTF(GIC, "Gicv3Redistributor::write(): " 440 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 441 } 442 443 break; 444 445 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0 446 for (int int_id = 0; int_id < 8 * size; int_id++) { 447 if (!distributor->DS && !is_secure_access) { 448 // RAZ/WI for non-secure accesses for secure interrupts 449 if (getIntGroup(int_id) != Gicv3::G1NS) { 450 continue; 451 } 452 } 453 454 bool disable = data & (1 << int_id) ? 1 : 0; 455 456 if (disable) { 457 irqEnabled[int_id] = false; 458 } 459 460 DPRINTF(GIC, "Gicv3Redistributor::write(): " 461 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 462 } 463 464 break; 465 466 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0 467 for (int int_id = 0; int_id < 8 * size; int_id++) { 468 if (!distributor->DS && !is_secure_access) { 469 // RAZ/WI for non-secure accesses for secure interrupts 470 if (getIntGroup(int_id) != Gicv3::G1NS) { 471 continue; 472 } 473 } 474 475 bool pending = data & (1 << int_id) ? 1 : 0; 476 477 if (pending) { 478 DPRINTF(GIC, "Gicv3Redistributor::write() " 479 "(GICR_ISPENDR0): int_id %d (PPI) " 480 "pending bit set\n", int_id); 481 irqPending[int_id] = true; 482 } 483 } 484 485 updateAndInformCPUInterface(); 486 break; 487 488 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0 489 for (int int_id = 0; int_id < 8 * size; int_id++) { 490 if (!distributor->DS && !is_secure_access) { 491 // RAZ/WI for non-secure accesses for secure interrupts 492 if (getIntGroup(int_id) != Gicv3::G1NS) { 493 continue; 494 } 495 } 496 497 bool clear = data & (1 << int_id) ? 1 : 0; 498 499 if (clear) { 500 irqPending[int_id] = false; 501 } 502 } 503 504 break; 505 506 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 507 for (int int_id = 0; int_id < 8 * size; int_id++) { 508 if (!distributor->DS && !is_secure_access) { 509 // RAZ/WI for non-secure accesses for secure interrupts 510 if (getIntGroup(int_id) != Gicv3::G1NS) { 511 continue; 512 } 513 } 514 515 bool activate = data & (1 << int_id) ? 1 : 0; 516 517 if (activate) { 518 if (!irqActive[int_id]) { 519 DPRINTF(GIC, "Gicv3Redistributor::write(): " 520 "int_id %d active set\n", int_id); 521 } 522 523 irqActive[int_id] = true; 524 } 525 } 526 527 break; 528 529 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0 530 for (int int_id = 0; int_id < 8 * size; int_id++) { 531 if (!distributor->DS && !is_secure_access) { 532 // RAZ/WI for non-secure accesses for secure interrupts 533 if (getIntGroup(int_id) != Gicv3::G1NS) { 534 continue; 535 } 536 } 537 538 bool clear = data & (1 << int_id) ? 1 : 0; 539 540 if (clear) { 541 if (irqActive[int_id]) { 542 DPRINTF(GIC, "Gicv3Redistributor::write(): " 543 "int_id %d active cleared\n", int_id); 544 } 545 546 irqActive[int_id] = false; 547 } 548 } 549 550 break; 551 552 case GICR_ICFGR1: { // PPI Configuration Register 553 int first_intid = Gicv3::SGI_MAX; 554 555 for (int i = 0, int_id = first_intid; i < 8 * size; 556 i = i + 2, int_id++) { 557 if (!distributor->DS && !is_secure_access) { 558 // RAZ/WI for non-secure accesses for secure interrupts 559 if (getIntGroup(int_id) != Gicv3::G1NS) { 560 continue; 561 } 562 } 563 564 irqConfig[int_id] = data & (0x2 << i) 565 ? Gicv3::INT_EDGE_TRIGGERED : 566 Gicv3::INT_LEVEL_SENSITIVE; 567 DPRINTF(GIC, "Gicv3Redistributor::write(): " 568 "int_id %d (PPI) config %d\n", 569 int_id, irqConfig[int_id]); 570 } 571 572 break; 573 } 574 575 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 576 if (distributor->DS) { 577 // RAZ/WI if secutiry disabled 578 } else { 579 for (int int_id = 0; int_id < 8 * size; int_id++) { 580 if (!is_secure_access) { 581 // RAZ/WI for non-secure accesses 582 continue; 583 } 584 585 irqGrpmod[int_id] = data & (1 << int_id); 586 } 587 } 588 589 break; 590 } 591 592 case GICR_NSACR: { // Non-secure Access Control Register 593 if (distributor->DS) { 594 // RAZ/WI 595 } else { 596 if (!is_secure_access) { 597 // RAZ/WI 598 } else { 599 for (int i = 0, int_id = 0; i < 8 * size; 600 i = i + 2, int_id++) { 601 irqNsacr[int_id] = (data >> i) & 0x3; 602 } 603 } 604 } 605 606 break; 607 } 608
| 429 DPG1S = data & GICR_CTLR_DPG1S; 430 DPG1NS = data & GICR_CTLR_DPG1NS; 431 DPG0 = data & GICR_CTLR_DPG0; 432 break; 433 } 434 435 case GICR_WAKER: // Wake Register 436 if (!distributor->DS && !is_secure_access) { 437 // RAZ/WI for non-secure accesses 438 return; 439 } 440 441 if (not peInLowPowerState and 442 (data & GICR_WAKER_ProcessorSleep)) { 443 DPRINTF(GIC, "Gicv3Redistributor::write(): " 444 "PE entering in low power state\n"); 445 } else if (peInLowPowerState and 446 not(data & GICR_WAKER_ProcessorSleep)) { 447 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n"); 448 } 449 450 peInLowPowerState = data & GICR_WAKER_ProcessorSleep; 451 break; 452 453 case GICR_IGROUPR0: // Interrupt Group Register 0 454 if (!distributor->DS && !is_secure_access) { 455 // RAZ/WI for non-secure accesses 456 return; 457 } 458 459 for (int int_id = 0; int_id < 8 * size; int_id++) { 460 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0; 461 DPRINTF(GIC, "Gicv3Redistributor::write(): " 462 "int_id %d group %d\n", int_id, irqGroup[int_id]); 463 } 464 465 break; 466 467 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 468 for (int int_id = 0; int_id < 8 * size; int_id++) { 469 if (!distributor->DS && !is_secure_access) { 470 // RAZ/WI for non-secure accesses for secure interrupts 471 if (getIntGroup(int_id) != Gicv3::G1NS) { 472 continue; 473 } 474 } 475 476 bool enable = data & (1 << int_id) ? 1 : 0; 477 478 if (enable) { 479 irqEnabled[int_id] = true; 480 } 481 482 DPRINTF(GIC, "Gicv3Redistributor::write(): " 483 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 484 } 485 486 break; 487 488 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0 489 for (int int_id = 0; int_id < 8 * size; int_id++) { 490 if (!distributor->DS && !is_secure_access) { 491 // RAZ/WI for non-secure accesses for secure interrupts 492 if (getIntGroup(int_id) != Gicv3::G1NS) { 493 continue; 494 } 495 } 496 497 bool disable = data & (1 << int_id) ? 1 : 0; 498 499 if (disable) { 500 irqEnabled[int_id] = false; 501 } 502 503 DPRINTF(GIC, "Gicv3Redistributor::write(): " 504 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 505 } 506 507 break; 508 509 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0 510 for (int int_id = 0; int_id < 8 * size; int_id++) { 511 if (!distributor->DS && !is_secure_access) { 512 // RAZ/WI for non-secure accesses for secure interrupts 513 if (getIntGroup(int_id) != Gicv3::G1NS) { 514 continue; 515 } 516 } 517 518 bool pending = data & (1 << int_id) ? 1 : 0; 519 520 if (pending) { 521 DPRINTF(GIC, "Gicv3Redistributor::write() " 522 "(GICR_ISPENDR0): int_id %d (PPI) " 523 "pending bit set\n", int_id); 524 irqPending[int_id] = true; 525 } 526 } 527 528 updateAndInformCPUInterface(); 529 break; 530 531 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0 532 for (int int_id = 0; int_id < 8 * size; int_id++) { 533 if (!distributor->DS && !is_secure_access) { 534 // RAZ/WI for non-secure accesses for secure interrupts 535 if (getIntGroup(int_id) != Gicv3::G1NS) { 536 continue; 537 } 538 } 539 540 bool clear = data & (1 << int_id) ? 1 : 0; 541 542 if (clear) { 543 irqPending[int_id] = false; 544 } 545 } 546 547 break; 548 549 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 550 for (int int_id = 0; int_id < 8 * size; int_id++) { 551 if (!distributor->DS && !is_secure_access) { 552 // RAZ/WI for non-secure accesses for secure interrupts 553 if (getIntGroup(int_id) != Gicv3::G1NS) { 554 continue; 555 } 556 } 557 558 bool activate = data & (1 << int_id) ? 1 : 0; 559 560 if (activate) { 561 if (!irqActive[int_id]) { 562 DPRINTF(GIC, "Gicv3Redistributor::write(): " 563 "int_id %d active set\n", int_id); 564 } 565 566 irqActive[int_id] = true; 567 } 568 } 569 570 break; 571 572 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0 573 for (int int_id = 0; int_id < 8 * size; int_id++) { 574 if (!distributor->DS && !is_secure_access) { 575 // RAZ/WI for non-secure accesses for secure interrupts 576 if (getIntGroup(int_id) != Gicv3::G1NS) { 577 continue; 578 } 579 } 580 581 bool clear = data & (1 << int_id) ? 1 : 0; 582 583 if (clear) { 584 if (irqActive[int_id]) { 585 DPRINTF(GIC, "Gicv3Redistributor::write(): " 586 "int_id %d active cleared\n", int_id); 587 } 588 589 irqActive[int_id] = false; 590 } 591 } 592 593 break; 594 595 case GICR_ICFGR1: { // PPI Configuration Register 596 int first_intid = Gicv3::SGI_MAX; 597 598 for (int i = 0, int_id = first_intid; i < 8 * size; 599 i = i + 2, int_id++) { 600 if (!distributor->DS && !is_secure_access) { 601 // RAZ/WI for non-secure accesses for secure interrupts 602 if (getIntGroup(int_id) != Gicv3::G1NS) { 603 continue; 604 } 605 } 606 607 irqConfig[int_id] = data & (0x2 << i) 608 ? Gicv3::INT_EDGE_TRIGGERED : 609 Gicv3::INT_LEVEL_SENSITIVE; 610 DPRINTF(GIC, "Gicv3Redistributor::write(): " 611 "int_id %d (PPI) config %d\n", 612 int_id, irqConfig[int_id]); 613 } 614 615 break; 616 } 617 618 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 619 if (distributor->DS) { 620 // RAZ/WI if secutiry disabled 621 } else { 622 for (int int_id = 0; int_id < 8 * size; int_id++) { 623 if (!is_secure_access) { 624 // RAZ/WI for non-secure accesses 625 continue; 626 } 627 628 irqGrpmod[int_id] = data & (1 << int_id); 629 } 630 } 631 632 break; 633 } 634 635 case GICR_NSACR: { // Non-secure Access Control Register 636 if (distributor->DS) { 637 // RAZ/WI 638 } else { 639 if (!is_secure_access) { 640 // RAZ/WI 641 } else { 642 for (int i = 0, int_id = 0; i < 8 * size; 643 i = i + 2, int_id++) { 644 irqNsacr[int_id] = (data >> i) & 0x3; 645 } 646 } 647 } 648 649 break; 650 } 651
|
| 652 case GICR_SETLPIR: // Set LPI Pending Register 653 setClrLPI(data, true); 654 break; 655 656 case GICR_CLRLPIR: // Clear LPI Pending Register 657 setClrLPI(data, false); 658 break; 659 660 case GICR_PROPBASER: { // Redistributor Properties Base Address Register 661 // OuterCache, bits [58:56] 662 // 000 Memory type defined in InnerCache field 663 // Physical_Address, bits [51:12] 664 // Bits [51:12] of the physical address containing the LPI 665 // Configuration table 666 // Shareability, bits [11:10] 667 // 00 Non-shareable 668 // InnerCache, bits [9:7] 669 // 000 Device-nGnRnE 670 // IDbits, bits [4:0] 671 // limited by GICD_TYPER.IDbits (= 0xf) 672 lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000; 673 lpiIDBits = data & 0x1f; 674 675 // 0xf here matches the value of GICD_TYPER.IDbits. 676 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded 677 // value 678 if (lpiIDBits > 0xf) { 679 lpiIDBits = 0xf; 680 } 681 682 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 683 uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1; 684 lpiConfigurationTable.resize(number_lpis); 685 break; 686 } 687 688 // Redistributor LPI Pending Table Base Address Register 689 case GICR_PENDBASER: 690 // PTZ, bit [62] 691 // Pending Table Zero 692 // OuterCache, bits [58:56] 693 // 000 Memory type defined in InnerCache field 694 // Physical_Address, bits [51:16] 695 // Bits [51:16] of the physical address containing the LPI Pending 696 // table 697 // Shareability, bits [11:10] 698 // 00 Non-shareable 699 // InnerCache, bits [9:7] 700 // 000 Device-nGnRnE 701 lpiPendingTablePtr = data & 0xFFFFFFFFF0000; 702 break; 703 704 case GICR_INVLPIR: { // Redistributor Invalidate LPI Register 705 uint32_t lpi_id = data & 0xffffffff; 706 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 707 708 if (lpi_id > largest_lpi_id) { 709 return; 710 } 711 712 uint32_t lpi_table_entry_index = lpi_id - SMALLEST_LPI_ID; 713 invalLpiConfig(lpi_table_entry_index); 714 break; 715 } 716 717 case GICR_INVALLR: { // Redistributor Invalidate All Register 718 for (int lpi_table_entry_index = 0; 719 lpi_table_entry_index < lpiConfigurationTable.size(); 720 lpi_table_entry_index++) { 721 invalLpiConfig(lpi_table_entry_index); 722 } 723 724 break; 725 } 726
|
609 default: 610 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr); 611 break; 612 } 613} 614 615void
| 727 default: 728 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr); 729 break; 730 } 731} 732 733void
|
| 734Gicv3Redistributor::invalLpiConfig(uint32_t lpi_entry_index) 735{ 736 Addr lpi_table_entry_ptr = lpiConfigurationTablePtr + 737 lpi_entry_index * sizeof(LPIConfigurationTableEntry); 738 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 739 tc->getVirtProxy().readBlob(lpi_table_entry_ptr, 740 (uint8_t*) &lpiConfigurationTable[lpi_entry_index], 741 sizeof(LPIConfigurationTableEntry)); 742} 743 744void
|
616Gicv3Redistributor::sendPPInt(uint32_t int_id) 617{ 618 assert((int_id >= Gicv3::SGI_MAX) && 619 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 620 irqPending[int_id] = true; 621 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): " 622 "int_id %d (PPI) pending bit set\n", int_id); 623 updateAndInformCPUInterface(); 624} 625 626void 627Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns) 628{ 629 assert(int_id < Gicv3::SGI_MAX); 630 Gicv3::GroupId int_group = getIntGroup(int_id); 631 632 // asked for secure group 1 633 // configured as group 0 634 // send group 0 635 if (int_group == Gicv3::G0S && group == Gicv3::G1S) { 636 group = Gicv3::G0S; 637 } 638 639 if (group == Gicv3::G0S and int_group != Gicv3::G0S) { 640 return; 641 } 642 643 if (ns && distributor->DS == 0) { 644 int nsaccess = irqNsacr[int_id]; 645 646 if ((int_group == Gicv3::G0S && nsaccess < 1) || 647 (int_group == Gicv3::G1S && nsaccess < 2)) { 648 return; 649 } 650 } 651 652 irqPending[int_id] = true; 653 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): " 654 "int_id %d (SGI) pending bit set\n", int_id); 655 updateAndInformCPUInterface(); 656} 657 658Gicv3::IntStatus 659Gicv3Redistributor::intStatus(uint32_t int_id) 660{ 661 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX); 662 663 if (irqPending[int_id]) { 664 if (irqActive[int_id]) { 665 return Gicv3::INT_ACTIVE_PENDING; 666 } 667 668 return Gicv3::INT_PENDING; 669 } else if (irqActive[int_id]) { 670 return Gicv3::INT_ACTIVE; 671 } else { 672 return Gicv3::INT_INACTIVE; 673 } 674} 675 676/* 677 * Recalculate the highest priority pending interrupt after a 678 * change to redistributor state. 679 */ 680void 681Gicv3Redistributor::update() 682{ 683 bool new_hppi = false; 684 685 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) { 686 Gicv3::GroupId int_group = getIntGroup(int_id); 687 bool group_enabled = distributor->groupEnabled(int_group); 688 689 if (irqPending[int_id] && irqEnabled[int_id] && 690 !irqActive[int_id] && group_enabled) { 691 if ((irqPriority[int_id] < cpuInterface->hppi.prio) || 692 /* 693 * Multiple pending ints with same priority. 694 * Implementation choice which one to signal. 695 * Our implementation selects the one with the lower id. 696 */ 697 (irqPriority[int_id] == cpuInterface->hppi.prio && 698 int_id < cpuInterface->hppi.intid)) { 699 cpuInterface->hppi.intid = int_id; 700 cpuInterface->hppi.prio = irqPriority[int_id]; 701 cpuInterface->hppi.group = int_group; 702 new_hppi = true; 703 } 704 } 705 } 706
| 745Gicv3Redistributor::sendPPInt(uint32_t int_id) 746{ 747 assert((int_id >= Gicv3::SGI_MAX) && 748 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 749 irqPending[int_id] = true; 750 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): " 751 "int_id %d (PPI) pending bit set\n", int_id); 752 updateAndInformCPUInterface(); 753} 754 755void 756Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns) 757{ 758 assert(int_id < Gicv3::SGI_MAX); 759 Gicv3::GroupId int_group = getIntGroup(int_id); 760 761 // asked for secure group 1 762 // configured as group 0 763 // send group 0 764 if (int_group == Gicv3::G0S && group == Gicv3::G1S) { 765 group = Gicv3::G0S; 766 } 767 768 if (group == Gicv3::G0S and int_group != Gicv3::G0S) { 769 return; 770 } 771 772 if (ns && distributor->DS == 0) { 773 int nsaccess = irqNsacr[int_id]; 774 775 if ((int_group == Gicv3::G0S && nsaccess < 1) || 776 (int_group == Gicv3::G1S && nsaccess < 2)) { 777 return; 778 } 779 } 780 781 irqPending[int_id] = true; 782 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): " 783 "int_id %d (SGI) pending bit set\n", int_id); 784 updateAndInformCPUInterface(); 785} 786 787Gicv3::IntStatus 788Gicv3Redistributor::intStatus(uint32_t int_id) 789{ 790 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX); 791 792 if (irqPending[int_id]) { 793 if (irqActive[int_id]) { 794 return Gicv3::INT_ACTIVE_PENDING; 795 } 796 797 return Gicv3::INT_PENDING; 798 } else if (irqActive[int_id]) { 799 return Gicv3::INT_ACTIVE; 800 } else { 801 return Gicv3::INT_INACTIVE; 802 } 803} 804 805/* 806 * Recalculate the highest priority pending interrupt after a 807 * change to redistributor state. 808 */ 809void 810Gicv3Redistributor::update() 811{ 812 bool new_hppi = false; 813 814 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) { 815 Gicv3::GroupId int_group = getIntGroup(int_id); 816 bool group_enabled = distributor->groupEnabled(int_group); 817 818 if (irqPending[int_id] && irqEnabled[int_id] && 819 !irqActive[int_id] && group_enabled) { 820 if ((irqPriority[int_id] < cpuInterface->hppi.prio) || 821 /* 822 * Multiple pending ints with same priority. 823 * Implementation choice which one to signal. 824 * Our implementation selects the one with the lower id. 825 */ 826 (irqPriority[int_id] == cpuInterface->hppi.prio && 827 int_id < cpuInterface->hppi.intid)) { 828 cpuInterface->hppi.intid = int_id; 829 cpuInterface->hppi.prio = irqPriority[int_id]; 830 cpuInterface->hppi.group = int_group; 831 new_hppi = true; 832 } 833 } 834 } 835
|
| 836 // Check LPIs 837 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 838 char lpi_pending_table[largest_lpi_id / 8]; 839 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 840 tc->getVirtProxy().readBlob(lpiPendingTablePtr, 841 (uint8_t *) lpi_pending_table, 842 sizeof(lpi_pending_table)); 843 for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id; 844 largest_lpi_id++) { 845 uint32_t lpi_pending_entry_byte = lpi_id / 8; 846 uint8_t lpi_pending_entry_bit_position = lpi_id % 8; 847 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] & 848 1 << lpi_pending_entry_bit_position; 849 uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID; 850 bool lpi_is_enable = 851 lpiConfigurationTable[lpi_configuration_entry_index].enable; 852 // LPIs are always Non-secure Group 1 interrupts, 853 // in a system where two Security states are enabled. 854 Gicv3::GroupId lpi_group = Gicv3::G1NS; 855 bool group_enabled = distributor->groupEnabled(lpi_group); 856 857 if (lpi_is_pending && lpi_is_enable && group_enabled) { 858 uint8_t lpi_priority = 859 lpiConfigurationTable[lpi_configuration_entry_index].priority; 860 861 if ((lpi_priority < cpuInterface->hppi.prio) || 862 (lpi_priority == cpuInterface->hppi.prio && 863 lpi_id < cpuInterface->hppi.intid)) { 864 cpuInterface->hppi.intid = lpi_id; 865 cpuInterface->hppi.prio = lpi_priority; 866 cpuInterface->hppi.group = lpi_group; 867 new_hppi = true; 868 } 869 } 870 } 871
|
707 if (!new_hppi && cpuInterface->hppi.prio != 0xff && 708 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 709 distributor->fullUpdate(); 710 } 711} 712 713void
| 872 if (!new_hppi && cpuInterface->hppi.prio != 0xff && 873 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 874 distributor->fullUpdate(); 875 } 876} 877 878void
|
| 879Gicv3Redistributor::setClrLPI(uint64_t data, bool set) 880{ 881 if (!EnableLPIs) { 882 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if 883 // GICR_CTLR.EnableLPIs == 0. 884 return; 885 } 886 887 uint32_t lpi_id = data & 0xffffffff; 888 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 889 890 if (lpi_id > largest_lpi_id) { 891 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if 892 // pINTID value specifies an unimplemented LPI. 893 return; 894 } 895 896 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8); 897 uint8_t lpi_pending_entry; 898 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 899 tc->getVirtProxy().readBlob(lpi_pending_entry_ptr, 900 (uint8_t*) &lpi_pending_entry, 901 sizeof(lpi_pending_entry)); 902 uint8_t lpi_pending_entry_bit_position = lpi_id % 8; 903 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position); 904 905 if (set) { 906 if (is_set) { 907 // Writes to GICR_SETLPIR have not effect if the pINTID field 908 // corresponds to an LPI that is already pending. 909 return; 910 } 911 912 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position); 913 } else { 914 if (!is_set) { 915 // Writes to GICR_SETLPIR have not effect if the pINTID field 916 // corresponds to an LPI that is not pending. 917 return; 918 } 919 920 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position)); 921 } 922 923 tc->getVirtProxy().writeBlob(lpi_pending_entry_ptr, 924 (uint8_t*) &lpi_pending_entry, 925 sizeof(lpi_pending_entry)); 926 updateAndInformCPUInterface(); 927} 928 929void
|
714Gicv3Redistributor::updateAndInformCPUInterface() 715{ 716 update(); 717 cpuInterface->update(); 718} 719 720Gicv3::GroupId 721Gicv3Redistributor::getIntGroup(int int_id) 722{ 723 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 724 725 if (distributor->DS) { 726 if (irqGroup[int_id] == 0) { 727 return Gicv3::G0S; 728 } else { 729 return Gicv3::G1NS; 730 } 731 } else { 732 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 733 return Gicv3::G0S; 734 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 735 return Gicv3::G1NS; 736 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 737 return Gicv3::G1S; 738 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 739 return Gicv3::G1NS; 740 } 741 } 742 743 M5_UNREACHABLE; 744} 745 746void 747Gicv3Redistributor::activateIRQ(uint32_t int_id) 748{ 749 irqPending[int_id] = false; 750 irqActive[int_id] = true; 751} 752 753void 754Gicv3Redistributor::deactivateIRQ(uint32_t int_id) 755{ 756 irqActive[int_id] = false; 757} 758 759uint32_t 760Gicv3Redistributor::getAffinity() 761{ 762 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 763 uint64_t mpidr = getMPIDR(gic->getSystem(), tc); 764 /* 765 * Aff3 = MPIDR[39:32] 766 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...) 767 * Aff2 = MPIDR[23:16] 768 * Aff1 = MPIDR[15:8] 769 * Aff0 = MPIDR[7:0] 770 * affinity = Aff3.Aff2.Aff1.Aff0 771 */ 772 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff)); 773 return affinity; 774} 775 776bool 777Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) 778{ 779 if (peInLowPowerState) { 780 return false; 781 } 782 783 if (!distributor->groupEnabled(group)) { 784 return false; 785 } 786 787 if ((group == Gicv3::G1S) && DPG1S) { 788 return false; 789 } 790 791 if ((group == Gicv3::G1NS) && DPG1NS) { 792 return false; 793 } 794 795 if ((group == Gicv3::G0S) && DPG0) { 796 return false; 797 } 798 799 return true; 800} 801 802void 803Gicv3Redistributor::serialize(CheckpointOut & cp) const 804{ 805 SERIALIZE_SCALAR(peInLowPowerState); 806 SERIALIZE_CONTAINER(irqGroup); 807 SERIALIZE_CONTAINER(irqEnabled); 808 SERIALIZE_CONTAINER(irqPending); 809 SERIALIZE_CONTAINER(irqActive); 810 SERIALIZE_CONTAINER(irqPriority); 811 SERIALIZE_CONTAINER(irqConfig); 812 SERIALIZE_CONTAINER(irqGrpmod); 813 SERIALIZE_CONTAINER(irqNsacr); 814 SERIALIZE_SCALAR(DPG1S); 815 SERIALIZE_SCALAR(DPG1NS); 816 SERIALIZE_SCALAR(DPG0);
| 930Gicv3Redistributor::updateAndInformCPUInterface() 931{ 932 update(); 933 cpuInterface->update(); 934} 935 936Gicv3::GroupId 937Gicv3Redistributor::getIntGroup(int int_id) 938{ 939 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 940 941 if (distributor->DS) { 942 if (irqGroup[int_id] == 0) { 943 return Gicv3::G0S; 944 } else { 945 return Gicv3::G1NS; 946 } 947 } else { 948 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 949 return Gicv3::G0S; 950 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 951 return Gicv3::G1NS; 952 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 953 return Gicv3::G1S; 954 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 955 return Gicv3::G1NS; 956 } 957 } 958 959 M5_UNREACHABLE; 960} 961 962void 963Gicv3Redistributor::activateIRQ(uint32_t int_id) 964{ 965 irqPending[int_id] = false; 966 irqActive[int_id] = true; 967} 968 969void 970Gicv3Redistributor::deactivateIRQ(uint32_t int_id) 971{ 972 irqActive[int_id] = false; 973} 974 975uint32_t 976Gicv3Redistributor::getAffinity() 977{ 978 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 979 uint64_t mpidr = getMPIDR(gic->getSystem(), tc); 980 /* 981 * Aff3 = MPIDR[39:32] 982 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...) 983 * Aff2 = MPIDR[23:16] 984 * Aff1 = MPIDR[15:8] 985 * Aff0 = MPIDR[7:0] 986 * affinity = Aff3.Aff2.Aff1.Aff0 987 */ 988 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff)); 989 return affinity; 990} 991 992bool 993Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) 994{ 995 if (peInLowPowerState) { 996 return false; 997 } 998 999 if (!distributor->groupEnabled(group)) { 1000 return false; 1001 } 1002 1003 if ((group == Gicv3::G1S) && DPG1S) { 1004 return false; 1005 } 1006 1007 if ((group == Gicv3::G1NS) && DPG1NS) { 1008 return false; 1009 } 1010 1011 if ((group == Gicv3::G0S) && DPG0) { 1012 return false; 1013 } 1014 1015 return true; 1016} 1017 1018void 1019Gicv3Redistributor::serialize(CheckpointOut & cp) const 1020{ 1021 SERIALIZE_SCALAR(peInLowPowerState); 1022 SERIALIZE_CONTAINER(irqGroup); 1023 SERIALIZE_CONTAINER(irqEnabled); 1024 SERIALIZE_CONTAINER(irqPending); 1025 SERIALIZE_CONTAINER(irqActive); 1026 SERIALIZE_CONTAINER(irqPriority); 1027 SERIALIZE_CONTAINER(irqConfig); 1028 SERIALIZE_CONTAINER(irqGrpmod); 1029 SERIALIZE_CONTAINER(irqNsacr); 1030 SERIALIZE_SCALAR(DPG1S); 1031 SERIALIZE_SCALAR(DPG1NS); 1032 SERIALIZE_SCALAR(DPG0);
|
| 1033 SERIALIZE_SCALAR(EnableLPIs); 1034 SERIALIZE_SCALAR(lpiConfigurationTablePtr); 1035 SERIALIZE_SCALAR(lpiIDBits); 1036 SERIALIZE_SCALAR(lpiPendingTablePtr);
|
817} 818 819void 820Gicv3Redistributor::unserialize(CheckpointIn & cp) 821{ 822 UNSERIALIZE_SCALAR(peInLowPowerState); 823 UNSERIALIZE_CONTAINER(irqGroup); 824 UNSERIALIZE_CONTAINER(irqEnabled); 825 UNSERIALIZE_CONTAINER(irqPending); 826 UNSERIALIZE_CONTAINER(irqActive); 827 UNSERIALIZE_CONTAINER(irqPriority); 828 UNSERIALIZE_CONTAINER(irqConfig); 829 UNSERIALIZE_CONTAINER(irqGrpmod); 830 UNSERIALIZE_CONTAINER(irqNsacr); 831 UNSERIALIZE_SCALAR(DPG1S); 832 UNSERIALIZE_SCALAR(DPG1NS); 833 UNSERIALIZE_SCALAR(DPG0);
| 1037} 1038 1039void 1040Gicv3Redistributor::unserialize(CheckpointIn & cp) 1041{ 1042 UNSERIALIZE_SCALAR(peInLowPowerState); 1043 UNSERIALIZE_CONTAINER(irqGroup); 1044 UNSERIALIZE_CONTAINER(irqEnabled); 1045 UNSERIALIZE_CONTAINER(irqPending); 1046 UNSERIALIZE_CONTAINER(irqActive); 1047 UNSERIALIZE_CONTAINER(irqPriority); 1048 UNSERIALIZE_CONTAINER(irqConfig); 1049 UNSERIALIZE_CONTAINER(irqGrpmod); 1050 UNSERIALIZE_CONTAINER(irqNsacr); 1051 UNSERIALIZE_SCALAR(DPG1S); 1052 UNSERIALIZE_SCALAR(DPG1NS); 1053 UNSERIALIZE_SCALAR(DPG0);
|
| 1054 UNSERIALIZE_SCALAR(EnableLPIs); 1055 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr); 1056 UNSERIALIZE_SCALAR(lpiIDBits); 1057 UNSERIALIZE_SCALAR(lpiPendingTablePtr);
|
834}
| 1058}
|