arm: bank GIC registers per CPU
Updated according to GICv2 documentation. Change-Id: I5d926d1abf665eecc43ff0f7d6e561e1ee1c390a Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
parent
ae445c0348
commit
fc8fd0fd18
3 changed files with 400 additions and 212 deletions
|
@ -51,15 +51,29 @@
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "mem/packet_access.hh"
|
#include "mem/packet_access.hh"
|
||||||
|
|
||||||
|
const AddrRange Pl390::GICD_ISENABLER (0x100, 0x17f);
|
||||||
|
const AddrRange Pl390::GICD_ICENABLER (0x180, 0x1ff);
|
||||||
|
const AddrRange Pl390::GICD_ISPENDR (0x200, 0x27f);
|
||||||
|
const AddrRange Pl390::GICD_ICPENDR (0x280, 0x2ff);
|
||||||
|
const AddrRange Pl390::GICD_ISACTIVER (0x300, 0x37f);
|
||||||
|
const AddrRange Pl390::GICD_ICACTIVER (0x380, 0x3ff);
|
||||||
|
const AddrRange Pl390::GICD_IPRIORITYR(0x400, 0x7ff);
|
||||||
|
const AddrRange Pl390::GICD_ITARGETSR (0x800, 0xbff);
|
||||||
|
const AddrRange Pl390::GICD_ICFGR (0xc00, 0xcff);
|
||||||
|
|
||||||
Pl390::Pl390(const Params *p)
|
Pl390::Pl390(const Params *p)
|
||||||
: BaseGic(p), distAddr(p->dist_addr),
|
: BaseGic(p), distAddr(p->dist_addr),
|
||||||
cpuAddr(p->cpu_addr), distPioDelay(p->dist_pio_delay),
|
cpuAddr(p->cpu_addr), distPioDelay(p->dist_pio_delay),
|
||||||
cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
|
cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
|
||||||
enabled(false), itLines(p->it_lines),
|
enabled(false), haveGem5Extensions(p->gem5_extensions),
|
||||||
haveGem5Extensions(p->gem5_extensions), irqEnable(false)
|
itLines(p->it_lines),
|
||||||
|
intEnabled {}, pendingInt {}, activeInt {},
|
||||||
|
intPriority {}, cpuTarget {}, intConfig {},
|
||||||
|
cpuSgiPending {}, cpuSgiActive {},
|
||||||
|
cpuSgiPendingExt {}, cpuSgiActiveExt {},
|
||||||
|
cpuPpiPending {}, cpuPpiActive {},
|
||||||
|
irqEnable(false)
|
||||||
{
|
{
|
||||||
itLinesLog2 = ceilLog2(itLines);
|
|
||||||
|
|
||||||
for (int x = 0; x < CPU_MAX; x++) {
|
for (int x = 0; x < CPU_MAX; x++) {
|
||||||
iccrpr[x] = 0xff;
|
iccrpr[x] = 0xff;
|
||||||
cpuEnabled[x] = false;
|
cpuEnabled[x] = false;
|
||||||
|
@ -72,38 +86,6 @@ Pl390::Pl390(const Params *p)
|
||||||
DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
|
DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
|
||||||
cpuEnabled[1]);
|
cpuEnabled[1]);
|
||||||
|
|
||||||
for (int x = 0; x < INT_BITS_MAX; x++) {
|
|
||||||
intEnabled[x] = 0;
|
|
||||||
pendingInt[x] = 0;
|
|
||||||
activeInt[x] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x < INT_LINES_MAX; x++) {
|
|
||||||
intPriority[x] = 0;
|
|
||||||
cpuTarget[x] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x < INT_BITS_MAX*2; x++) {
|
|
||||||
intConfig[x] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x < SGI_MAX; x++) {
|
|
||||||
cpuSgiActive[x] = 0;
|
|
||||||
cpuSgiPending[x] = 0;
|
|
||||||
}
|
|
||||||
for (int x = 0; x < CPU_MAX; x++) {
|
|
||||||
cpuPpiActive[x] = 0;
|
|
||||||
cpuPpiPending[x] = 0;
|
|
||||||
cpuSgiActiveExt[x] = 0;
|
|
||||||
cpuSgiPendingExt[x] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < CPU_MAX; i++) {
|
|
||||||
for (int j = 0; j < (SGI_MAX + PPI_MAX); j++) {
|
|
||||||
bankedIntPriority[i][j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gem5ExtensionsEnabled = false;
|
gem5ExtensionsEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,63 +127,68 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
|
|
||||||
DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
|
DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
|
||||||
|
|
||||||
if (daddr >= GICD_ISENABLER_ST && daddr < GICD_ISENABLER_ED + 4) {
|
if (GICD_ISENABLER.contains(daddr)) {
|
||||||
assert((daddr-GICD_ISENABLER_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
|
||||||
pkt->set<uint32_t>(intEnabled[(daddr-GICD_ISENABLER_ST)>>2]);
|
assert(ix < 32);
|
||||||
|
pkt->set<uint32_t>(getIntEnabled(ctx_id, ix));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ICENABLER_ST && daddr < GICD_ICENABLER_ED + 4) {
|
if (GICD_ICENABLER.contains(daddr)) {
|
||||||
assert((daddr-GICD_ICENABLER_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
|
||||||
pkt->set<uint32_t>(intEnabled[(daddr-GICD_ICENABLER_ST)>>2]);
|
assert(ix < 32);
|
||||||
|
pkt->set<uint32_t>(getIntEnabled(ctx_id, ix));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ISPENDR_ST && daddr < GICD_ISPENDR_ED + 4) {
|
if (GICD_ISPENDR.contains(daddr)) {
|
||||||
assert((daddr-GICD_ISPENDR_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
|
||||||
pkt->set<uint32_t>(pendingInt[(daddr-GICD_ISPENDR_ST)>>2]);
|
assert(ix < 32);
|
||||||
|
pkt->set<uint32_t>(getPendingInt(ctx_id, ix));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ICPENDR_ST && daddr < GICD_ICPENDR_ED + 4) {
|
if (GICD_ICPENDR.contains(daddr)) {
|
||||||
assert((daddr-GICD_ICPENDR_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
|
||||||
pkt->set<uint32_t>(pendingInt[(daddr-GICD_ICPENDR_ST)>>2]);
|
assert(ix < 32);
|
||||||
|
pkt->set<uint32_t>(getPendingInt(ctx_id, ix));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ISACTIVER_ST && daddr < GICD_ISACTIVER_ED + 4) {
|
if (GICD_ISACTIVER.contains(daddr)) {
|
||||||
assert((daddr-GICD_ISACTIVER_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
|
||||||
pkt->set<uint32_t>(activeInt[(daddr-GICD_ISACTIVER_ST)>>2]);
|
assert(ix < 32);
|
||||||
|
pkt->set<uint32_t>(getPendingInt(ctx_id, ix));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_IPRIORITYR_ST && daddr < GICD_IPRIORITYR_ED + 4) {
|
if (GICD_ICACTIVER.contains(daddr)) {
|
||||||
Addr int_num;
|
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
|
||||||
int_num = daddr - GICD_IPRIORITYR_ST;
|
assert(ix < 32);
|
||||||
|
pkt->set<uint32_t>(getPendingInt(ctx_id, ix));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GICD_IPRIORITYR.contains(daddr)) {
|
||||||
|
Addr int_num = daddr - GICD_IPRIORITYR.start();
|
||||||
assert(int_num < INT_LINES_MAX);
|
assert(int_num < INT_LINES_MAX);
|
||||||
DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
|
DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
|
||||||
|
|
||||||
uint8_t* int_p;
|
|
||||||
if (int_num < (SGI_MAX + PPI_MAX))
|
|
||||||
int_p = bankedIntPriority[ctx_id];
|
|
||||||
else
|
|
||||||
int_p = intPriority;
|
|
||||||
|
|
||||||
switch (pkt->getSize()) {
|
switch (pkt->getSize()) {
|
||||||
case 1:
|
case 1:
|
||||||
pkt->set<uint8_t>(int_p[int_num]);
|
pkt->set<uint8_t>(getIntPriority(ctx_id, int_num));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
assert((int_num + 1) < INT_LINES_MAX);
|
assert((int_num + 1) < INT_LINES_MAX);
|
||||||
pkt->set<uint16_t>(int_p[int_num] |
|
pkt->set<uint16_t>(getIntPriority(ctx_id, int_num) |
|
||||||
int_p[int_num+1] << 8);
|
getIntPriority(ctx_id, int_num+1) << 8);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
assert((int_num + 3) < INT_LINES_MAX);
|
assert((int_num + 3) < INT_LINES_MAX);
|
||||||
pkt->set<uint32_t>(int_p[int_num] |
|
pkt->set<uint32_t>(getIntPriority(ctx_id, int_num) |
|
||||||
int_p[int_num+1] << 8 |
|
getIntPriority(ctx_id, int_num+1) << 8 |
|
||||||
int_p[int_num+2] << 16 |
|
getIntPriority(ctx_id, int_num+2) << 16 |
|
||||||
int_p[int_num+3] << 24);
|
getIntPriority(ctx_id, int_num+3) << 24);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Invalid size while reading priority regs in GIC: %d\n",
|
panic("Invalid size while reading priority regs in GIC: %d\n",
|
||||||
|
@ -210,9 +197,8 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ITARGETSR_ST && daddr < GICD_ITARGETSR_ED + 4) {
|
if (GICD_ITARGETSR.contains(daddr)) {
|
||||||
Addr int_num;
|
Addr int_num = daddr - GICD_ITARGETSR.start();
|
||||||
int_num = (daddr-GICD_ITARGETSR_ST) ;
|
|
||||||
DPRINTF(GIC, "Reading processor target register for int# %#x \n",
|
DPRINTF(GIC, "Reading processor target register for int# %#x \n",
|
||||||
int_num);
|
int_num);
|
||||||
assert(int_num < INT_LINES_MAX);
|
assert(int_num < INT_LINES_MAX);
|
||||||
|
@ -246,12 +232,12 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ICFGR_ST && daddr < GICD_ICFGR_ED + 4) {
|
if (GICD_ICFGR.contains(daddr)) {
|
||||||
assert((daddr-GICD_ICFGR_ST) >> 2 < 64);
|
uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
|
||||||
/** @todo software generated interrutps and PPIs
|
assert(ix < 64);
|
||||||
* can't be configured in some ways
|
/** @todo software generated interrupts and PPIs
|
||||||
*/
|
* can't be configured in some ways */
|
||||||
pkt->set<uint32_t>(intConfig[(daddr-GICD_ICFGR_ST)>>2]);
|
pkt->set<uint32_t>(intConfig[ix]);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +248,7 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
case GICD_TYPER: {
|
case GICD_TYPER: {
|
||||||
/* The 0x100 is a made-up flag to show that gem5 extensions
|
/* The 0x100 is a made-up flag to show that gem5 extensions
|
||||||
* are available,
|
* are available,
|
||||||
* write 0x200 to this register to enable it.
|
* write 0x200 to this register to enable it. */
|
||||||
*/
|
|
||||||
uint32_t tmp = ((sys->numRunningContexts() - 1) << 5) |
|
uint32_t tmp = ((sys->numRunningContexts() - 1) << 5) |
|
||||||
(itLines/INT_BITS_MAX -1) |
|
(itLines/INT_BITS_MAX -1) |
|
||||||
(haveGem5Extensions ? 0x100 : 0x0);
|
(haveGem5Extensions ? 0x100 : 0x0);
|
||||||
|
@ -342,7 +327,8 @@ Pl390::readCpu(PacketPtr pkt)
|
||||||
uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx_id]);
|
uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx_id]);
|
||||||
activeInt[intNumToWord(cpuHighestInt[ctx_id])] |= int_num;
|
activeInt[intNumToWord(cpuHighestInt[ctx_id])] |= int_num;
|
||||||
updateRunPri();
|
updateRunPri();
|
||||||
pendingInt[intNumToWord(cpuHighestInt[ctx_id])] &= ~int_num;
|
getPendingInt(ctx_id, intNumToWord(cpuHighestInt[ctx_id]))
|
||||||
|
&= ~int_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(Interrupt,"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
|
DPRINTF(Interrupt,"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
|
||||||
|
@ -399,60 +385,70 @@ Pl390::writeDistributor(PacketPtr pkt)
|
||||||
DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
|
DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
|
||||||
daddr, pkt->getSize(), pkt_data);
|
daddr, pkt->getSize(), pkt_data);
|
||||||
|
|
||||||
if (daddr >= GICD_ISENABLER_ST && daddr < GICD_ISENABLER_ED + 4) {
|
if (GICD_ISENABLER.contains(daddr)) {
|
||||||
assert((daddr-GICD_ISENABLER_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
|
||||||
intEnabled[(daddr-GICD_ISENABLER_ST) >> 2] |= pkt->get<uint32_t>();
|
assert(ix < 32);
|
||||||
|
getIntEnabled(ctx_id, ix) |= pkt->get<uint32_t>();
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ICENABLER_ST && daddr < GICD_ICENABLER_ED + 4) {
|
if (GICD_ICENABLER.contains(daddr)) {
|
||||||
assert((daddr-GICD_ICENABLER_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
|
||||||
intEnabled[(daddr-GICD_ICENABLER_ST) >> 2] &= ~pkt->get<uint32_t>();
|
assert(ix < 32);
|
||||||
|
getIntEnabled(ctx_id, ix) &= ~pkt->get<uint32_t>();
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ISPENDR_ST && daddr < GICD_ISPENDR_ED + 4) {
|
if (GICD_ISPENDR.contains(daddr)) {
|
||||||
assert((daddr-GICD_ISPENDR_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
|
||||||
pendingInt[(daddr-GICD_ISPENDR_ST) >> 2] |= pkt->get<uint32_t>();
|
auto mask = pkt->get<uint32_t>();
|
||||||
pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
|
if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
|
||||||
updateIntState((daddr-GICD_ISPENDR_ST) >> 2);
|
getPendingInt(ctx_id, ix) |= mask;
|
||||||
|
updateIntState(ix);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ICPENDR_ST && daddr < GICD_ICPENDR_ED + 4) {
|
if (GICD_ICPENDR.contains(daddr)) {
|
||||||
assert((daddr-GICD_ICPENDR_ST) >> 2 < 32);
|
uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
|
||||||
pendingInt[(daddr-GICD_ICPENDR_ST) >> 2] &= ~pkt->get<uint32_t>();
|
auto mask = pkt->get<uint32_t>();
|
||||||
pendingInt[0] &= SGI_MASK; // Don't allow SGIs to be changed
|
if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
|
||||||
updateIntState((daddr-GICD_ICPENDR_ST) >> 2);
|
getPendingInt(ctx_id, ix) &= ~mask;
|
||||||
|
updateIntState(ix);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_IPRIORITYR_ST && daddr < GICD_IPRIORITYR_ED + 4) {
|
if (GICD_ISACTIVER.contains(daddr)) {
|
||||||
Addr int_num = daddr - GICD_IPRIORITYR_ST;
|
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
|
||||||
assert(int_num < INT_LINES_MAX);
|
getActiveInt(ctx_id, ix) |= pkt->get<uint32_t>();
|
||||||
uint8_t* int_p;
|
goto done;
|
||||||
if (int_num < (SGI_MAX + PPI_MAX))
|
}
|
||||||
int_p = bankedIntPriority[ctx_id];
|
|
||||||
else
|
if (GICD_ICACTIVER.contains(daddr)) {
|
||||||
int_p = intPriority;
|
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
|
||||||
uint32_t tmp;
|
getActiveInt(ctx_id, ix) &= ~pkt->get<uint32_t>();
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GICD_IPRIORITYR.contains(daddr)) {
|
||||||
|
Addr int_num = daddr - GICD_IPRIORITYR.start();
|
||||||
switch(pkt->getSize()) {
|
switch(pkt->getSize()) {
|
||||||
case 1:
|
case 1:
|
||||||
tmp = pkt->get<uint8_t>();
|
getIntPriority(ctx_id, int_num) = pkt->get<uint8_t>();
|
||||||
int_p[int_num] = bits(tmp, 7, 0);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2: {
|
||||||
tmp = pkt->get<uint16_t>();
|
auto tmp16 = pkt->get<uint16_t>();
|
||||||
int_p[int_num] = bits(tmp, 7, 0);
|
getIntPriority(ctx_id, int_num) = bits(tmp16, 7, 0);
|
||||||
int_p[int_num + 1] = bits(tmp, 15, 8);
|
getIntPriority(ctx_id, int_num + 1) = bits(tmp16, 15, 8);
|
||||||
break;
|
break;
|
||||||
case 4:
|
}
|
||||||
tmp = pkt->get<uint32_t>();
|
case 4: {
|
||||||
int_p[int_num] = bits(tmp, 7, 0);
|
auto tmp32 = pkt->get<uint32_t>();
|
||||||
int_p[int_num + 1] = bits(tmp, 15, 8);
|
getIntPriority(ctx_id, int_num) = bits(tmp32, 7, 0);
|
||||||
int_p[int_num + 2] = bits(tmp, 23, 16);
|
getIntPriority(ctx_id, int_num + 1) = bits(tmp32, 15, 8);
|
||||||
int_p[int_num + 3] = bits(tmp, 31, 24);
|
getIntPriority(ctx_id, int_num + 2) = bits(tmp32, 23, 16);
|
||||||
|
getIntPriority(ctx_id, int_num + 3) = bits(tmp32, 31, 24);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic("Invalid size when writing to priority regs in Gic: %d\n",
|
panic("Invalid size when writing to priority regs in Gic: %d\n",
|
||||||
pkt->getSize());
|
pkt->getSize());
|
||||||
|
@ -463,9 +459,8 @@ Pl390::writeDistributor(PacketPtr pkt)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ITARGETSR_ST && daddr < GICD_ITARGETSR_ED + 4) {
|
if (GICD_ITARGETSR.contains(daddr)) {
|
||||||
Addr int_num = (daddr-GICD_ITARGETSR_ST) ;
|
Addr int_num = daddr - GICD_ITARGETSR.start();
|
||||||
assert(int_num < INT_LINES_MAX);
|
|
||||||
// First 31 interrupts only target single processor
|
// First 31 interrupts only target single processor
|
||||||
if (int_num >= SGI_MAX) {
|
if (int_num >= SGI_MAX) {
|
||||||
if (pkt->getSize() == 1) {
|
if (pkt->getSize() == 1) {
|
||||||
|
@ -480,14 +475,15 @@ Pl390::writeDistributor(PacketPtr pkt)
|
||||||
cpuTarget[int_num+2] = bits(tmp, 23, 16);
|
cpuTarget[int_num+2] = bits(tmp, 23, 16);
|
||||||
cpuTarget[int_num+3] = bits(tmp, 31, 24);
|
cpuTarget[int_num+3] = bits(tmp, 31, 24);
|
||||||
}
|
}
|
||||||
updateIntState((daddr-GICD_ITARGETSR_ST)>>2);
|
updateIntState(int_num >> 2);
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daddr >= GICD_ICFGR_ST && daddr < GICD_ICFGR_ED + 4) {
|
if (GICD_ICFGR.contains(daddr)) {
|
||||||
assert((daddr-GICD_ICFGR_ST) >> 2 < 64);
|
uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
|
||||||
intConfig[(daddr-GICD_ICFGR_ST)>>2] = pkt->get<uint32_t>();
|
assert(ix < INT_BITS_MAX*2);
|
||||||
|
intConfig[ix] = pkt->get<uint32_t>();
|
||||||
if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
|
if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
|
||||||
warn("GIC N:N mode selected and not supported at this time\n");
|
warn("GIC N:N mode selected and not supported at this time\n");
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -562,10 +558,10 @@ Pl390::writeCpu(PacketPtr pkt)
|
||||||
cpuPpiActive[ctx_id] &= ~int_num;
|
cpuPpiActive[ctx_id] &= ~int_num;
|
||||||
} else {
|
} else {
|
||||||
uint32_t int_num = 1 << intNumToBit(iar.ack_id);
|
uint32_t int_num = 1 << intNumToBit(iar.ack_id);
|
||||||
if (!(activeInt[intNumToWord(iar.ack_id)] & int_num))
|
if (!(getActiveInt(ctx_id, intNumToWord(iar.ack_id)) & int_num))
|
||||||
warn("Done handling interrupt that isn't active: %d\n",
|
warn("Done handling interrupt that isn't active: %d\n",
|
||||||
intNumToBit(iar.ack_id));
|
intNumToBit(iar.ack_id));
|
||||||
activeInt[intNumToWord(iar.ack_id)] &= ~int_num;
|
getActiveInt(ctx_id, intNumToWord(iar.ack_id)) &= ~int_num;
|
||||||
}
|
}
|
||||||
updateRunPri();
|
updateRunPri();
|
||||||
DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
|
DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
|
||||||
|
@ -580,6 +576,16 @@ Pl390::writeCpu(PacketPtr pkt)
|
||||||
return cpuPioDelay;
|
return cpuPioDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pl390::BankedRegs&
|
||||||
|
Pl390::getBankedRegs(ContextID ctx_id) {
|
||||||
|
if (bankedRegs.size() <= ctx_id)
|
||||||
|
bankedRegs.resize(ctx_id + 1);
|
||||||
|
|
||||||
|
if (!bankedRegs[ctx_id])
|
||||||
|
bankedRegs[ctx_id] = new BankedRegs;
|
||||||
|
return *bankedRegs[ctx_id];
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Pl390::softInt(ContextID ctx_id, SWI swi)
|
Pl390::softInt(ContextID ctx_id, SWI swi)
|
||||||
{
|
{
|
||||||
|
@ -676,8 +682,8 @@ Pl390::updateIntState(int hint)
|
||||||
continue;
|
continue;
|
||||||
if ((cpuSgiPending[swi] & genSwiMask(cpu)) ||
|
if ((cpuSgiPending[swi] & genSwiMask(cpu)) ||
|
||||||
(cpuSgiPendingExt[cpu] & (1 << swi)))
|
(cpuSgiPendingExt[cpu] & (1 << swi)))
|
||||||
if (highest_pri > bankedIntPriority[cpu][swi]) {
|
if (highest_pri > getIntPriority(cpu, swi)) {
|
||||||
highest_pri = bankedIntPriority[cpu][swi];
|
highest_pri = getIntPriority(cpu, swi);
|
||||||
highest_int = swi;
|
highest_int = swi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,8 +692,8 @@ Pl390::updateIntState(int hint)
|
||||||
if (cpuPpiPending[cpu]) {
|
if (cpuPpiPending[cpu]) {
|
||||||
for (int ppi = 0; ppi < PPI_MAX; ppi++) {
|
for (int ppi = 0; ppi < PPI_MAX; ppi++) {
|
||||||
if (cpuPpiPending[cpu] & (1 << ppi))
|
if (cpuPpiPending[cpu] & (1 << ppi))
|
||||||
if (highest_pri > bankedIntPriority[cpu][SGI_MAX + ppi]) {
|
if (highest_pri > getIntPriority(cpu, SGI_MAX + ppi)) {
|
||||||
highest_pri = bankedIntPriority[cpu][SGI_MAX + ppi];
|
highest_pri = getIntPriority(cpu, SGI_MAX + ppi);
|
||||||
highest_int = SGI_MAX + ppi;
|
highest_int = SGI_MAX + ppi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -696,21 +702,22 @@ Pl390::updateIntState(int hint)
|
||||||
bool mp_sys = sys->numRunningContexts() > 1;
|
bool mp_sys = sys->numRunningContexts() > 1;
|
||||||
// Check other ints
|
// Check other ints
|
||||||
for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
|
for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
|
||||||
if (intEnabled[x] & pendingInt[x]) {
|
if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) {
|
||||||
for (int y = 0; y < INT_BITS_MAX; y++) {
|
for (int y = 0; y < INT_BITS_MAX; y++) {
|
||||||
uint32_t int_nm = x * INT_BITS_MAX + y;
|
uint32_t int_nm = x * INT_BITS_MAX + y;
|
||||||
DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
|
DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
|
||||||
/* Set current pending int as highest int for current cpu
|
/* Set current pending int as highest int for current cpu
|
||||||
if the interrupt's priority higher than current prioirty
|
if the interrupt's priority higher than current priority
|
||||||
and if currrent cpu is the target (for mp configs only)
|
and if currrent cpu is the target (for mp configs only)
|
||||||
*/
|
*/
|
||||||
if ((bits(intEnabled[x], y) & bits(pendingInt[x], y)) &&
|
if ((bits(getIntEnabled(cpu, x), y)
|
||||||
(intPriority[int_nm] < highest_pri))
|
&bits(getPendingInt(cpu, x), y)) &&
|
||||||
if ( (!mp_sys) ||
|
(getIntPriority(cpu, int_nm) < highest_pri))
|
||||||
(!gem5ExtensionsEnabled && (cpuTarget[int_nm] & (1 << cpu))) ||
|
if ((!mp_sys) ||
|
||||||
(gem5ExtensionsEnabled && (cpuTarget[int_nm] == cpu))
|
(gem5ExtensionsEnabled
|
||||||
) {
|
? (cpuTarget[int_nm] == cpu)
|
||||||
highest_pri = intPriority[int_nm];
|
: (cpuTarget[int_nm] & (1 << cpu)))) {
|
||||||
|
highest_pri = getIntPriority(cpu, int_nm);
|
||||||
highest_int = int_nm;
|
highest_int = int_nm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -725,8 +732,8 @@ Pl390::updateIntState(int hint)
|
||||||
/* @todo make this work for more than one cpu, need to handle 1:N, N:N
|
/* @todo make this work for more than one cpu, need to handle 1:N, N:N
|
||||||
* models */
|
* models */
|
||||||
if (enabled && cpuEnabled[cpu] && (highest_pri < cpuPriority[cpu]) &&
|
if (enabled && cpuEnabled[cpu] && (highest_pri < cpuPriority[cpu]) &&
|
||||||
!(activeInt[intNumToWord(highest_int)]
|
!(getActiveInt(cpu, intNumToWord(highest_int))
|
||||||
& (1 << intNumToBit(highest_int)))) {
|
& (1 << intNumToBit(highest_int)))) {
|
||||||
|
|
||||||
DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
|
DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
|
||||||
cpu);
|
cpu);
|
||||||
|
@ -742,21 +749,22 @@ Pl390::updateRunPri()
|
||||||
if (!cpuEnabled[cpu])
|
if (!cpuEnabled[cpu])
|
||||||
continue;
|
continue;
|
||||||
uint8_t maxPriority = 0xff;
|
uint8_t maxPriority = 0xff;
|
||||||
for (int i = 0; i < itLines; i++){
|
for (int i = 0; i < itLines; i++) {
|
||||||
if (i < SGI_MAX) {
|
if (i < SGI_MAX) {
|
||||||
if (((cpuSgiActive[i] & genSwiMask(cpu)) ||
|
if (((cpuSgiActive[i] & genSwiMask(cpu)) ||
|
||||||
(cpuSgiActiveExt[cpu] & (1 << i))) &&
|
(cpuSgiActiveExt[cpu] & (1 << i))) &&
|
||||||
(bankedIntPriority[cpu][i] < maxPriority))
|
(getIntPriority(cpu, i) < maxPriority))
|
||||||
maxPriority = bankedIntPriority[cpu][i];
|
maxPriority = getIntPriority(cpu, i);
|
||||||
} else if (i < (SGI_MAX + PPI_MAX)) {
|
} else if (i < (SGI_MAX + PPI_MAX)) {
|
||||||
if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
|
if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
|
||||||
(bankedIntPriority[cpu][i] < maxPriority))
|
(getIntPriority(cpu, i) < maxPriority))
|
||||||
maxPriority = bankedIntPriority[cpu][i];
|
maxPriority = getIntPriority(cpu, i);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (activeInt[intNumToWord(i)] & (1 << intNumToBit(i)))
|
if (getActiveInt(cpu, intNumToWord(i))
|
||||||
if (intPriority[i] < maxPriority)
|
& (1 << intNumToBit(i)))
|
||||||
maxPriority = intPriority[i];
|
if (getIntPriority(cpu, i) < maxPriority)
|
||||||
|
maxPriority = getIntPriority(cpu, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iccrpr[cpu] = maxPriority;
|
iccrpr[cpu] = maxPriority;
|
||||||
|
@ -770,9 +778,10 @@ Pl390::sendInt(uint32_t num)
|
||||||
num, cpuTarget[num]);
|
num, cpuTarget[num]);
|
||||||
if ((cpuTarget[num] & (cpuTarget[num] - 1)) && !gem5ExtensionsEnabled)
|
if ((cpuTarget[num] & (cpuTarget[num] - 1)) && !gem5ExtensionsEnabled)
|
||||||
panic("Multiple targets for peripheral interrupts is not supported\n");
|
panic("Multiple targets for peripheral interrupts is not supported\n");
|
||||||
pendingInt[intNumToWord(num)] |= 1 << intNumToBit(num);
|
panic_if(num < SGI_MAX + PPI_MAX,
|
||||||
|
"sentInt() must only be used for interrupts 32 and higher");
|
||||||
|
getPendingInt(cpuTarget[num], intNumToWord(num)) |= 1 << intNumToBit(num);
|
||||||
updateIntState(intNumToWord(num));
|
updateIntState(intNumToWord(num));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -827,13 +836,12 @@ Pl390::serialize(CheckpointOut &cp) const
|
||||||
SERIALIZE_SCALAR(cpuPioDelay);
|
SERIALIZE_SCALAR(cpuPioDelay);
|
||||||
SERIALIZE_SCALAR(enabled);
|
SERIALIZE_SCALAR(enabled);
|
||||||
SERIALIZE_SCALAR(itLines);
|
SERIALIZE_SCALAR(itLines);
|
||||||
SERIALIZE_SCALAR(itLinesLog2);
|
SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1);
|
||||||
SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
|
SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1);
|
||||||
SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
|
SERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1);
|
||||||
SERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
|
|
||||||
SERIALIZE_ARRAY(iccrpr, CPU_MAX);
|
SERIALIZE_ARRAY(iccrpr, CPU_MAX);
|
||||||
SERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
|
SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES);
|
||||||
SERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
|
SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES);
|
||||||
SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
|
SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
|
||||||
SERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
|
SERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
|
||||||
SERIALIZE_ARRAY(cpuPriority, CPU_MAX);
|
SERIALIZE_ARRAY(cpuPriority, CPU_MAX);
|
||||||
|
@ -845,7 +853,6 @@ Pl390::serialize(CheckpointOut &cp) const
|
||||||
SERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX);
|
SERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX);
|
||||||
SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
|
SERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
|
||||||
SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
|
SERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
|
||||||
SERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
|
|
||||||
SERIALIZE_SCALAR(irqEnable);
|
SERIALIZE_SCALAR(irqEnable);
|
||||||
Tick interrupt_time[CPU_MAX];
|
Tick interrupt_time[CPU_MAX];
|
||||||
for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
|
for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
|
||||||
|
@ -856,6 +863,22 @@ Pl390::serialize(CheckpointOut &cp) const
|
||||||
}
|
}
|
||||||
SERIALIZE_ARRAY(interrupt_time, CPU_MAX);
|
SERIALIZE_ARRAY(interrupt_time, CPU_MAX);
|
||||||
SERIALIZE_SCALAR(gem5ExtensionsEnabled);
|
SERIALIZE_SCALAR(gem5ExtensionsEnabled);
|
||||||
|
|
||||||
|
for (uint32_t i=0; i < bankedRegs.size(); ++i) {
|
||||||
|
if (!bankedRegs[i])
|
||||||
|
continue;
|
||||||
|
bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Pl390::BankedRegs::serialize(CheckpointOut &cp) const
|
||||||
|
{
|
||||||
|
SERIALIZE_SCALAR(intEnabled);
|
||||||
|
SERIALIZE_SCALAR(pendingInt);
|
||||||
|
SERIALIZE_SCALAR(activeInt);
|
||||||
|
SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
|
||||||
|
SERIALIZE_ARRAY(cpuTarget, SGI_MAX + PPI_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -869,13 +892,12 @@ Pl390::unserialize(CheckpointIn &cp)
|
||||||
UNSERIALIZE_SCALAR(cpuPioDelay);
|
UNSERIALIZE_SCALAR(cpuPioDelay);
|
||||||
UNSERIALIZE_SCALAR(enabled);
|
UNSERIALIZE_SCALAR(enabled);
|
||||||
UNSERIALIZE_SCALAR(itLines);
|
UNSERIALIZE_SCALAR(itLines);
|
||||||
UNSERIALIZE_SCALAR(itLinesLog2);
|
UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1);
|
||||||
UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX);
|
UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1);
|
||||||
UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX);
|
UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1);
|
||||||
UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX);
|
|
||||||
UNSERIALIZE_ARRAY(iccrpr, CPU_MAX);
|
UNSERIALIZE_ARRAY(iccrpr, CPU_MAX);
|
||||||
UNSERIALIZE_ARRAY(intPriority, INT_LINES_MAX);
|
UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES);
|
||||||
UNSERIALIZE_ARRAY(cpuTarget, INT_LINES_MAX);
|
UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES);
|
||||||
UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
|
UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
|
||||||
UNSERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
|
UNSERIALIZE_ARRAY(cpuEnabled, CPU_MAX);
|
||||||
UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX);
|
UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX);
|
||||||
|
@ -887,7 +909,6 @@ Pl390::unserialize(CheckpointIn &cp)
|
||||||
UNSERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX);
|
UNSERIALIZE_ARRAY(cpuSgiPendingExt, CPU_MAX);
|
||||||
UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
|
UNSERIALIZE_ARRAY(cpuPpiActive, CPU_MAX);
|
||||||
UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
|
UNSERIALIZE_ARRAY(cpuPpiPending, CPU_MAX);
|
||||||
UNSERIALIZE_ARRAY(*bankedIntPriority, CPU_MAX * (SGI_MAX + PPI_MAX));
|
|
||||||
UNSERIALIZE_SCALAR(irqEnable);
|
UNSERIALIZE_SCALAR(irqEnable);
|
||||||
|
|
||||||
Tick interrupt_time[CPU_MAX];
|
Tick interrupt_time[CPU_MAX];
|
||||||
|
@ -899,6 +920,23 @@ Pl390::unserialize(CheckpointIn &cp)
|
||||||
}
|
}
|
||||||
if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled))
|
if (!UNSERIALIZE_OPT_SCALAR(gem5ExtensionsEnabled))
|
||||||
gem5ExtensionsEnabled = false;
|
gem5ExtensionsEnabled = false;
|
||||||
|
|
||||||
|
for (uint32_t i=0; i < CPU_MAX; ++i) {
|
||||||
|
ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i));
|
||||||
|
if (cp.sectionExists(Serializable::currentSection())) {
|
||||||
|
getBankedRegs(i).unserialize(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Pl390::BankedRegs::unserialize(CheckpointIn &cp)
|
||||||
|
{
|
||||||
|
UNSERIALIZE_SCALAR(intEnabled);
|
||||||
|
UNSERIALIZE_SCALAR(pendingInt);
|
||||||
|
UNSERIALIZE_SCALAR(activeInt);
|
||||||
|
UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
|
||||||
|
UNSERIALIZE_ARRAY(cpuTarget, SGI_MAX + PPI_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pl390 *
|
Pl390 *
|
||||||
|
@ -909,10 +947,10 @@ Pl390Params::create()
|
||||||
|
|
||||||
/* Functions for debugging and testing */
|
/* Functions for debugging and testing */
|
||||||
void
|
void
|
||||||
Pl390::driveSPI(unsigned int spiVect)
|
Pl390::driveSPI(uint32_t spiVect)
|
||||||
{
|
{
|
||||||
DPRINTF(GIC, "Received SPI Vector:%x Enable: %d\n", spiVect, irqEnable);
|
DPRINTF(GIC, "Received SPI Vector:%x Enable: %d\n", spiVect, irqEnable);
|
||||||
pendingInt[1] |= spiVect;
|
getPendingInt(0, 1) |= spiVect;
|
||||||
if (irqEnable && enabled) {
|
if (irqEnable && enabled) {
|
||||||
updateIntState(-1);
|
updateIntState(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,12 +42,15 @@
|
||||||
|
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
* Implementiation of a PL390 GIC
|
* Implementation of a PL390 GIC
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DEV_ARM_GIC_PL390_H__
|
#ifndef __DEV_ARM_GIC_PL390_H__
|
||||||
#define __DEV_ARM_GIC_PL390_H__
|
#define __DEV_ARM_GIC_PL390_H__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/addr_range.hh"
|
||||||
#include "base/bitunion.hh"
|
#include "base/bitunion.hh"
|
||||||
#include "cpu/intr_control.hh"
|
#include "cpu/intr_control.hh"
|
||||||
#include "dev/arm/base_gic.hh"
|
#include "dev/arm/base_gic.hh"
|
||||||
|
@ -55,12 +58,6 @@
|
||||||
#include "dev/platform.hh"
|
#include "dev/platform.hh"
|
||||||
#include "params/Pl390.hh"
|
#include "params/Pl390.hh"
|
||||||
|
|
||||||
/** @todo this code only assumes one processor for now. Low word
|
|
||||||
* of intEnabled and pendingInt need to be replicated per CPU.
|
|
||||||
* bottom 31 interrupts (7 words) need to be replicated for
|
|
||||||
* for interrupt priority register, processor target registers
|
|
||||||
* interrupt config registers */
|
|
||||||
|
|
||||||
class Pl390 : public BaseGic
|
class Pl390 : public BaseGic
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -69,28 +66,22 @@ class Pl390 : public BaseGic
|
||||||
GICD_CTLR = 0x000, // control register
|
GICD_CTLR = 0x000, // control register
|
||||||
GICD_TYPER = 0x004, // controller type
|
GICD_TYPER = 0x004, // controller type
|
||||||
GICD_IIDR = 0x008, // implementer id
|
GICD_IIDR = 0x008, // implementer id
|
||||||
GICD_ISENABLER_ST = 0x100, // interrupt set enable
|
|
||||||
GICD_ISENABLER_ED = 0x17c,
|
|
||||||
GICD_ICENABLER_ST = 0x180, // interrupt clear enable
|
|
||||||
GICD_ICENABLER_ED = 0x1fc,
|
|
||||||
GICD_ISPENDR_ST = 0x200, // set pending interrupt
|
|
||||||
GICD_ISPENDR_ED = 0x27c,
|
|
||||||
GICD_ICPENDR_ST = 0x280, // clear pending interrupt
|
|
||||||
GICD_ICPENDR_ED = 0x2fc,
|
|
||||||
GICD_ISACTIVER_ST = 0x300, // active bit registers
|
|
||||||
GICD_ISACTIVER_ED = 0x37c,
|
|
||||||
GICD_IPRIORITYR_ST = 0x400, // interrupt priority registers
|
|
||||||
GICD_IPRIORITYR_ED = 0x7f8,
|
|
||||||
GICD_ITARGETSR_ST = 0x800, // processor target registers
|
|
||||||
GICD_ITARGETSR_ED = 0xbf8,
|
|
||||||
GICD_ICFGR_ST = 0xc00, // interrupt config registers
|
|
||||||
GICD_ICFGR_ED = 0xcfc,
|
|
||||||
GICD_SGIR = 0xf00, // software generated interrupt
|
GICD_SGIR = 0xf00, // software generated interrupt
|
||||||
|
|
||||||
DIST_SIZE = 0xfff
|
DIST_SIZE = 0xfff
|
||||||
};
|
};
|
||||||
|
|
||||||
// cpu memory addressesa
|
static const AddrRange GICD_ISENABLER; // interrupt set enable
|
||||||
|
static const AddrRange GICD_ICENABLER; // interrupt clear enable
|
||||||
|
static const AddrRange GICD_ISPENDR; // set pending interrupt
|
||||||
|
static const AddrRange GICD_ICPENDR; // clear pending interrupt
|
||||||
|
static const AddrRange GICD_ISACTIVER; // active bit registers
|
||||||
|
static const AddrRange GICD_ICACTIVER; // clear bit registers
|
||||||
|
static const AddrRange GICD_IPRIORITYR; // interrupt priority registers
|
||||||
|
static const AddrRange GICD_ITARGETSR; // processor target registers
|
||||||
|
static const AddrRange GICD_ICFGR; // interrupt config registers
|
||||||
|
|
||||||
|
// cpu memory addresses
|
||||||
enum {
|
enum {
|
||||||
GICC_CTLR = 0x00, // CPU control register
|
GICC_CTLR = 0x00, // CPU control register
|
||||||
GICC_PMR = 0x04, // Interrupt priority mask
|
GICC_PMR = 0x04, // Interrupt priority mask
|
||||||
|
@ -118,6 +109,7 @@ class Pl390 : public BaseGic
|
||||||
static const int SPURIOUS_INT = 1023;
|
static const int SPURIOUS_INT = 1023;
|
||||||
static const int INT_BITS_MAX = 32;
|
static const int INT_BITS_MAX = 32;
|
||||||
static const int INT_LINES_MAX = 1020;
|
static const int INT_LINES_MAX = 1020;
|
||||||
|
static const int GLOBAL_INT_LINES = INT_LINES_MAX - SGI_MAX - PPI_MAX;
|
||||||
|
|
||||||
BitUnion32(SWI)
|
BitUnion32(SWI)
|
||||||
Bitfield<3,0> sgi_id;
|
Bitfield<3,0> sgi_id;
|
||||||
|
@ -149,41 +141,121 @@ class Pl390 : public BaseGic
|
||||||
/** Gic enabled */
|
/** Gic enabled */
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
|
/** Are gem5 extensions available? */
|
||||||
|
const bool haveGem5Extensions;
|
||||||
|
|
||||||
/** gem5 many-core extension enabled by driver */
|
/** gem5 many-core extension enabled by driver */
|
||||||
bool gem5ExtensionsEnabled;
|
bool gem5ExtensionsEnabled;
|
||||||
|
|
||||||
/** Number of itLines enabled */
|
/** Number of itLines enabled */
|
||||||
uint32_t itLines;
|
uint32_t itLines;
|
||||||
|
|
||||||
uint32_t itLinesLog2;
|
/** Registers "banked for each connected processor" per ARM IHI0048B */
|
||||||
|
struct BankedRegs : public Serializable {
|
||||||
|
/** GICD_I{S,C}ENABLER0
|
||||||
|
* interrupt enable bits for first 32 interrupts, 1b per interrupt */
|
||||||
|
uint32_t intEnabled;
|
||||||
|
|
||||||
/** Are gem5 extensions available? */
|
/** GICD_I{S,C}PENDR0
|
||||||
const bool haveGem5Extensions;
|
* interrupt pending bits for first 32 interrupts, 1b per interrupt */
|
||||||
|
uint32_t pendingInt;
|
||||||
|
|
||||||
/** interrupt enable bits for all possible 1020 interupts.
|
/** GICD_I{S,C}ACTIVER0
|
||||||
* one bit per interrupt, 32 bit per word = 32 words */
|
* interrupt active bits for first 32 interrupts, 1b per interrupt */
|
||||||
uint32_t intEnabled[INT_BITS_MAX];
|
uint32_t activeInt;
|
||||||
|
|
||||||
/** interrupt pending bits for all possible 1020 interupts.
|
/** GICD_IPRIORITYR{0..7}
|
||||||
* one bit per interrupt, 32 bit per word = 32 words */
|
* interrupt priority for SGIs and PPIs */
|
||||||
uint32_t pendingInt[INT_BITS_MAX];
|
uint8_t intPriority[SGI_MAX + PPI_MAX];
|
||||||
|
|
||||||
/** interrupt active bits for all possible 1020 interupts.
|
/** GICD_ITARGETSR{0..7}
|
||||||
* one bit per interrupt, 32 bit per word = 32 words */
|
* 8b CPU target ID for each SGI and PPI */
|
||||||
uint32_t activeInt[INT_BITS_MAX];
|
uint8_t cpuTarget[SGI_MAX + PPI_MAX];
|
||||||
|
|
||||||
/** read only running priroity register, 1 per cpu*/
|
void serialize(CheckpointOut &cp) const override;
|
||||||
|
void unserialize(CheckpointIn &cp) override;
|
||||||
|
|
||||||
|
BankedRegs() :
|
||||||
|
intEnabled(0), pendingInt(0), activeInt(0),
|
||||||
|
intPriority {0}, cpuTarget {0}
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
std::vector<BankedRegs*> bankedRegs;
|
||||||
|
|
||||||
|
BankedRegs& getBankedRegs(ContextID);
|
||||||
|
|
||||||
|
/** GICD_I{S,C}ENABLER{1..31}
|
||||||
|
* interrupt enable bits for global interrupts
|
||||||
|
* 1b per interrupt, 32 bits per word, 31 words */
|
||||||
|
uint32_t intEnabled[INT_BITS_MAX-1];
|
||||||
|
|
||||||
|
uint32_t& getIntEnabled(ContextID ctx_id, uint32_t ix) {
|
||||||
|
if (ix == 0) {
|
||||||
|
return getBankedRegs(ctx_id).intEnabled;
|
||||||
|
} else {
|
||||||
|
return intEnabled[ix - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** GICD_I{S,C}PENDR{1..31}
|
||||||
|
* interrupt pending bits for global interrupts
|
||||||
|
* 1b per interrupt, 32 bits per word, 31 words */
|
||||||
|
uint32_t pendingInt[INT_BITS_MAX-1];
|
||||||
|
|
||||||
|
uint32_t& getPendingInt(ContextID ctx_id, uint32_t ix) {
|
||||||
|
assert(ix < INT_BITS_MAX);
|
||||||
|
if (ix == 0) {
|
||||||
|
return getBankedRegs(ctx_id).pendingInt;
|
||||||
|
} else {
|
||||||
|
return pendingInt[ix - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** GICD_I{S,C}ACTIVER{1..31}
|
||||||
|
* interrupt active bits for global interrupts
|
||||||
|
* 1b per interrupt, 32 bits per word, 31 words */
|
||||||
|
uint32_t activeInt[INT_BITS_MAX-1];
|
||||||
|
|
||||||
|
uint32_t& getActiveInt(ContextID ctx_id, uint32_t ix) {
|
||||||
|
assert(ix < INT_BITS_MAX);
|
||||||
|
if (ix == 0) {
|
||||||
|
return getBankedRegs(ctx_id).activeInt;
|
||||||
|
} else {
|
||||||
|
return activeInt[ix - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read only running priority register, 1 per cpu*/
|
||||||
uint32_t iccrpr[CPU_MAX];
|
uint32_t iccrpr[CPU_MAX];
|
||||||
|
|
||||||
/** an 8 bit priority (lower is higher priority) for each
|
/** GICD_IPRIORITYR{8..255}
|
||||||
* of the 1020 possible supported interrupts.
|
* an 8 bit priority (lower is higher priority) for each
|
||||||
|
* of the global (not replicated per CPU) interrupts.
|
||||||
*/
|
*/
|
||||||
uint8_t intPriority[INT_LINES_MAX];
|
uint8_t intPriority[GLOBAL_INT_LINES];
|
||||||
|
|
||||||
/** an 8 bit cpu target id for each shared peripheral interrupt
|
uint8_t& getIntPriority(ContextID ctx_id, uint32_t ix) {
|
||||||
* of the 1020 possible supported interrupts.
|
assert(ix < INT_LINES_MAX);
|
||||||
|
if (ix < SGI_MAX + PPI_MAX) {
|
||||||
|
return getBankedRegs(ctx_id).intPriority[ix];
|
||||||
|
} else {
|
||||||
|
return intPriority[ix - (SGI_MAX + PPI_MAX)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** GICD_ITARGETSR{8..255}
|
||||||
|
* an 8 bit cpu target id for each global interrupt.
|
||||||
*/
|
*/
|
||||||
uint8_t cpuTarget[INT_LINES_MAX];
|
uint8_t cpuTarget[GLOBAL_INT_LINES];
|
||||||
|
|
||||||
|
uint8_t& getCpuTarget(ContextID ctx_id, uint32_t ix) {
|
||||||
|
assert(ix < INT_LINES_MAX);
|
||||||
|
if (ix < SGI_MAX + PPI_MAX) {
|
||||||
|
return getBankedRegs(ctx_id).cpuTarget[ix];
|
||||||
|
} else {
|
||||||
|
return cpuTarget[ix - (SGI_MAX + PPI_MAX)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 2 bit per interrupt signaling if it's level or edge sensitive
|
/** 2 bit per interrupt signaling if it's level or edge sensitive
|
||||||
* and if it is 1:N or N:N */
|
* and if it is 1:N or N:N */
|
||||||
|
@ -219,9 +291,6 @@ class Pl390 : public BaseGic
|
||||||
uint32_t cpuPpiPending[CPU_MAX];
|
uint32_t cpuPpiPending[CPU_MAX];
|
||||||
uint32_t cpuPpiActive[CPU_MAX];
|
uint32_t cpuPpiActive[CPU_MAX];
|
||||||
|
|
||||||
/** Banked interrupt prioirty registers for SGIs and PPIs */
|
|
||||||
uint8_t bankedIntPriority[CPU_MAX][SGI_MAX + PPI_MAX];
|
|
||||||
|
|
||||||
/** IRQ Enable Used for debug */
|
/** IRQ Enable Used for debug */
|
||||||
bool irqEnable;
|
bool irqEnable;
|
||||||
|
|
||||||
|
|
81
util/cpt_upgraders/arm-gicv2-banked-regs.py
Normal file
81
util/cpt_upgraders/arm-gicv2-banked-regs.py
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
# Copyright (c) 2016 ARM Limited
|
||||||
|
# All rights reserved
|
||||||
|
#
|
||||||
|
# The license below extends only to copyright in the software and shall
|
||||||
|
# not be construed as granting a license to any other intellectual
|
||||||
|
# property including but not limited to intellectual property relating
|
||||||
|
# to a hardware implementation of the functionality of the software
|
||||||
|
# licensed hereunder. You may use the software subject to the license
|
||||||
|
# terms below provided that you ensure that this notice is replicated
|
||||||
|
# unmodified and in its entirety in all distributions of the software,
|
||||||
|
# modified or unmodified, in source code or in binary form.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met: redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer;
|
||||||
|
# redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution;
|
||||||
|
# neither the name of the copyright holders nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
# duplicate banked registers into new per-cpu arrays.
|
||||||
|
def upgrader(cpt):
|
||||||
|
if cpt.get('root','isa') == 'arm':
|
||||||
|
for sec in cpt.sections():
|
||||||
|
import re
|
||||||
|
|
||||||
|
if not re.search('\.gic$', sec):
|
||||||
|
continue
|
||||||
|
cpuEnabled = cpt.get(sec, 'cpuEnabled' ).split()
|
||||||
|
|
||||||
|
intEnabled = cpt.get(sec, 'intEnabled' ).split()
|
||||||
|
pendingInt = cpt.get(sec, 'pendingInt' ).split()
|
||||||
|
activeInt = cpt.get(sec, 'activeInt' ).split()
|
||||||
|
intPriority = cpt.get(sec, 'intPriority').split()
|
||||||
|
cpuTarget = cpt.get(sec, 'cpuTarget' ).split()
|
||||||
|
|
||||||
|
b_intEnabled = intEnabled[0]
|
||||||
|
b_pendingInt = pendingInt[0]
|
||||||
|
b_activeInt = activeInt[0]
|
||||||
|
b_cpuTarget = cpuTarget[0:32]
|
||||||
|
|
||||||
|
del intEnabled[0]
|
||||||
|
del pendingInt[0]
|
||||||
|
del activeInt[0]
|
||||||
|
del intPriority[0:32] # unused; overlapped with bankedIntPriority
|
||||||
|
del cpuTarget[0:32]
|
||||||
|
|
||||||
|
cpt.set(sec, 'intEnabled', ' '.join(intEnabled))
|
||||||
|
cpt.set(sec, 'pendingInt', ' '.join(pendingInt))
|
||||||
|
cpt.set(sec, 'activeInt', ' '.join(activeInt))
|
||||||
|
cpt.set(sec, 'intPriority',' '.join(intPriority))
|
||||||
|
cpt.set(sec, 'cpuTarget', ' '.join(cpuTarget))
|
||||||
|
|
||||||
|
b_intPriority = cpt.get(sec, '*bankedIntPriority').split()
|
||||||
|
cpt.remove_option(sec, '*bankedIntPriority')
|
||||||
|
|
||||||
|
for cpu in xrange(0, 255):
|
||||||
|
if cpuEnabled[cpu] == 'true':
|
||||||
|
intPriority = b_intPriority[cpu*32 : (cpu+1)*32]
|
||||||
|
new_sec = "%s.bankedRegs%u" % (sec, cpu)
|
||||||
|
cpt.add_section(new_sec)
|
||||||
|
cpt.set(new_sec, 'intEnabled', b_intEnabled)
|
||||||
|
cpt.set(new_sec, 'pendingInt', b_pendingInt)
|
||||||
|
cpt.set(new_sec, 'activeInt', b_activeInt)
|
||||||
|
cpt.set(new_sec, 'intPriority',' '.join(intPriority))
|
||||||
|
cpt.set(new_sec, 'cpuTarget', ' '.join(b_cpuTarget))
|
Loading…
Reference in a new issue