summaryrefslogtreecommitdiff
path: root/src/dev/arm/gic_pl390.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev/arm/gic_pl390.cc')
-rw-r--r--src/dev/arm/gic_pl390.cc250
1 files changed, 133 insertions, 117 deletions
diff --git a/src/dev/arm/gic_pl390.cc b/src/dev/arm/gic_pl390.cc
index 22788b375..b65014d23 100644
--- a/src/dev/arm/gic_pl390.cc
+++ b/src/dev/arm/gic_pl390.cc
@@ -129,46 +129,64 @@ Pl390::readDistributor(PacketPtr pkt)
DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
+ const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize());
+
+ switch (pkt->getSize()) {
+ case 1:
+ pkt->set<uint8_t>(resp);
+ break;
+ case 2:
+ pkt->set<uint16_t>(resp);
+ break;
+ case 4:
+ pkt->set<uint32_t>(resp);
+ break;
+ default:
+ panic("Invalid size while reading Distributor regs in GIC: %d\n",
+ pkt->getSize());
+ }
+
+ pkt->makeAtomicResponse();
+ return distPioDelay;
+}
+
+uint32_t
+Pl390::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz)
+{
if (GICD_ISENABLER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
assert(ix < 32);
- pkt->set<uint32_t>(getIntEnabled(ctx, ix));
- goto done;
+ return getIntEnabled(ctx, ix);
}
if (GICD_ICENABLER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
assert(ix < 32);
- pkt->set<uint32_t>(getIntEnabled(ctx, ix));
- goto done;
+ return getIntEnabled(ctx, ix);
}
if (GICD_ISPENDR.contains(daddr)) {
uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
assert(ix < 32);
- pkt->set<uint32_t>(getPendingInt(ctx, ix));
- goto done;
+ return getPendingInt(ctx, ix);
}
if (GICD_ICPENDR.contains(daddr)) {
uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
assert(ix < 32);
- pkt->set<uint32_t>(getPendingInt(ctx, ix));
- goto done;
+ return getPendingInt(ctx, ix);
}
if (GICD_ISACTIVER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
assert(ix < 32);
- pkt->set<uint32_t>(getActiveInt(ctx, ix));
- goto done;
+ return getActiveInt(ctx, ix);
}
if (GICD_ICACTIVER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
assert(ix < 32);
- pkt->set<uint32_t>(getActiveInt(ctx, ix));
- goto done;
+ return getActiveInt(ctx, ix);
}
if (GICD_IPRIORITYR.contains(daddr)) {
@@ -176,27 +194,21 @@ Pl390::readDistributor(PacketPtr pkt)
assert(int_num < INT_LINES_MAX);
DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
- switch (pkt->getSize()) {
+ switch (resp_sz) {
+ default: // will panic() after return to caller anyway
case 1:
- pkt->set<uint8_t>(getIntPriority(ctx, int_num));
- break;
+ return getIntPriority(ctx, int_num);
case 2:
assert((int_num + 1) < INT_LINES_MAX);
- pkt->set<uint16_t>(getIntPriority(ctx, int_num) |
- getIntPriority(ctx, int_num+1) << 8);
- break;
+ return (getIntPriority(ctx, int_num) |
+ getIntPriority(ctx, int_num+1) << 8);
case 4:
assert((int_num + 3) < INT_LINES_MAX);
- pkt->set<uint32_t>(getIntPriority(ctx, int_num) |
- getIntPriority(ctx, int_num+1) << 8 |
- getIntPriority(ctx, int_num+2) << 16 |
- getIntPriority(ctx, int_num+3) << 24);
- break;
- default:
- panic("Invalid size while reading priority regs in GIC: %d\n",
- pkt->getSize());
+ return (getIntPriority(ctx, int_num) |
+ getIntPriority(ctx, int_num+1) << 8 |
+ getIntPriority(ctx, int_num+2) << 16 |
+ getIntPriority(ctx, int_num+3) << 24);
}
- goto done;
}
if (GICD_ITARGETSR.contains(daddr)) {
@@ -207,15 +219,15 @@ Pl390::readDistributor(PacketPtr pkt)
// First 31 interrupts only target single processor (SGI)
if (int_num > 31) {
- if (pkt->getSize() == 1) {
- pkt->set<uint8_t>(cpuTarget[int_num]);
+ if (resp_sz == 1) {
+ return cpuTarget[int_num];
} else {
- assert(pkt->getSize() == 4);
+ assert(resp_sz == 4);
int_num = mbits(int_num, 31, 2);
- pkt->set<uint32_t>(cpuTarget[int_num] |
- cpuTarget[int_num+1] << 8 |
- cpuTarget[int_num+2] << 16 |
- cpuTarget[int_num+3] << 24) ;
+ return (cpuTarget[int_num] |
+ cpuTarget[int_num+1] << 8 |
+ cpuTarget[int_num+2] << 16 |
+ cpuTarget[int_num+3] << 24) ;
}
} else {
assert(ctx < sys->numRunningContexts());
@@ -229,9 +241,8 @@ Pl390::readDistributor(PacketPtr pkt)
// replicate the 8-bit mask 4 times in a 32-bit word
ctx_mask |= ctx_mask << 8;
ctx_mask |= ctx_mask << 16;
- pkt->set<uint32_t>(ctx_mask);
+ return ctx_mask;
}
- goto done;
}
if (GICD_ICFGR.contains(daddr)) {
@@ -239,30 +250,23 @@ Pl390::readDistributor(PacketPtr pkt)
assert(ix < 64);
/** @todo software generated interrupts and PPIs
* can't be configured in some ways */
- pkt->set<uint32_t>(intConfig[ix]);
- goto done;
+ return intConfig[ix];
}
switch(daddr) {
case GICD_CTLR:
- pkt->set<uint32_t>(enabled);
- break;
- case GICD_TYPER: {
+ return enabled;
+ case GICD_TYPER:
/* The 0x100 is a made-up flag to show that gem5 extensions
* are available,
* write 0x200 to this register to enable it. */
- uint32_t tmp = ((sys->numRunningContexts() - 1) << 5) |
- (itLines/INT_BITS_MAX -1) |
- (haveGem5Extensions ? 0x100 : 0x0);
- pkt->set<uint32_t>(tmp);
- } break;
+ return (((sys->numRunningContexts() - 1) << 5) |
+ (itLines/INT_BITS_MAX -1) |
+ (haveGem5Extensions ? 0x100 : 0x0));
default:
panic("Tried to read Gic distributor at offset %#x\n", daddr);
break;
}
-done:
- pkt->makeAtomicResponse();
- return distPioDelay;
}
Tick
@@ -277,19 +281,24 @@ Pl390::readCpu(PacketPtr pkt)
DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
ctx);
+ pkt->set<uint32_t>(readCpu(ctx, daddr));
+
+ pkt->makeAtomicResponse();
+ return cpuPioDelay;
+}
+
+uint32_t
+Pl390::readCpu(ContextID ctx, Addr daddr)
+{
switch(daddr) {
case GICC_IIDR:
- pkt->set<uint32_t>(0);
- break;
+ return 0;
case GICC_CTLR:
- pkt->set<uint32_t>(cpuEnabled[ctx]);
- break;
+ return cpuEnabled[ctx];
case GICC_PMR:
- pkt->set<uint32_t>(cpuPriority[ctx]);
- break;
+ return cpuPriority[ctx];
case GICC_BPR:
- pkt->set<uint32_t>(cpuBpr[ctx]);
- break;
+ return cpuBpr[ctx];
case GICC_IAR:
if (enabled && cpuEnabled[ctx]) {
int active_int = cpuHighestInt[ctx];
@@ -337,26 +346,22 @@ Pl390::readCpu(PacketPtr pkt)
ctx, iar.ack_id, iar.cpu_id, iar);
cpuHighestInt[ctx] = SPURIOUS_INT;
updateIntState(-1);
- pkt->set<uint32_t>(iar);
platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0);
+ return iar;
} else {
- pkt->set<uint32_t>(SPURIOUS_INT);
+ return SPURIOUS_INT;
}
break;
case GICC_RPR:
- pkt->set<uint32_t>(iccrpr[0]);
- break;
+ return iccrpr[0];
case GICC_HPPIR:
- pkt->set<uint32_t>(0);
panic("Need to implement HPIR");
break;
default:
panic("Tried to read Gic cpu at offset %#x\n", daddr);
break;
}
- pkt->makeAtomicResponse();
- return cpuPioDelay;
}
Tick
@@ -366,9 +371,10 @@ Pl390::writeDistributor(PacketPtr pkt)
assert(pkt->req->hasContextId());
const ContextID ctx = pkt->req->contextId();
+ const size_t data_sz = pkt->getSize();
uint32_t pkt_data M5_VAR_USED;
- switch (pkt->getSize())
+ switch (data_sz)
{
case 1:
pkt_data = pkt->get<uint8_t>();
@@ -381,97 +387,104 @@ Pl390::writeDistributor(PacketPtr pkt)
break;
default:
panic("Invalid size when writing to priority regs in Gic: %d\n",
- pkt->getSize());
+ data_sz);
}
DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
- daddr, pkt->getSize(), pkt_data);
+ daddr, data_sz, pkt_data);
+
+ writeDistributor(ctx, daddr, pkt_data, data_sz);
+ pkt->makeAtomicResponse();
+ return distPioDelay;
+}
+
+void
+Pl390::writeDistributor(ContextID ctx, Addr daddr, uint32_t data,
+ size_t data_sz)
+{
if (GICD_ISENABLER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
assert(ix < 32);
- getIntEnabled(ctx, ix) |= pkt->get<uint32_t>();
- goto done;
+ getIntEnabled(ctx, ix) |= data;
+ return;
}
if (GICD_ICENABLER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
assert(ix < 32);
- getIntEnabled(ctx, ix) &= ~pkt->get<uint32_t>();
- goto done;
+ getIntEnabled(ctx, ix) &= ~data;
+ return;
}
if (GICD_ISPENDR.contains(daddr)) {
uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
- auto mask = pkt->get<uint32_t>();
+ auto mask = data;
if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
getPendingInt(ctx, ix) |= mask;
updateIntState(ix);
- goto done;
+ return;
}
if (GICD_ICPENDR.contains(daddr)) {
uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
- auto mask = pkt->get<uint32_t>();
+ auto mask = data;
if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
getPendingInt(ctx, ix) &= ~mask;
updateIntState(ix);
- goto done;
+ return;
}
if (GICD_ISACTIVER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
- getActiveInt(ctx, ix) |= pkt->get<uint32_t>();
- goto done;
+ getActiveInt(ctx, ix) |= data;
+ return;
}
if (GICD_ICACTIVER.contains(daddr)) {
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
- getActiveInt(ctx, ix) &= ~pkt->get<uint32_t>();
- goto done;
+ getActiveInt(ctx, ix) &= ~data;
+ return;
}
if (GICD_IPRIORITYR.contains(daddr)) {
Addr int_num = daddr - GICD_IPRIORITYR.start();
- switch(pkt->getSize()) {
+ switch(data_sz) {
case 1:
- getIntPriority(ctx, int_num) = pkt->get<uint8_t>();
+ getIntPriority(ctx, int_num) = data;
break;
case 2: {
- auto tmp16 = pkt->get<uint16_t>();
- getIntPriority(ctx, int_num) = bits(tmp16, 7, 0);
- getIntPriority(ctx, int_num + 1) = bits(tmp16, 15, 8);
+ getIntPriority(ctx, int_num) = bits(data, 7, 0);
+ getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
break;
}
case 4: {
- auto tmp32 = pkt->get<uint32_t>();
- getIntPriority(ctx, int_num) = bits(tmp32, 7, 0);
- getIntPriority(ctx, int_num + 1) = bits(tmp32, 15, 8);
- getIntPriority(ctx, int_num + 2) = bits(tmp32, 23, 16);
- getIntPriority(ctx, int_num + 3) = bits(tmp32, 31, 24);
+ getIntPriority(ctx, int_num) = bits(data, 7, 0);
+ getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
+ getIntPriority(ctx, int_num + 2) = bits(data, 23, 16);
+ getIntPriority(ctx, int_num + 3) = bits(data, 31, 24);
break;
}
default:
panic("Invalid size when writing to priority regs in Gic: %d\n",
- pkt->getSize());
+ data_sz);
}
updateIntState(-1);
updateRunPri();
- goto done;
+ return;
}
if (GICD_ITARGETSR.contains(daddr)) {
Addr int_num = daddr - GICD_ITARGETSR.start();
// First 31 interrupts only target single processor
if (int_num >= SGI_MAX) {
- if (pkt->getSize() == 1) {
- uint8_t tmp = pkt->get<uint8_t>();
- cpuTarget[int_num] = tmp & 0xff;
+ if (data_sz == 1) {
+ cpuTarget[int_num] = data & 0xff;
} else {
- assert (pkt->getSize() == 4);
+ assert (data_sz == 4);
int_num = mbits(int_num, 31, 2);
- uint32_t tmp = pkt->get<uint32_t>();
+ uint32_t tmp = data;
cpuTarget[int_num] = bits(tmp, 7, 0);
cpuTarget[int_num+1] = bits(tmp, 15, 8);
cpuTarget[int_num+2] = bits(tmp, 23, 16);
@@ -479,43 +492,38 @@ Pl390::writeDistributor(PacketPtr pkt)
}
updateIntState(int_num >> 2);
}
- goto done;
+ return;
}
if (GICD_ICFGR.contains(daddr)) {
uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
assert(ix < INT_BITS_MAX*2);
- intConfig[ix] = pkt->get<uint32_t>();
- if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
+ intConfig[ix] = data;
+ if (data & NN_CONFIG_MASK)
warn("GIC N:N mode selected and not supported at this time\n");
- goto done;
+ return;
}
switch(daddr) {
case GICD_CTLR:
- enabled = pkt->get<uint32_t>();
+ enabled = data;
DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
break;
case GICD_TYPER:
/* 0x200 is a made-up flag to enable gem5 extension functionality.
* This reg is not normally written.
*/
- gem5ExtensionsEnabled = (
- (pkt->get<uint32_t>() & 0x200) && haveGem5Extensions);
+ gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions;
DPRINTF(GIC, "gem5 extensions %s\n",
gem5ExtensionsEnabled ? "enabled" : "disabled");
break;
case GICD_SGIR:
- softInt(ctx, pkt->get<uint32_t>());
+ softInt(ctx, data);
break;
default:
panic("Tried to write Gic distributor at offset %#x\n", daddr);
break;
}
-
-done:
- pkt->makeAtomicResponse();
- return distPioDelay;
}
Tick
@@ -525,23 +533,32 @@ Pl390::writeCpu(PacketPtr pkt)
assert(pkt->req->hasContextId());
const ContextID ctx = pkt->req->contextId();
- IAR iar;
+ const uint32_t data = pkt->get<uint32_t>();
DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
- ctx, daddr, pkt->get<uint32_t>());
+ ctx, daddr, data);
+ writeCpu(ctx, daddr, data);
+
+ pkt->makeAtomicResponse();
+ return cpuPioDelay;
+}
+
+void
+Pl390::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
+{
switch(daddr) {
case GICC_CTLR:
- cpuEnabled[ctx] = pkt->get<uint32_t>();
+ cpuEnabled[ctx] = data;
break;
case GICC_PMR:
- cpuPriority[ctx] = pkt->get<uint32_t>();
+ cpuPriority[ctx] = data;
break;
case GICC_BPR:
- cpuBpr[ctx] = pkt->get<uint32_t>();
+ cpuBpr[ctx] = data;
break;
- case GICC_EOIR:
- iar = pkt->get<uint32_t>();
+ case GICC_EOIR: {
+ const IAR iar = data;
if (iar.ack_id < SGI_MAX) {
// Clear out the bit that corresponds to the cleared int
uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id);
@@ -569,13 +586,12 @@ Pl390::writeCpu(PacketPtr pkt)
DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
ctx, iar.ack_id, iar.cpu_id);
break;
+ }
default:
panic("Tried to write Gic cpu at offset %#x\n", daddr);
break;
}
if (cpuEnabled[ctx]) updateIntState(-1);
- pkt->makeAtomicResponse();
- return cpuPioDelay;
}
Pl390::BankedRegs&