1/* 2 * Copyright (c) 2010, 2013, 2015-2018 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Ali Saidi 41 * Prakash Ramrakhyani 42 */ 43 44#include "dev/arm/gic_v2.hh" 45 46#include "base/trace.hh" 47#include "debug/Checkpoint.hh" 48#include "debug/GIC.hh" 49#include "debug/IPI.hh" 50#include "debug/Interrupt.hh" 51#include "mem/packet.hh" 52#include "mem/packet_access.hh" 53 54const AddrRange GicV2::GICD_IGROUPR (0x080, 0x0ff); 55const AddrRange GicV2::GICD_ISENABLER (0x100, 0x17f); 56const AddrRange GicV2::GICD_ICENABLER (0x180, 0x1ff); 57const AddrRange GicV2::GICD_ISPENDR (0x200, 0x27f); 58const AddrRange GicV2::GICD_ICPENDR (0x280, 0x2ff); 59const AddrRange GicV2::GICD_ISACTIVER (0x300, 0x37f); 60const AddrRange GicV2::GICD_ICACTIVER (0x380, 0x3ff); 61const AddrRange GicV2::GICD_IPRIORITYR(0x400, 0x7ff); 62const AddrRange GicV2::GICD_ITARGETSR (0x800, 0xbff); 63const AddrRange GicV2::GICD_ICFGR (0xc00, 0xcff); 64 65GicV2::GicV2(const Params *p) 66 : BaseGic(p), 67 distRange(RangeSize(p->dist_addr, DIST_SIZE)), 68 cpuRange(RangeSize(p->cpu_addr, p->cpu_size)), 69 addrRanges{distRange, cpuRange}, 70 distPioDelay(p->dist_pio_delay), 71 cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency), 72 enabled(false), haveGem5Extensions(p->gem5_extensions), 73 itLines(p->it_lines), 74 intEnabled {}, pendingInt {}, activeInt {}, 75 intPriority {}, cpuTarget {}, intConfig {}, 76 cpuSgiPending {}, cpuSgiActive {}, 77 cpuSgiPendingExt {}, cpuSgiActiveExt {}, 78 cpuPpiPending {}, cpuPpiActive {}, 79 pendingDelayedInterrupts(0) 80{ 81 for (int x = 0; x < CPU_MAX; x++) { 82 iccrpr[x] = 0xff; 83 cpuControl[x] = 0; 84 cpuPriority[x] = 0xff; 85 cpuBpr[x] = GICC_BPR_MINIMUM; 86 // Initialize cpu highest int 87 cpuHighestInt[x] = SPURIOUS_INT; 88 postIntEvent[x] = 89 new EventFunctionWrapper([this, x]{ postDelayedInt(x); }, 90 "Post Interrupt to CPU");
| 1/* 2 * Copyright (c) 2010, 2013, 2015-2018 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Ali Saidi 41 * Prakash Ramrakhyani 42 */ 43 44#include "dev/arm/gic_v2.hh" 45 46#include "base/trace.hh" 47#include "debug/Checkpoint.hh" 48#include "debug/GIC.hh" 49#include "debug/IPI.hh" 50#include "debug/Interrupt.hh" 51#include "mem/packet.hh" 52#include "mem/packet_access.hh" 53 54const AddrRange GicV2::GICD_IGROUPR (0x080, 0x0ff); 55const AddrRange GicV2::GICD_ISENABLER (0x100, 0x17f); 56const AddrRange GicV2::GICD_ICENABLER (0x180, 0x1ff); 57const AddrRange GicV2::GICD_ISPENDR (0x200, 0x27f); 58const AddrRange GicV2::GICD_ICPENDR (0x280, 0x2ff); 59const AddrRange GicV2::GICD_ISACTIVER (0x300, 0x37f); 60const AddrRange GicV2::GICD_ICACTIVER (0x380, 0x3ff); 61const AddrRange GicV2::GICD_IPRIORITYR(0x400, 0x7ff); 62const AddrRange GicV2::GICD_ITARGETSR (0x800, 0xbff); 63const AddrRange GicV2::GICD_ICFGR (0xc00, 0xcff); 64 65GicV2::GicV2(const Params *p) 66 : BaseGic(p), 67 distRange(RangeSize(p->dist_addr, DIST_SIZE)), 68 cpuRange(RangeSize(p->cpu_addr, p->cpu_size)), 69 addrRanges{distRange, cpuRange}, 70 distPioDelay(p->dist_pio_delay), 71 cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency), 72 enabled(false), haveGem5Extensions(p->gem5_extensions), 73 itLines(p->it_lines), 74 intEnabled {}, pendingInt {}, activeInt {}, 75 intPriority {}, cpuTarget {}, intConfig {}, 76 cpuSgiPending {}, cpuSgiActive {}, 77 cpuSgiPendingExt {}, cpuSgiActiveExt {}, 78 cpuPpiPending {}, cpuPpiActive {}, 79 pendingDelayedInterrupts(0) 80{ 81 for (int x = 0; x < CPU_MAX; x++) { 82 iccrpr[x] = 0xff; 83 cpuControl[x] = 0; 84 cpuPriority[x] = 0xff; 85 cpuBpr[x] = GICC_BPR_MINIMUM; 86 // Initialize cpu highest int 87 cpuHighestInt[x] = SPURIOUS_INT; 88 postIntEvent[x] = 89 new EventFunctionWrapper([this, x]{ postDelayedInt(x); }, 90 "Post Interrupt to CPU");
|
102} 103 104Tick 105GicV2::read(PacketPtr pkt) 106{ 107 const Addr addr = pkt->getAddr(); 108 109 if (distRange.contains(addr)) 110 return readDistributor(pkt); 111 else if (cpuRange.contains(addr)) 112 return readCpu(pkt); 113 else 114 panic("Read to unknown address %#x\n", pkt->getAddr()); 115} 116 117 118Tick 119GicV2::write(PacketPtr pkt) 120{ 121 const Addr addr = pkt->getAddr(); 122 123 if (distRange.contains(addr)) 124 return writeDistributor(pkt); 125 else if (cpuRange.contains(addr)) 126 return writeCpu(pkt); 127 else 128 panic("Write to unknown address %#x\n", pkt->getAddr()); 129} 130 131Tick 132GicV2::readDistributor(PacketPtr pkt) 133{ 134 const Addr daddr = pkt->getAddr() - distRange.start(); 135 const ContextID ctx = pkt->req->contextId(); 136 137 DPRINTF(GIC, "gic distributor read register %#x\n", daddr); 138 139 const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize()); 140 141 switch (pkt->getSize()) { 142 case 1: 143 pkt->set<uint8_t>(resp); 144 break; 145 case 2: 146 pkt->set<uint16_t>(resp); 147 break; 148 case 4: 149 pkt->set<uint32_t>(resp); 150 break; 151 default: 152 panic("Invalid size while reading Distributor regs in GIC: %d\n", 153 pkt->getSize()); 154 } 155 156 pkt->makeAtomicResponse(); 157 return distPioDelay; 158} 159 160uint32_t 161GicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz) 162{ 163 if (GICD_IGROUPR.contains(daddr)) { 164 uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; 165 assert(ix < 32); 166 return getIntGroup(ctx, ix); 167 } 168 169 if (GICD_ISENABLER.contains(daddr)) { 170 uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 171 assert(ix < 32); 172 return getIntEnabled(ctx, ix); 173 } 174 175 if (GICD_ICENABLER.contains(daddr)) { 176 uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 177 assert(ix < 32); 178 return getIntEnabled(ctx, ix); 179 } 180 181 if (GICD_ISPENDR.contains(daddr)) { 182 uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 183 assert(ix < 32); 184 return getPendingInt(ctx, ix); 185 } 186 187 if (GICD_ICPENDR.contains(daddr)) { 188 uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 189 assert(ix < 32); 190 return getPendingInt(ctx, ix); 191 } 192 193 if (GICD_ISACTIVER.contains(daddr)) { 194 uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 195 assert(ix < 32); 196 return getActiveInt(ctx, ix); 197 } 198 199 if (GICD_ICACTIVER.contains(daddr)) { 200 uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 201 assert(ix < 32); 202 return getActiveInt(ctx, ix); 203 } 204 205 if (GICD_IPRIORITYR.contains(daddr)) { 206 Addr int_num = daddr - GICD_IPRIORITYR.start(); 207 assert(int_num < INT_LINES_MAX); 208 DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n", 209 int_num); 210 211 switch (resp_sz) { 212 default: // will panic() after return to caller anyway 213 case 1: 214 return getIntPriority(ctx, int_num); 215 case 2: 216 assert((int_num + 1) < INT_LINES_MAX); 217 return (getIntPriority(ctx, int_num) | 218 getIntPriority(ctx, int_num+1) << 8); 219 case 4: 220 assert((int_num + 3) < INT_LINES_MAX); 221 return (getIntPriority(ctx, int_num) | 222 getIntPriority(ctx, int_num+1) << 8 | 223 getIntPriority(ctx, int_num+2) << 16 | 224 getIntPriority(ctx, int_num+3) << 24); 225 } 226 } 227 228 if (GICD_ITARGETSR.contains(daddr)) { 229 Addr int_num = daddr - GICD_ITARGETSR.start(); 230 DPRINTF(GIC, "Reading processor target register for int# %#x \n", 231 int_num); 232 assert(int_num < INT_LINES_MAX); 233 234 if (resp_sz == 1) { 235 return getCpuTarget(ctx, int_num); 236 } else { 237 assert(resp_sz == 4); 238 int_num = mbits(int_num, 31, 2); 239 return (getCpuTarget(ctx, int_num) | 240 getCpuTarget(ctx, int_num+1) << 8 | 241 getCpuTarget(ctx, int_num+2) << 16 | 242 getCpuTarget(ctx, int_num+3) << 24) ; 243 } 244 } 245 246 if (GICD_ICFGR.contains(daddr)) { 247 uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 248 assert(ix < 64); 249 /** @todo software generated interrupts and PPIs 250 * can't be configured in some ways */ 251 return intConfig[ix]; 252 } 253 254 switch(daddr) { 255 case GICD_CTLR: 256 return enabled; 257 case GICD_TYPER: 258 /* The 0x100 is a made-up flag to show that gem5 extensions 259 * are available, 260 * write 0x200 to this register to enable it. */ 261 return (((sys->numRunningContexts() - 1) << 5) | 262 (itLines/INT_BITS_MAX -1) | 263 (haveGem5Extensions ? 0x100 : 0x0)); 264 case GICD_PIDR0: 265 //ARM defined DevID 266 return (GICD_400_PIDR_VALUE & 0xFF); 267 case GICD_PIDR1: 268 return ((GICD_400_PIDR_VALUE >> 8) & 0xFF); 269 case GICD_PIDR2: 270 return ((GICD_400_PIDR_VALUE >> 16) & 0xFF); 271 case GICD_PIDR3: 272 return ((GICD_400_PIDR_VALUE >> 24) & 0xFF); 273 case GICD_IIDR: 274 /* revision id is resorted to 1 and variant to 0*/ 275 return GICD_400_IIDR_VALUE; 276 default: 277 panic("Tried to read Gic distributor at offset %#x\n", daddr); 278 break; 279 } 280} 281 282Tick 283GicV2::readCpu(PacketPtr pkt) 284{ 285 const Addr daddr = pkt->getAddr() - cpuRange.start(); 286 287 assert(pkt->req->hasContextId()); 288 const ContextID ctx = pkt->req->contextId(); 289 assert(ctx < sys->numRunningContexts()); 290 291 DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr, 292 ctx); 293 294 pkt->set<uint32_t>(readCpu(ctx, daddr)); 295 296 pkt->makeAtomicResponse(); 297 return cpuPioDelay; 298} 299 300uint32_t 301GicV2::readCpu(ContextID ctx, Addr daddr) 302{ 303 switch(daddr) { 304 case GICC_IIDR: 305 return GICC_400_IIDR_VALUE; 306 case GICC_CTLR: 307 return cpuControl[ctx]; 308 case GICC_PMR: 309 return cpuPriority[ctx]; 310 case GICC_BPR: 311 return cpuBpr[ctx]; 312 case GICC_IAR: 313 if (enabled && cpuEnabled(ctx)) { 314 int active_int = cpuHighestInt[ctx]; 315 IAR iar = 0; 316 iar.ack_id = active_int; 317 iar.cpu_id = 0; 318 if (active_int < SGI_MAX) { 319 // this is a software interrupt from another CPU 320 if (!gem5ExtensionsEnabled) { 321 panic_if(!cpuSgiPending[active_int], 322 "Interrupt %d active but no CPU generated it?\n", 323 active_int); 324 for (int x = 0; x < sys->numRunningContexts(); x++) { 325 // See which CPU generated the interrupt 326 uint8_t cpugen = 327 bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x); 328 if (cpugen & (1 << ctx)) { 329 iar.cpu_id = x; 330 break; 331 } 332 } 333 uint64_t sgi_num = ULL(1) << (ctx + 8 * iar.cpu_id); 334 cpuSgiActive[iar.ack_id] |= sgi_num; 335 cpuSgiPending[iar.ack_id] &= ~sgi_num; 336 } else { 337 uint64_t sgi_num = ULL(1) << iar.ack_id; 338 cpuSgiActiveExt[ctx] |= sgi_num; 339 cpuSgiPendingExt[ctx] &= ~sgi_num; 340 } 341 } else if (active_int < (SGI_MAX + PPI_MAX) ) { 342 uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX); 343 cpuPpiActive[ctx] |= int_num; 344 updateRunPri(); 345 cpuPpiPending[ctx] &= ~int_num; 346 347 } else { 348 uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]); 349 getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num; 350 updateRunPri(); 351 if (!isLevelSensitive(ctx, active_int)) { 352 getPendingInt(ctx, intNumToWord(cpuHighestInt[ctx])) 353 &= ~int_num; 354 } 355 } 356 357 DPRINTF(Interrupt, 358 "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n", 359 ctx, iar.ack_id, iar.cpu_id, iar); 360 cpuHighestInt[ctx] = SPURIOUS_INT; 361 updateIntState(-1); 362 platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0); 363 return iar; 364 } else { 365 return SPURIOUS_INT; 366 } 367 368 break; 369 case GICC_RPR: 370 return iccrpr[0]; 371 case GICC_HPPIR: 372 panic("Need to implement HPIR"); 373 break; 374 default: 375 panic("Tried to read Gic cpu at offset %#x\n", daddr); 376 break; 377 } 378} 379 380Tick 381GicV2::writeDistributor(PacketPtr pkt) 382{ 383 const Addr daddr = pkt->getAddr() - distRange.start(); 384 385 assert(pkt->req->hasContextId()); 386 const ContextID ctx = pkt->req->contextId(); 387 const size_t data_sz = pkt->getSize(); 388 389 uint32_t pkt_data M5_VAR_USED; 390 switch (data_sz) 391 { 392 case 1: 393 pkt_data = pkt->get<uint8_t>(); 394 break; 395 case 2: 396 pkt_data = pkt->get<uint16_t>(); 397 break; 398 case 4: 399 pkt_data = pkt->get<uint32_t>(); 400 break; 401 default: 402 panic("Invalid size when writing to priority regs in Gic: %d\n", 403 data_sz); 404 } 405 406 DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n", 407 daddr, data_sz, pkt_data); 408 409 writeDistributor(ctx, daddr, pkt_data, data_sz); 410 411 pkt->makeAtomicResponse(); 412 return distPioDelay; 413} 414 415void 416GicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data, 417 size_t data_sz) 418{ 419 if (GICD_IGROUPR.contains(daddr)) { 420 uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; 421 assert(ix < 32); 422 getIntGroup(ctx, ix) |= data; 423 return; 424 } 425 426 if (GICD_ISENABLER.contains(daddr)) { 427 uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 428 assert(ix < 32); 429 getIntEnabled(ctx, ix) |= data; 430 return; 431 } 432 433 if (GICD_ICENABLER.contains(daddr)) { 434 uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 435 assert(ix < 32); 436 getIntEnabled(ctx, ix) &= ~data; 437 return; 438 } 439 440 if (GICD_ISPENDR.contains(daddr)) { 441 uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 442 auto mask = data; 443 if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 444 getPendingInt(ctx, ix) |= mask; 445 updateIntState(ix); 446 return; 447 } 448 449 if (GICD_ICPENDR.contains(daddr)) { 450 uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 451 auto mask = data; 452 if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 453 getPendingInt(ctx, ix) &= ~mask; 454 updateIntState(ix); 455 return; 456 } 457 458 if (GICD_ISACTIVER.contains(daddr)) { 459 uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 460 getActiveInt(ctx, ix) |= data; 461 return; 462 } 463 464 if (GICD_ICACTIVER.contains(daddr)) { 465 uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 466 getActiveInt(ctx, ix) &= ~data; 467 return; 468 } 469 470 if (GICD_IPRIORITYR.contains(daddr)) { 471 Addr int_num = daddr - GICD_IPRIORITYR.start(); 472 switch(data_sz) { 473 case 1: 474 getIntPriority(ctx, int_num) = data; 475 break; 476 case 2: { 477 getIntPriority(ctx, int_num) = bits(data, 7, 0); 478 getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 479 break; 480 } 481 case 4: { 482 getIntPriority(ctx, int_num) = bits(data, 7, 0); 483 getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 484 getIntPriority(ctx, int_num + 2) = bits(data, 23, 16); 485 getIntPriority(ctx, int_num + 3) = bits(data, 31, 24); 486 break; 487 } 488 default: 489 panic("Invalid size when writing to priority regs in Gic: %d\n", 490 data_sz); 491 } 492 493 updateIntState(-1); 494 updateRunPri(); 495 return; 496 } 497 498 if (GICD_ITARGETSR.contains(daddr)) { 499 Addr int_num = daddr - GICD_ITARGETSR.start(); 500 // Interrupts 0-31 are read only 501 unsigned offset = SGI_MAX + PPI_MAX; 502 if (int_num >= offset) { 503 unsigned ix = int_num - offset; // index into cpuTarget array 504 if (data_sz == 1) { 505 cpuTarget[ix] = data & 0xff; 506 } else { 507 assert (data_sz == 4); 508 cpuTarget[ix] = bits(data, 7, 0); 509 cpuTarget[ix+1] = bits(data, 15, 8); 510 cpuTarget[ix+2] = bits(data, 23, 16); 511 cpuTarget[ix+3] = bits(data, 31, 24); 512 } 513 updateIntState(int_num >> 2); 514 } 515 return; 516 } 517 518 if (GICD_ICFGR.contains(daddr)) { 519 uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 520 assert(ix < INT_BITS_MAX*2); 521 intConfig[ix] = data; 522 if (data & NN_CONFIG_MASK) 523 warn("GIC N:N mode selected and not supported at this time\n"); 524 return; 525 } 526 527 switch(daddr) { 528 case GICD_CTLR: 529 enabled = data; 530 DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled); 531 break; 532 case GICD_TYPER: 533 /* 0x200 is a made-up flag to enable gem5 extension functionality. 534 * This reg is not normally written. 535 */ 536 gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions; 537 DPRINTF(GIC, "gem5 extensions %s\n", 538 gem5ExtensionsEnabled ? "enabled" : "disabled"); 539 break; 540 case GICD_SGIR: 541 softInt(ctx, data); 542 break; 543 default: 544 panic("Tried to write Gic distributor at offset %#x\n", daddr); 545 break; 546 } 547} 548 549Tick 550GicV2::writeCpu(PacketPtr pkt) 551{ 552 const Addr daddr = pkt->getAddr() - cpuRange.start(); 553 554 assert(pkt->req->hasContextId()); 555 const ContextID ctx = pkt->req->contextId(); 556 const uint32_t data = pkt->get<uint32_t>(); 557 558 DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n", 559 ctx, daddr, data); 560 561 writeCpu(ctx, daddr, data); 562 563 pkt->makeAtomicResponse(); 564 return cpuPioDelay; 565} 566 567void 568GicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data) 569{ 570 switch(daddr) { 571 case GICC_CTLR: 572 cpuControl[ctx] = data; 573 break; 574 case GICC_PMR: 575 cpuPriority[ctx] = data; 576 break; 577 case GICC_BPR: { 578 auto bpr = data & 0x7; 579 if (bpr < GICC_BPR_MINIMUM) 580 bpr = GICC_BPR_MINIMUM; 581 cpuBpr[ctx] = bpr; 582 break; 583 } 584 case GICC_EOIR: { 585 const IAR iar = data; 586 if (iar.ack_id < SGI_MAX) { 587 // Clear out the bit that corresponds to the cleared int 588 uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id); 589 if (!(cpuSgiActive[iar.ack_id] & clr_int) && 590 !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id))) 591 panic("Done handling a SGI that isn't active?\n"); 592 if (gem5ExtensionsEnabled) 593 cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id); 594 else 595 cpuSgiActive[iar.ack_id] &= ~clr_int; 596 } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) { 597 uint32_t int_num = 1 << (iar.ack_id - SGI_MAX); 598 if (!(cpuPpiActive[ctx] & int_num)) 599 panic("CPU %d Done handling a PPI interrupt " 600 "that isn't active?\n", ctx); 601 cpuPpiActive[ctx] &= ~int_num; 602 } else { 603 uint32_t int_num = 1 << intNumToBit(iar.ack_id); 604 if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num)) 605 warn("Done handling interrupt that isn't active: %d\n", 606 intNumToBit(iar.ack_id)); 607 getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num; 608 } 609 updateRunPri(); 610 DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n", 611 ctx, iar.ack_id, iar.cpu_id); 612 break; 613 } 614 case GICC_APR0: 615 case GICC_APR1: 616 case GICC_APR2: 617 case GICC_APR3: 618 warn("GIC APRn write ignored because not implemented: %#x\n", daddr); 619 break; 620 default: 621 panic("Tried to write Gic cpu at offset %#x\n", daddr); 622 break; 623 } 624 if (cpuEnabled(ctx)) updateIntState(-1); 625} 626 627GicV2::BankedRegs& 628GicV2::getBankedRegs(ContextID ctx) { 629 if (bankedRegs.size() <= ctx) 630 bankedRegs.resize(ctx + 1); 631 632 if (!bankedRegs[ctx]) 633 bankedRegs[ctx] = new BankedRegs; 634 return *bankedRegs[ctx]; 635} 636 637void 638GicV2::softInt(ContextID ctx, SWI swi) 639{ 640 if (gem5ExtensionsEnabled) { 641 switch (swi.list_type) { 642 case 0: { 643 // interrupt cpus specified 644 int dest = swi.cpu_list; 645 DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 646 ctx, dest); 647 if (cpuEnabled(dest)) { 648 cpuSgiPendingExt[dest] |= (1 << swi.sgi_id); 649 DPRINTF(IPI, "SGI[%d]=%#x\n", dest, 650 cpuSgiPendingExt[dest]); 651 } 652 } break; 653 case 1: { 654 // interrupt all 655 for (int i = 0; i < sys->numContexts(); i++) { 656 DPRINTF(IPI, "Processing CPU %d\n", i); 657 if (!cpuEnabled(i)) 658 continue; 659 cpuSgiPendingExt[i] |= 1 << swi.sgi_id; 660 DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 661 cpuSgiPendingExt[i]); 662 } 663 } break; 664 case 2: { 665 // Interrupt requesting cpu only 666 DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 667 ctx, ctx); 668 if (cpuEnabled(ctx)) { 669 cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id); 670 DPRINTF(IPI, "SGI[%d]=%#x\n", ctx, 671 cpuSgiPendingExt[ctx]); 672 } 673 } break; 674 } 675 } else { 676 switch (swi.list_type) { 677 case 1: 678 // interrupt all 679 uint8_t cpu_list; 680 cpu_list = 0; 681 for (int x = 0; x < sys->numContexts(); x++) 682 cpu_list |= cpuEnabled(x) ? 1 << x : 0; 683 swi.cpu_list = cpu_list; 684 break; 685 case 2: 686 // interrupt requesting cpu only 687 swi.cpu_list = 1 << ctx; 688 break; 689 // else interrupt cpus specified 690 } 691 692 DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx, 693 swi.cpu_list); 694 for (int i = 0; i < sys->numContexts(); i++) { 695 DPRINTF(IPI, "Processing CPU %d\n", i); 696 if (!cpuEnabled(i)) 697 continue; 698 if (swi.cpu_list & (1 << i)) 699 cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx); 700 DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 701 cpuSgiPending[swi.sgi_id]); 702 } 703 } 704 updateIntState(-1); 705} 706 707uint64_t 708GicV2::genSwiMask(int cpu) 709{ 710 if (cpu > sys->numContexts()) 711 panic("Invalid CPU ID\n"); 712 return ULL(0x0101010101010101) << cpu; 713} 714 715uint8_t 716GicV2::getCpuPriority(unsigned cpu) 717{ 718 // see Table 3-2 in IHI0048B.b (GICv2) 719 // mask some low-order priority bits per BPR value 720 // NB: the GIC prioritization scheme is upside down: 721 // lower values are higher priority; masking off bits 722 // actually creates a higher priority, not lower. 723 return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu])); 724} 725 726void 727GicV2::updateIntState(int hint) 728{ 729 for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 730 if (!cpuEnabled(cpu)) 731 continue; 732 733 /*@todo use hint to do less work. */ 734 int highest_int = SPURIOUS_INT; 735 // Priorities below that set in GICC_PMR can be ignored 736 uint8_t highest_pri = getCpuPriority(cpu); 737 738 // Check SGIs 739 for (int swi = 0; swi < SGI_MAX; swi++) { 740 if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu]) 741 continue; 742 if ((cpuSgiPending[swi] & genSwiMask(cpu)) || 743 (cpuSgiPendingExt[cpu] & (1 << swi))) 744 if (highest_pri > getIntPriority(cpu, swi)) { 745 highest_pri = getIntPriority(cpu, swi); 746 highest_int = swi; 747 } 748 } 749 750 // Check PPIs 751 if (cpuPpiPending[cpu]) { 752 for (int ppi_idx = 0, int_num = SGI_MAX; 753 int_num < PPI_MAX + SGI_MAX; 754 ppi_idx++, int_num++) { 755 756 const bool ppi_pending = bits(cpuPpiPending[cpu], ppi_idx); 757 const bool ppi_enabled = bits(getIntEnabled(cpu, 0), int_num); 758 const bool higher_priority = 759 highest_pri > getIntPriority(cpu, int_num); 760 761 if (ppi_pending && ppi_enabled && higher_priority) { 762 highest_pri = getIntPriority(cpu, int_num); 763 highest_int = int_num; 764 } 765 } 766 } 767 768 bool mp_sys = sys->numRunningContexts() > 1; 769 // Check other ints 770 for (int x = 0; x < (itLines/INT_BITS_MAX); x++) { 771 if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) { 772 for (int y = 0; y < INT_BITS_MAX; y++) { 773 uint32_t int_nm = x * INT_BITS_MAX + y; 774 DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm); 775 /* Set current pending int as highest int for current cpu 776 if the interrupt's priority higher than current priority 777 and if current cpu is the target (for mp configs only) 778 */ 779 if ((bits(getIntEnabled(cpu, x), y) 780 &bits(getPendingInt(cpu, x), y)) && 781 (getIntPriority(cpu, int_nm) < highest_pri)) 782 if ((!mp_sys) || 783 (gem5ExtensionsEnabled 784 ? (getCpuTarget(cpu, int_nm) == cpu) 785 : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) { 786 highest_pri = getIntPriority(cpu, int_nm); 787 highest_int = int_nm; 788 } 789 } 790 } 791 } 792 793 uint32_t prev_highest = cpuHighestInt[cpu]; 794 cpuHighestInt[cpu] = highest_int; 795 796 if (highest_int == SPURIOUS_INT) { 797 if (isLevelSensitive(cpu, prev_highest)) { 798 799 DPRINTF(Interrupt, "Clear IRQ for cpu%d\n", cpu); 800 platform->intrctrl->clear(cpu, ArmISA::INT_IRQ, 0); 801 } 802 continue; 803 } 804 805 /* @todo make this work for more than one cpu, need to handle 1:N, N:N 806 * models */ 807 if (enabled && cpuEnabled(cpu) && 808 (highest_pri < getCpuPriority(cpu)) && 809 !(getActiveInt(cpu, intNumToWord(highest_int)) 810 & (1 << intNumToBit(highest_int)))) { 811 812 DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int, 813 cpu); 814 postInt(cpu, curTick() + intLatency); 815 } 816 } 817} 818 819void 820GicV2::updateRunPri() 821{ 822 for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 823 if (!cpuEnabled(cpu)) 824 continue; 825 uint8_t maxPriority = 0xff; 826 for (int i = 0; i < itLines; i++) { 827 if (i < SGI_MAX) { 828 if (((cpuSgiActive[i] & genSwiMask(cpu)) || 829 (cpuSgiActiveExt[cpu] & (1 << i))) && 830 (getIntPriority(cpu, i) < maxPriority)) 831 maxPriority = getIntPriority(cpu, i); 832 } else if (i < (SGI_MAX + PPI_MAX)) { 833 if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) && 834 (getIntPriority(cpu, i) < maxPriority)) 835 maxPriority = getIntPriority(cpu, i); 836 837 } else { 838 if (getActiveInt(cpu, intNumToWord(i)) 839 & (1 << intNumToBit(i))) 840 if (getIntPriority(cpu, i) < maxPriority) 841 maxPriority = getIntPriority(cpu, i); 842 } 843 } 844 iccrpr[cpu] = maxPriority; 845 } 846} 847 848void 849GicV2::sendInt(uint32_t num) 850{ 851 uint8_t target = getCpuTarget(0, num); 852 DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n", 853 num, target); 854 if ((target & (target - 1)) && !gem5ExtensionsEnabled) 855 panic("Multiple targets for peripheral interrupts is not supported\n"); 856 panic_if(num < SGI_MAX + PPI_MAX, 857 "sentInt() must only be used for interrupts 32 and higher"); 858 getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num); 859 updateIntState(intNumToWord(num)); 860} 861 862void 863GicV2::sendPPInt(uint32_t num, uint32_t cpu) 864{ 865 DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n", 866 num, cpu); 867 cpuPpiPending[cpu] |= 1 << (num - SGI_MAX); 868 updateIntState(intNumToWord(num)); 869} 870 871void 872GicV2::clearInt(uint32_t num) 873{ 874 if (isLevelSensitive(0, num)) { 875 uint8_t target = getCpuTarget(0, num); 876 877 DPRINTF(Interrupt, 878 "Received Clear interrupt number %d, cpuTarget %#x:\n", 879 num, target); 880 881 getPendingInt(target, intNumToWord(num)) &= ~(1 << intNumToBit(num)); 882 updateIntState(intNumToWord(num)); 883 } else { 884 /* Nothing to do : 885 * Edge-triggered interrupt remain pending until software 886 * writes GICD_ICPENDR or reads GICC_IAR */ 887 } 888} 889 890void 891GicV2::clearPPInt(uint32_t num, uint32_t cpu) 892{ 893 DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n", 894 num, cpu); 895 cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX)); 896 updateIntState(intNumToWord(num)); 897} 898 899void 900GicV2::postInt(uint32_t cpu, Tick when) 901{ 902 if (!(postIntEvent[cpu]->scheduled())) { 903 ++pendingDelayedInterrupts; 904 eventq->schedule(postIntEvent[cpu], when); 905 } 906} 907 908void 909GicV2::postDelayedInt(uint32_t cpu) 910{ 911 platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0); 912 --pendingDelayedInterrupts; 913 assert(pendingDelayedInterrupts >= 0); 914 if (pendingDelayedInterrupts == 0) 915 signalDrainDone(); 916} 917
| 107} 108 109Tick 110GicV2::read(PacketPtr pkt) 111{ 112 const Addr addr = pkt->getAddr(); 113 114 if (distRange.contains(addr)) 115 return readDistributor(pkt); 116 else if (cpuRange.contains(addr)) 117 return readCpu(pkt); 118 else 119 panic("Read to unknown address %#x\n", pkt->getAddr()); 120} 121 122 123Tick 124GicV2::write(PacketPtr pkt) 125{ 126 const Addr addr = pkt->getAddr(); 127 128 if (distRange.contains(addr)) 129 return writeDistributor(pkt); 130 else if (cpuRange.contains(addr)) 131 return writeCpu(pkt); 132 else 133 panic("Write to unknown address %#x\n", pkt->getAddr()); 134} 135 136Tick 137GicV2::readDistributor(PacketPtr pkt) 138{ 139 const Addr daddr = pkt->getAddr() - distRange.start(); 140 const ContextID ctx = pkt->req->contextId(); 141 142 DPRINTF(GIC, "gic distributor read register %#x\n", daddr); 143 144 const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize()); 145 146 switch (pkt->getSize()) { 147 case 1: 148 pkt->set<uint8_t>(resp); 149 break; 150 case 2: 151 pkt->set<uint16_t>(resp); 152 break; 153 case 4: 154 pkt->set<uint32_t>(resp); 155 break; 156 default: 157 panic("Invalid size while reading Distributor regs in GIC: %d\n", 158 pkt->getSize()); 159 } 160 161 pkt->makeAtomicResponse(); 162 return distPioDelay; 163} 164 165uint32_t 166GicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz) 167{ 168 if (GICD_IGROUPR.contains(daddr)) { 169 uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; 170 assert(ix < 32); 171 return getIntGroup(ctx, ix); 172 } 173 174 if (GICD_ISENABLER.contains(daddr)) { 175 uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 176 assert(ix < 32); 177 return getIntEnabled(ctx, ix); 178 } 179 180 if (GICD_ICENABLER.contains(daddr)) { 181 uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 182 assert(ix < 32); 183 return getIntEnabled(ctx, ix); 184 } 185 186 if (GICD_ISPENDR.contains(daddr)) { 187 uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 188 assert(ix < 32); 189 return getPendingInt(ctx, ix); 190 } 191 192 if (GICD_ICPENDR.contains(daddr)) { 193 uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 194 assert(ix < 32); 195 return getPendingInt(ctx, ix); 196 } 197 198 if (GICD_ISACTIVER.contains(daddr)) { 199 uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 200 assert(ix < 32); 201 return getActiveInt(ctx, ix); 202 } 203 204 if (GICD_ICACTIVER.contains(daddr)) { 205 uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 206 assert(ix < 32); 207 return getActiveInt(ctx, ix); 208 } 209 210 if (GICD_IPRIORITYR.contains(daddr)) { 211 Addr int_num = daddr - GICD_IPRIORITYR.start(); 212 assert(int_num < INT_LINES_MAX); 213 DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n", 214 int_num); 215 216 switch (resp_sz) { 217 default: // will panic() after return to caller anyway 218 case 1: 219 return getIntPriority(ctx, int_num); 220 case 2: 221 assert((int_num + 1) < INT_LINES_MAX); 222 return (getIntPriority(ctx, int_num) | 223 getIntPriority(ctx, int_num+1) << 8); 224 case 4: 225 assert((int_num + 3) < INT_LINES_MAX); 226 return (getIntPriority(ctx, int_num) | 227 getIntPriority(ctx, int_num+1) << 8 | 228 getIntPriority(ctx, int_num+2) << 16 | 229 getIntPriority(ctx, int_num+3) << 24); 230 } 231 } 232 233 if (GICD_ITARGETSR.contains(daddr)) { 234 Addr int_num = daddr - GICD_ITARGETSR.start(); 235 DPRINTF(GIC, "Reading processor target register for int# %#x \n", 236 int_num); 237 assert(int_num < INT_LINES_MAX); 238 239 if (resp_sz == 1) { 240 return getCpuTarget(ctx, int_num); 241 } else { 242 assert(resp_sz == 4); 243 int_num = mbits(int_num, 31, 2); 244 return (getCpuTarget(ctx, int_num) | 245 getCpuTarget(ctx, int_num+1) << 8 | 246 getCpuTarget(ctx, int_num+2) << 16 | 247 getCpuTarget(ctx, int_num+3) << 24) ; 248 } 249 } 250 251 if (GICD_ICFGR.contains(daddr)) { 252 uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 253 assert(ix < 64); 254 /** @todo software generated interrupts and PPIs 255 * can't be configured in some ways */ 256 return intConfig[ix]; 257 } 258 259 switch(daddr) { 260 case GICD_CTLR: 261 return enabled; 262 case GICD_TYPER: 263 /* The 0x100 is a made-up flag to show that gem5 extensions 264 * are available, 265 * write 0x200 to this register to enable it. */ 266 return (((sys->numRunningContexts() - 1) << 5) | 267 (itLines/INT_BITS_MAX -1) | 268 (haveGem5Extensions ? 0x100 : 0x0)); 269 case GICD_PIDR0: 270 //ARM defined DevID 271 return (GICD_400_PIDR_VALUE & 0xFF); 272 case GICD_PIDR1: 273 return ((GICD_400_PIDR_VALUE >> 8) & 0xFF); 274 case GICD_PIDR2: 275 return ((GICD_400_PIDR_VALUE >> 16) & 0xFF); 276 case GICD_PIDR3: 277 return ((GICD_400_PIDR_VALUE >> 24) & 0xFF); 278 case GICD_IIDR: 279 /* revision id is resorted to 1 and variant to 0*/ 280 return GICD_400_IIDR_VALUE; 281 default: 282 panic("Tried to read Gic distributor at offset %#x\n", daddr); 283 break; 284 } 285} 286 287Tick 288GicV2::readCpu(PacketPtr pkt) 289{ 290 const Addr daddr = pkt->getAddr() - cpuRange.start(); 291 292 assert(pkt->req->hasContextId()); 293 const ContextID ctx = pkt->req->contextId(); 294 assert(ctx < sys->numRunningContexts()); 295 296 DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr, 297 ctx); 298 299 pkt->set<uint32_t>(readCpu(ctx, daddr)); 300 301 pkt->makeAtomicResponse(); 302 return cpuPioDelay; 303} 304 305uint32_t 306GicV2::readCpu(ContextID ctx, Addr daddr) 307{ 308 switch(daddr) { 309 case GICC_IIDR: 310 return GICC_400_IIDR_VALUE; 311 case GICC_CTLR: 312 return cpuControl[ctx]; 313 case GICC_PMR: 314 return cpuPriority[ctx]; 315 case GICC_BPR: 316 return cpuBpr[ctx]; 317 case GICC_IAR: 318 if (enabled && cpuEnabled(ctx)) { 319 int active_int = cpuHighestInt[ctx]; 320 IAR iar = 0; 321 iar.ack_id = active_int; 322 iar.cpu_id = 0; 323 if (active_int < SGI_MAX) { 324 // this is a software interrupt from another CPU 325 if (!gem5ExtensionsEnabled) { 326 panic_if(!cpuSgiPending[active_int], 327 "Interrupt %d active but no CPU generated it?\n", 328 active_int); 329 for (int x = 0; x < sys->numRunningContexts(); x++) { 330 // See which CPU generated the interrupt 331 uint8_t cpugen = 332 bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x); 333 if (cpugen & (1 << ctx)) { 334 iar.cpu_id = x; 335 break; 336 } 337 } 338 uint64_t sgi_num = ULL(1) << (ctx + 8 * iar.cpu_id); 339 cpuSgiActive[iar.ack_id] |= sgi_num; 340 cpuSgiPending[iar.ack_id] &= ~sgi_num; 341 } else { 342 uint64_t sgi_num = ULL(1) << iar.ack_id; 343 cpuSgiActiveExt[ctx] |= sgi_num; 344 cpuSgiPendingExt[ctx] &= ~sgi_num; 345 } 346 } else if (active_int < (SGI_MAX + PPI_MAX) ) { 347 uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX); 348 cpuPpiActive[ctx] |= int_num; 349 updateRunPri(); 350 cpuPpiPending[ctx] &= ~int_num; 351 352 } else { 353 uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]); 354 getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num; 355 updateRunPri(); 356 if (!isLevelSensitive(ctx, active_int)) { 357 getPendingInt(ctx, intNumToWord(cpuHighestInt[ctx])) 358 &= ~int_num; 359 } 360 } 361 362 DPRINTF(Interrupt, 363 "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n", 364 ctx, iar.ack_id, iar.cpu_id, iar); 365 cpuHighestInt[ctx] = SPURIOUS_INT; 366 updateIntState(-1); 367 platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0); 368 return iar; 369 } else { 370 return SPURIOUS_INT; 371 } 372 373 break; 374 case GICC_RPR: 375 return iccrpr[0]; 376 case GICC_HPPIR: 377 panic("Need to implement HPIR"); 378 break; 379 default: 380 panic("Tried to read Gic cpu at offset %#x\n", daddr); 381 break; 382 } 383} 384 385Tick 386GicV2::writeDistributor(PacketPtr pkt) 387{ 388 const Addr daddr = pkt->getAddr() - distRange.start(); 389 390 assert(pkt->req->hasContextId()); 391 const ContextID ctx = pkt->req->contextId(); 392 const size_t data_sz = pkt->getSize(); 393 394 uint32_t pkt_data M5_VAR_USED; 395 switch (data_sz) 396 { 397 case 1: 398 pkt_data = pkt->get<uint8_t>(); 399 break; 400 case 2: 401 pkt_data = pkt->get<uint16_t>(); 402 break; 403 case 4: 404 pkt_data = pkt->get<uint32_t>(); 405 break; 406 default: 407 panic("Invalid size when writing to priority regs in Gic: %d\n", 408 data_sz); 409 } 410 411 DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n", 412 daddr, data_sz, pkt_data); 413 414 writeDistributor(ctx, daddr, pkt_data, data_sz); 415 416 pkt->makeAtomicResponse(); 417 return distPioDelay; 418} 419 420void 421GicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data, 422 size_t data_sz) 423{ 424 if (GICD_IGROUPR.contains(daddr)) { 425 uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; 426 assert(ix < 32); 427 getIntGroup(ctx, ix) |= data; 428 return; 429 } 430 431 if (GICD_ISENABLER.contains(daddr)) { 432 uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2; 433 assert(ix < 32); 434 getIntEnabled(ctx, ix) |= data; 435 return; 436 } 437 438 if (GICD_ICENABLER.contains(daddr)) { 439 uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2; 440 assert(ix < 32); 441 getIntEnabled(ctx, ix) &= ~data; 442 return; 443 } 444 445 if (GICD_ISPENDR.contains(daddr)) { 446 uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2; 447 auto mask = data; 448 if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 449 getPendingInt(ctx, ix) |= mask; 450 updateIntState(ix); 451 return; 452 } 453 454 if (GICD_ICPENDR.contains(daddr)) { 455 uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2; 456 auto mask = data; 457 if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed 458 getPendingInt(ctx, ix) &= ~mask; 459 updateIntState(ix); 460 return; 461 } 462 463 if (GICD_ISACTIVER.contains(daddr)) { 464 uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2; 465 getActiveInt(ctx, ix) |= data; 466 return; 467 } 468 469 if (GICD_ICACTIVER.contains(daddr)) { 470 uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2; 471 getActiveInt(ctx, ix) &= ~data; 472 return; 473 } 474 475 if (GICD_IPRIORITYR.contains(daddr)) { 476 Addr int_num = daddr - GICD_IPRIORITYR.start(); 477 switch(data_sz) { 478 case 1: 479 getIntPriority(ctx, int_num) = data; 480 break; 481 case 2: { 482 getIntPriority(ctx, int_num) = bits(data, 7, 0); 483 getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 484 break; 485 } 486 case 4: { 487 getIntPriority(ctx, int_num) = bits(data, 7, 0); 488 getIntPriority(ctx, int_num + 1) = bits(data, 15, 8); 489 getIntPriority(ctx, int_num + 2) = bits(data, 23, 16); 490 getIntPriority(ctx, int_num + 3) = bits(data, 31, 24); 491 break; 492 } 493 default: 494 panic("Invalid size when writing to priority regs in Gic: %d\n", 495 data_sz); 496 } 497 498 updateIntState(-1); 499 updateRunPri(); 500 return; 501 } 502 503 if (GICD_ITARGETSR.contains(daddr)) { 504 Addr int_num = daddr - GICD_ITARGETSR.start(); 505 // Interrupts 0-31 are read only 506 unsigned offset = SGI_MAX + PPI_MAX; 507 if (int_num >= offset) { 508 unsigned ix = int_num - offset; // index into cpuTarget array 509 if (data_sz == 1) { 510 cpuTarget[ix] = data & 0xff; 511 } else { 512 assert (data_sz == 4); 513 cpuTarget[ix] = bits(data, 7, 0); 514 cpuTarget[ix+1] = bits(data, 15, 8); 515 cpuTarget[ix+2] = bits(data, 23, 16); 516 cpuTarget[ix+3] = bits(data, 31, 24); 517 } 518 updateIntState(int_num >> 2); 519 } 520 return; 521 } 522 523 if (GICD_ICFGR.contains(daddr)) { 524 uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2; 525 assert(ix < INT_BITS_MAX*2); 526 intConfig[ix] = data; 527 if (data & NN_CONFIG_MASK) 528 warn("GIC N:N mode selected and not supported at this time\n"); 529 return; 530 } 531 532 switch(daddr) { 533 case GICD_CTLR: 534 enabled = data; 535 DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled); 536 break; 537 case GICD_TYPER: 538 /* 0x200 is a made-up flag to enable gem5 extension functionality. 539 * This reg is not normally written. 540 */ 541 gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions; 542 DPRINTF(GIC, "gem5 extensions %s\n", 543 gem5ExtensionsEnabled ? "enabled" : "disabled"); 544 break; 545 case GICD_SGIR: 546 softInt(ctx, data); 547 break; 548 default: 549 panic("Tried to write Gic distributor at offset %#x\n", daddr); 550 break; 551 } 552} 553 554Tick 555GicV2::writeCpu(PacketPtr pkt) 556{ 557 const Addr daddr = pkt->getAddr() - cpuRange.start(); 558 559 assert(pkt->req->hasContextId()); 560 const ContextID ctx = pkt->req->contextId(); 561 const uint32_t data = pkt->get<uint32_t>(); 562 563 DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n", 564 ctx, daddr, data); 565 566 writeCpu(ctx, daddr, data); 567 568 pkt->makeAtomicResponse(); 569 return cpuPioDelay; 570} 571 572void 573GicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data) 574{ 575 switch(daddr) { 576 case GICC_CTLR: 577 cpuControl[ctx] = data; 578 break; 579 case GICC_PMR: 580 cpuPriority[ctx] = data; 581 break; 582 case GICC_BPR: { 583 auto bpr = data & 0x7; 584 if (bpr < GICC_BPR_MINIMUM) 585 bpr = GICC_BPR_MINIMUM; 586 cpuBpr[ctx] = bpr; 587 break; 588 } 589 case GICC_EOIR: { 590 const IAR iar = data; 591 if (iar.ack_id < SGI_MAX) { 592 // Clear out the bit that corresponds to the cleared int 593 uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id); 594 if (!(cpuSgiActive[iar.ack_id] & clr_int) && 595 !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id))) 596 panic("Done handling a SGI that isn't active?\n"); 597 if (gem5ExtensionsEnabled) 598 cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id); 599 else 600 cpuSgiActive[iar.ack_id] &= ~clr_int; 601 } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) { 602 uint32_t int_num = 1 << (iar.ack_id - SGI_MAX); 603 if (!(cpuPpiActive[ctx] & int_num)) 604 panic("CPU %d Done handling a PPI interrupt " 605 "that isn't active?\n", ctx); 606 cpuPpiActive[ctx] &= ~int_num; 607 } else { 608 uint32_t int_num = 1 << intNumToBit(iar.ack_id); 609 if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num)) 610 warn("Done handling interrupt that isn't active: %d\n", 611 intNumToBit(iar.ack_id)); 612 getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num; 613 } 614 updateRunPri(); 615 DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n", 616 ctx, iar.ack_id, iar.cpu_id); 617 break; 618 } 619 case GICC_APR0: 620 case GICC_APR1: 621 case GICC_APR2: 622 case GICC_APR3: 623 warn("GIC APRn write ignored because not implemented: %#x\n", daddr); 624 break; 625 default: 626 panic("Tried to write Gic cpu at offset %#x\n", daddr); 627 break; 628 } 629 if (cpuEnabled(ctx)) updateIntState(-1); 630} 631 632GicV2::BankedRegs& 633GicV2::getBankedRegs(ContextID ctx) { 634 if (bankedRegs.size() <= ctx) 635 bankedRegs.resize(ctx + 1); 636 637 if (!bankedRegs[ctx]) 638 bankedRegs[ctx] = new BankedRegs; 639 return *bankedRegs[ctx]; 640} 641 642void 643GicV2::softInt(ContextID ctx, SWI swi) 644{ 645 if (gem5ExtensionsEnabled) { 646 switch (swi.list_type) { 647 case 0: { 648 // interrupt cpus specified 649 int dest = swi.cpu_list; 650 DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 651 ctx, dest); 652 if (cpuEnabled(dest)) { 653 cpuSgiPendingExt[dest] |= (1 << swi.sgi_id); 654 DPRINTF(IPI, "SGI[%d]=%#x\n", dest, 655 cpuSgiPendingExt[dest]); 656 } 657 } break; 658 case 1: { 659 // interrupt all 660 for (int i = 0; i < sys->numContexts(); i++) { 661 DPRINTF(IPI, "Processing CPU %d\n", i); 662 if (!cpuEnabled(i)) 663 continue; 664 cpuSgiPendingExt[i] |= 1 << swi.sgi_id; 665 DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 666 cpuSgiPendingExt[i]); 667 } 668 } break; 669 case 2: { 670 // Interrupt requesting cpu only 671 DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n", 672 ctx, ctx); 673 if (cpuEnabled(ctx)) { 674 cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id); 675 DPRINTF(IPI, "SGI[%d]=%#x\n", ctx, 676 cpuSgiPendingExt[ctx]); 677 } 678 } break; 679 } 680 } else { 681 switch (swi.list_type) { 682 case 1: 683 // interrupt all 684 uint8_t cpu_list; 685 cpu_list = 0; 686 for (int x = 0; x < sys->numContexts(); x++) 687 cpu_list |= cpuEnabled(x) ? 1 << x : 0; 688 swi.cpu_list = cpu_list; 689 break; 690 case 2: 691 // interrupt requesting cpu only 692 swi.cpu_list = 1 << ctx; 693 break; 694 // else interrupt cpus specified 695 } 696 697 DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx, 698 swi.cpu_list); 699 for (int i = 0; i < sys->numContexts(); i++) { 700 DPRINTF(IPI, "Processing CPU %d\n", i); 701 if (!cpuEnabled(i)) 702 continue; 703 if (swi.cpu_list & (1 << i)) 704 cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx); 705 DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id, 706 cpuSgiPending[swi.sgi_id]); 707 } 708 } 709 updateIntState(-1); 710} 711 712uint64_t 713GicV2::genSwiMask(int cpu) 714{ 715 if (cpu > sys->numContexts()) 716 panic("Invalid CPU ID\n"); 717 return ULL(0x0101010101010101) << cpu; 718} 719 720uint8_t 721GicV2::getCpuPriority(unsigned cpu) 722{ 723 // see Table 3-2 in IHI0048B.b (GICv2) 724 // mask some low-order priority bits per BPR value 725 // NB: the GIC prioritization scheme is upside down: 726 // lower values are higher priority; masking off bits 727 // actually creates a higher priority, not lower. 728 return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu])); 729} 730 731void 732GicV2::updateIntState(int hint) 733{ 734 for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 735 if (!cpuEnabled(cpu)) 736 continue; 737 738 /*@todo use hint to do less work. */ 739 int highest_int = SPURIOUS_INT; 740 // Priorities below that set in GICC_PMR can be ignored 741 uint8_t highest_pri = getCpuPriority(cpu); 742 743 // Check SGIs 744 for (int swi = 0; swi < SGI_MAX; swi++) { 745 if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu]) 746 continue; 747 if ((cpuSgiPending[swi] & genSwiMask(cpu)) || 748 (cpuSgiPendingExt[cpu] & (1 << swi))) 749 if (highest_pri > getIntPriority(cpu, swi)) { 750 highest_pri = getIntPriority(cpu, swi); 751 highest_int = swi; 752 } 753 } 754 755 // Check PPIs 756 if (cpuPpiPending[cpu]) { 757 for (int ppi_idx = 0, int_num = SGI_MAX; 758 int_num < PPI_MAX + SGI_MAX; 759 ppi_idx++, int_num++) { 760 761 const bool ppi_pending = bits(cpuPpiPending[cpu], ppi_idx); 762 const bool ppi_enabled = bits(getIntEnabled(cpu, 0), int_num); 763 const bool higher_priority = 764 highest_pri > getIntPriority(cpu, int_num); 765 766 if (ppi_pending && ppi_enabled && higher_priority) { 767 highest_pri = getIntPriority(cpu, int_num); 768 highest_int = int_num; 769 } 770 } 771 } 772 773 bool mp_sys = sys->numRunningContexts() > 1; 774 // Check other ints 775 for (int x = 0; x < (itLines/INT_BITS_MAX); x++) { 776 if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) { 777 for (int y = 0; y < INT_BITS_MAX; y++) { 778 uint32_t int_nm = x * INT_BITS_MAX + y; 779 DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm); 780 /* Set current pending int as highest int for current cpu 781 if the interrupt's priority higher than current priority 782 and if current cpu is the target (for mp configs only) 783 */ 784 if ((bits(getIntEnabled(cpu, x), y) 785 &bits(getPendingInt(cpu, x), y)) && 786 (getIntPriority(cpu, int_nm) < highest_pri)) 787 if ((!mp_sys) || 788 (gem5ExtensionsEnabled 789 ? (getCpuTarget(cpu, int_nm) == cpu) 790 : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) { 791 highest_pri = getIntPriority(cpu, int_nm); 792 highest_int = int_nm; 793 } 794 } 795 } 796 } 797 798 uint32_t prev_highest = cpuHighestInt[cpu]; 799 cpuHighestInt[cpu] = highest_int; 800 801 if (highest_int == SPURIOUS_INT) { 802 if (isLevelSensitive(cpu, prev_highest)) { 803 804 DPRINTF(Interrupt, "Clear IRQ for cpu%d\n", cpu); 805 platform->intrctrl->clear(cpu, ArmISA::INT_IRQ, 0); 806 } 807 continue; 808 } 809 810 /* @todo make this work for more than one cpu, need to handle 1:N, N:N 811 * models */ 812 if (enabled && cpuEnabled(cpu) && 813 (highest_pri < getCpuPriority(cpu)) && 814 !(getActiveInt(cpu, intNumToWord(highest_int)) 815 & (1 << intNumToBit(highest_int)))) { 816 817 DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int, 818 cpu); 819 postInt(cpu, curTick() + intLatency); 820 } 821 } 822} 823 824void 825GicV2::updateRunPri() 826{ 827 for (int cpu = 0; cpu < sys->numContexts(); cpu++) { 828 if (!cpuEnabled(cpu)) 829 continue; 830 uint8_t maxPriority = 0xff; 831 for (int i = 0; i < itLines; i++) { 832 if (i < SGI_MAX) { 833 if (((cpuSgiActive[i] & genSwiMask(cpu)) || 834 (cpuSgiActiveExt[cpu] & (1 << i))) && 835 (getIntPriority(cpu, i) < maxPriority)) 836 maxPriority = getIntPriority(cpu, i); 837 } else if (i < (SGI_MAX + PPI_MAX)) { 838 if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) && 839 (getIntPriority(cpu, i) < maxPriority)) 840 maxPriority = getIntPriority(cpu, i); 841 842 } else { 843 if (getActiveInt(cpu, intNumToWord(i)) 844 & (1 << intNumToBit(i))) 845 if (getIntPriority(cpu, i) < maxPriority) 846 maxPriority = getIntPriority(cpu, i); 847 } 848 } 849 iccrpr[cpu] = maxPriority; 850 } 851} 852 853void 854GicV2::sendInt(uint32_t num) 855{ 856 uint8_t target = getCpuTarget(0, num); 857 DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n", 858 num, target); 859 if ((target & (target - 1)) && !gem5ExtensionsEnabled) 860 panic("Multiple targets for peripheral interrupts is not supported\n"); 861 panic_if(num < SGI_MAX + PPI_MAX, 862 "sentInt() must only be used for interrupts 32 and higher"); 863 getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num); 864 updateIntState(intNumToWord(num)); 865} 866 867void 868GicV2::sendPPInt(uint32_t num, uint32_t cpu) 869{ 870 DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n", 871 num, cpu); 872 cpuPpiPending[cpu] |= 1 << (num - SGI_MAX); 873 updateIntState(intNumToWord(num)); 874} 875 876void 877GicV2::clearInt(uint32_t num) 878{ 879 if (isLevelSensitive(0, num)) { 880 uint8_t target = getCpuTarget(0, num); 881 882 DPRINTF(Interrupt, 883 "Received Clear interrupt number %d, cpuTarget %#x:\n", 884 num, target); 885 886 getPendingInt(target, intNumToWord(num)) &= ~(1 << intNumToBit(num)); 887 updateIntState(intNumToWord(num)); 888 } else { 889 /* Nothing to do : 890 * Edge-triggered interrupt remain pending until software 891 * writes GICD_ICPENDR or reads GICC_IAR */ 892 } 893} 894 895void 896GicV2::clearPPInt(uint32_t num, uint32_t cpu) 897{ 898 DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n", 899 num, cpu); 900 cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX)); 901 updateIntState(intNumToWord(num)); 902} 903 904void 905GicV2::postInt(uint32_t cpu, Tick when) 906{ 907 if (!(postIntEvent[cpu]->scheduled())) { 908 ++pendingDelayedInterrupts; 909 eventq->schedule(postIntEvent[cpu], when); 910 } 911} 912 913void 914GicV2::postDelayedInt(uint32_t cpu) 915{ 916 platform->intrctrl->post(cpu, ArmISA::INT_IRQ, 0); 917 --pendingDelayedInterrupts; 918 assert(pendingDelayedInterrupts >= 0); 919 if (pendingDelayedInterrupts == 0) 920 signalDrainDone(); 921} 922
|
918DrainState 919GicV2::drain() 920{ 921 if (pendingDelayedInterrupts == 0) { 922 return DrainState::Drained; 923 } else { 924 return DrainState::Draining; 925 } 926} 927 928 929void 930GicV2::drainResume() 931{ 932 // There may be pending interrupts if checkpointed from Kvm; post them. 933 updateIntState(-1); 934} 935 936void 937GicV2::serialize(CheckpointOut &cp) const 938{ 939 DPRINTF(Checkpoint, "Serializing Arm GIC\n"); 940 941 SERIALIZE_SCALAR(enabled); 942 SERIALIZE_SCALAR(itLines); 943 SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 944 SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 945 SERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 946 SERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); 947 SERIALIZE_ARRAY(iccrpr, CPU_MAX); 948 SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 949 SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 950 SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 951 SERIALIZE_ARRAY(cpuControl, CPU_MAX); 952 SERIALIZE_ARRAY(cpuPriority, CPU_MAX); 953 SERIALIZE_ARRAY(cpuBpr, CPU_MAX); 954 SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 955 SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 956 SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 957 SERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 958 SERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 959 SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 960 SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 961 SERIALIZE_SCALAR(gem5ExtensionsEnabled); 962 963 for (uint32_t i=0; i < bankedRegs.size(); ++i) { 964 if (!bankedRegs[i]) 965 continue; 966 bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i)); 967 } 968} 969 970void 971GicV2::BankedRegs::serialize(CheckpointOut &cp) const 972{ 973 SERIALIZE_SCALAR(intEnabled); 974 SERIALIZE_SCALAR(pendingInt); 975 SERIALIZE_SCALAR(activeInt); 976 SERIALIZE_SCALAR(intGroup); 977 SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 978} 979 980void 981GicV2::unserialize(CheckpointIn &cp) 982{ 983 DPRINTF(Checkpoint, "Unserializing Arm GIC\n"); 984 985 UNSERIALIZE_SCALAR(enabled); 986 UNSERIALIZE_SCALAR(itLines); 987 UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 988 UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 989 UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 990 UNSERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); 991 UNSERIALIZE_ARRAY(iccrpr, CPU_MAX); 992 UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 993 UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 994 UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 995 UNSERIALIZE_ARRAY(cpuControl, CPU_MAX); 996 UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX); 997 UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX); 998 UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 999 UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 1000 UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 1001 UNSERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 1002 UNSERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 1003 UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 1004 UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 1005 1006 // Handle checkpoints from before we drained the GIC to prevent 1007 // in-flight interrupts. 1008 if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) { 1009 Tick interrupt_time[CPU_MAX]; 1010 UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX); 1011 1012 for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) { 1013 if (interrupt_time[cpu]) 1014 schedule(postIntEvent[cpu], interrupt_time[cpu]); 1015 } 1016 } 1017 1018 if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled)) 1019 gem5ExtensionsEnabled = false; 1020 1021 for (uint32_t i=0; i < CPU_MAX; ++i) { 1022 ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i)); 1023 if (cp.sectionExists(Serializable::currentSection())) { 1024 getBankedRegs(i).unserialize(cp); 1025 } 1026 } 1027} 1028 1029void 1030GicV2::BankedRegs::unserialize(CheckpointIn &cp) 1031{ 1032 UNSERIALIZE_SCALAR(intEnabled); 1033 UNSERIALIZE_SCALAR(pendingInt); 1034 UNSERIALIZE_SCALAR(activeInt); 1035 UNSERIALIZE_SCALAR(intGroup); 1036 UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 1037} 1038 1039GicV2 * 1040GicV2Params::create() 1041{ 1042 return new GicV2(this); 1043}
| 942DrainState 943GicV2::drain() 944{ 945 if (pendingDelayedInterrupts == 0) { 946 return DrainState::Drained; 947 } else { 948 return DrainState::Draining; 949 } 950} 951 952 953void 954GicV2::drainResume() 955{ 956 // There may be pending interrupts if checkpointed from Kvm; post them. 957 updateIntState(-1); 958} 959 960void 961GicV2::serialize(CheckpointOut &cp) const 962{ 963 DPRINTF(Checkpoint, "Serializing Arm GIC\n"); 964 965 SERIALIZE_SCALAR(enabled); 966 SERIALIZE_SCALAR(itLines); 967 SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 968 SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 969 SERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 970 SERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); 971 SERIALIZE_ARRAY(iccrpr, CPU_MAX); 972 SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 973 SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 974 SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 975 SERIALIZE_ARRAY(cpuControl, CPU_MAX); 976 SERIALIZE_ARRAY(cpuPriority, CPU_MAX); 977 SERIALIZE_ARRAY(cpuBpr, CPU_MAX); 978 SERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 979 SERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 980 SERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 981 SERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 982 SERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 983 SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 984 SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 985 SERIALIZE_SCALAR(gem5ExtensionsEnabled); 986 987 for (uint32_t i=0; i < bankedRegs.size(); ++i) { 988 if (!bankedRegs[i]) 989 continue; 990 bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i)); 991 } 992} 993 994void 995GicV2::BankedRegs::serialize(CheckpointOut &cp) const 996{ 997 SERIALIZE_SCALAR(intEnabled); 998 SERIALIZE_SCALAR(pendingInt); 999 SERIALIZE_SCALAR(activeInt); 1000 SERIALIZE_SCALAR(intGroup); 1001 SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 1002} 1003 1004void 1005GicV2::unserialize(CheckpointIn &cp) 1006{ 1007 DPRINTF(Checkpoint, "Unserializing Arm GIC\n"); 1008 1009 UNSERIALIZE_SCALAR(enabled); 1010 UNSERIALIZE_SCALAR(itLines); 1011 UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); 1012 UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); 1013 UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); 1014 UNSERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); 1015 UNSERIALIZE_ARRAY(iccrpr, CPU_MAX); 1016 UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); 1017 UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); 1018 UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2); 1019 UNSERIALIZE_ARRAY(cpuControl, CPU_MAX); 1020 UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX); 1021 UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX); 1022 UNSERIALIZE_ARRAY(cpuHighestInt, CPU_MAX); 1023 UNSERIALIZE_ARRAY(cpuSgiActive, SGI_MAX); 1024 UNSERIALIZE_ARRAY(cpuSgiPending, SGI_MAX); 1025 UNSERIALIZE_ARRAY(cpuSgiActiveExt, CPU_MAX); 1026 UNSERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX); 1027 UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX); 1028 UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX); 1029 1030 // Handle checkpoints from before we drained the GIC to prevent 1031 // in-flight interrupts. 1032 if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) { 1033 Tick interrupt_time[CPU_MAX]; 1034 UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX); 1035 1036 for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) { 1037 if (interrupt_time[cpu]) 1038 schedule(postIntEvent[cpu], interrupt_time[cpu]); 1039 } 1040 } 1041 1042 if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled)) 1043 gem5ExtensionsEnabled = false; 1044 1045 for (uint32_t i=0; i < CPU_MAX; ++i) { 1046 ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i)); 1047 if (cp.sectionExists(Serializable::currentSection())) { 1048 getBankedRegs(i).unserialize(cp); 1049 } 1050 } 1051} 1052 1053void 1054GicV2::BankedRegs::unserialize(CheckpointIn &cp) 1055{ 1056 UNSERIALIZE_SCALAR(intEnabled); 1057 UNSERIALIZE_SCALAR(pendingInt); 1058 UNSERIALIZE_SCALAR(activeInt); 1059 UNSERIALIZE_SCALAR(intGroup); 1060 UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); 1061} 1062 1063GicV2 * 1064GicV2Params::create() 1065{ 1066 return new GicV2(this); 1067}
|