arm: refactor packet processing in Pl390 GIC
Change-Id: I696703418506522ba90df5c2c4ca45c95a6efbea Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/2441 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-by: Weiping Liao <weipingliao@google.com>
This commit is contained in:
parent
3384caf0fe
commit
bbdd34d628
2 changed files with 138 additions and 117 deletions
|
@ -129,46 +129,64 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
|
|
||||||
DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
|
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)) {
|
if (GICD_ISENABLER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
pkt->set<uint32_t>(getIntEnabled(ctx, ix));
|
return getIntEnabled(ctx, ix);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICENABLER.contains(daddr)) {
|
if (GICD_ICENABLER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
pkt->set<uint32_t>(getIntEnabled(ctx, ix));
|
return getIntEnabled(ctx, ix);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ISPENDR.contains(daddr)) {
|
if (GICD_ISPENDR.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
pkt->set<uint32_t>(getPendingInt(ctx, ix));
|
return getPendingInt(ctx, ix);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICPENDR.contains(daddr)) {
|
if (GICD_ICPENDR.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
pkt->set<uint32_t>(getPendingInt(ctx, ix));
|
return getPendingInt(ctx, ix);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ISACTIVER.contains(daddr)) {
|
if (GICD_ISACTIVER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
pkt->set<uint32_t>(getActiveInt(ctx, ix));
|
return getActiveInt(ctx, ix);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICACTIVER.contains(daddr)) {
|
if (GICD_ICACTIVER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
pkt->set<uint32_t>(getActiveInt(ctx, ix));
|
return getActiveInt(ctx, ix);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_IPRIORITYR.contains(daddr)) {
|
if (GICD_IPRIORITYR.contains(daddr)) {
|
||||||
|
@ -176,27 +194,21 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
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);
|
||||||
|
|
||||||
switch (pkt->getSize()) {
|
switch (resp_sz) {
|
||||||
|
default: // will panic() after return to caller anyway
|
||||||
case 1:
|
case 1:
|
||||||
pkt->set<uint8_t>(getIntPriority(ctx, int_num));
|
return getIntPriority(ctx, int_num);
|
||||||
break;
|
|
||||||
case 2:
|
case 2:
|
||||||
assert((int_num + 1) < INT_LINES_MAX);
|
assert((int_num + 1) < INT_LINES_MAX);
|
||||||
pkt->set<uint16_t>(getIntPriority(ctx, int_num) |
|
return (getIntPriority(ctx, int_num) |
|
||||||
getIntPriority(ctx, int_num+1) << 8);
|
getIntPriority(ctx, int_num+1) << 8);
|
||||||
break;
|
|
||||||
case 4:
|
case 4:
|
||||||
assert((int_num + 3) < INT_LINES_MAX);
|
assert((int_num + 3) < INT_LINES_MAX);
|
||||||
pkt->set<uint32_t>(getIntPriority(ctx, int_num) |
|
return (getIntPriority(ctx, int_num) |
|
||||||
getIntPriority(ctx, int_num+1) << 8 |
|
getIntPriority(ctx, int_num+1) << 8 |
|
||||||
getIntPriority(ctx, int_num+2) << 16 |
|
getIntPriority(ctx, int_num+2) << 16 |
|
||||||
getIntPriority(ctx, int_num+3) << 24);
|
getIntPriority(ctx, int_num+3) << 24);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
panic("Invalid size while reading priority regs in GIC: %d\n",
|
|
||||||
pkt->getSize());
|
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ITARGETSR.contains(daddr)) {
|
if (GICD_ITARGETSR.contains(daddr)) {
|
||||||
|
@ -207,15 +219,15 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
|
|
||||||
// First 31 interrupts only target single processor (SGI)
|
// First 31 interrupts only target single processor (SGI)
|
||||||
if (int_num > 31) {
|
if (int_num > 31) {
|
||||||
if (pkt->getSize() == 1) {
|
if (resp_sz == 1) {
|
||||||
pkt->set<uint8_t>(cpuTarget[int_num]);
|
return cpuTarget[int_num];
|
||||||
} else {
|
} else {
|
||||||
assert(pkt->getSize() == 4);
|
assert(resp_sz == 4);
|
||||||
int_num = mbits(int_num, 31, 2);
|
int_num = mbits(int_num, 31, 2);
|
||||||
pkt->set<uint32_t>(cpuTarget[int_num] |
|
return (cpuTarget[int_num] |
|
||||||
cpuTarget[int_num+1] << 8 |
|
cpuTarget[int_num+1] << 8 |
|
||||||
cpuTarget[int_num+2] << 16 |
|
cpuTarget[int_num+2] << 16 |
|
||||||
cpuTarget[int_num+3] << 24) ;
|
cpuTarget[int_num+3] << 24) ;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(ctx < sys->numRunningContexts());
|
assert(ctx < sys->numRunningContexts());
|
||||||
|
@ -229,9 +241,8 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
// replicate the 8-bit mask 4 times in a 32-bit word
|
// replicate the 8-bit mask 4 times in a 32-bit word
|
||||||
ctx_mask |= ctx_mask << 8;
|
ctx_mask |= ctx_mask << 8;
|
||||||
ctx_mask |= ctx_mask << 16;
|
ctx_mask |= ctx_mask << 16;
|
||||||
pkt->set<uint32_t>(ctx_mask);
|
return ctx_mask;
|
||||||
}
|
}
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICFGR.contains(daddr)) {
|
if (GICD_ICFGR.contains(daddr)) {
|
||||||
|
@ -239,30 +250,23 @@ Pl390::readDistributor(PacketPtr pkt)
|
||||||
assert(ix < 64);
|
assert(ix < 64);
|
||||||
/** @todo software generated interrupts and PPIs
|
/** @todo software generated interrupts and PPIs
|
||||||
* can't be configured in some ways */
|
* can't be configured in some ways */
|
||||||
pkt->set<uint32_t>(intConfig[ix]);
|
return intConfig[ix];
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(daddr) {
|
switch(daddr) {
|
||||||
case GICD_CTLR:
|
case GICD_CTLR:
|
||||||
pkt->set<uint32_t>(enabled);
|
return enabled;
|
||||||
break;
|
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) |
|
return (((sys->numRunningContexts() - 1) << 5) |
|
||||||
(itLines/INT_BITS_MAX -1) |
|
(itLines/INT_BITS_MAX -1) |
|
||||||
(haveGem5Extensions ? 0x100 : 0x0);
|
(haveGem5Extensions ? 0x100 : 0x0));
|
||||||
pkt->set<uint32_t>(tmp);
|
|
||||||
} break;
|
|
||||||
default:
|
default:
|
||||||
panic("Tried to read Gic distributor at offset %#x\n", daddr);
|
panic("Tried to read Gic distributor at offset %#x\n", daddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
done:
|
|
||||||
pkt->makeAtomicResponse();
|
|
||||||
return distPioDelay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tick
|
Tick
|
||||||
|
@ -277,19 +281,24 @@ Pl390::readCpu(PacketPtr pkt)
|
||||||
DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
|
DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
|
||||||
ctx);
|
ctx);
|
||||||
|
|
||||||
|
pkt->set<uint32_t>(readCpu(ctx, daddr));
|
||||||
|
|
||||||
|
pkt->makeAtomicResponse();
|
||||||
|
return cpuPioDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
Pl390::readCpu(ContextID ctx, Addr daddr)
|
||||||
|
{
|
||||||
switch(daddr) {
|
switch(daddr) {
|
||||||
case GICC_IIDR:
|
case GICC_IIDR:
|
||||||
pkt->set<uint32_t>(0);
|
return 0;
|
||||||
break;
|
|
||||||
case GICC_CTLR:
|
case GICC_CTLR:
|
||||||
pkt->set<uint32_t>(cpuEnabled[ctx]);
|
return cpuEnabled[ctx];
|
||||||
break;
|
|
||||||
case GICC_PMR:
|
case GICC_PMR:
|
||||||
pkt->set<uint32_t>(cpuPriority[ctx]);
|
return cpuPriority[ctx];
|
||||||
break;
|
|
||||||
case GICC_BPR:
|
case GICC_BPR:
|
||||||
pkt->set<uint32_t>(cpuBpr[ctx]);
|
return cpuBpr[ctx];
|
||||||
break;
|
|
||||||
case GICC_IAR:
|
case GICC_IAR:
|
||||||
if (enabled && cpuEnabled[ctx]) {
|
if (enabled && cpuEnabled[ctx]) {
|
||||||
int active_int = cpuHighestInt[ctx];
|
int active_int = cpuHighestInt[ctx];
|
||||||
|
@ -337,26 +346,22 @@ Pl390::readCpu(PacketPtr pkt)
|
||||||
ctx, iar.ack_id, iar.cpu_id, iar);
|
ctx, iar.ack_id, iar.cpu_id, iar);
|
||||||
cpuHighestInt[ctx] = SPURIOUS_INT;
|
cpuHighestInt[ctx] = SPURIOUS_INT;
|
||||||
updateIntState(-1);
|
updateIntState(-1);
|
||||||
pkt->set<uint32_t>(iar);
|
|
||||||
platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0);
|
platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0);
|
||||||
|
return iar;
|
||||||
} else {
|
} else {
|
||||||
pkt->set<uint32_t>(SPURIOUS_INT);
|
return SPURIOUS_INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case GICC_RPR:
|
case GICC_RPR:
|
||||||
pkt->set<uint32_t>(iccrpr[0]);
|
return iccrpr[0];
|
||||||
break;
|
|
||||||
case GICC_HPPIR:
|
case GICC_HPPIR:
|
||||||
pkt->set<uint32_t>(0);
|
|
||||||
panic("Need to implement HPIR");
|
panic("Need to implement HPIR");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Tried to read Gic cpu at offset %#x\n", daddr);
|
panic("Tried to read Gic cpu at offset %#x\n", daddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pkt->makeAtomicResponse();
|
|
||||||
return cpuPioDelay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tick
|
Tick
|
||||||
|
@ -366,9 +371,10 @@ Pl390::writeDistributor(PacketPtr pkt)
|
||||||
|
|
||||||
assert(pkt->req->hasContextId());
|
assert(pkt->req->hasContextId());
|
||||||
const ContextID ctx = pkt->req->contextId();
|
const ContextID ctx = pkt->req->contextId();
|
||||||
|
const size_t data_sz = pkt->getSize();
|
||||||
|
|
||||||
uint32_t pkt_data M5_VAR_USED;
|
uint32_t pkt_data M5_VAR_USED;
|
||||||
switch (pkt->getSize())
|
switch (data_sz)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
pkt_data = pkt->get<uint8_t>();
|
pkt_data = pkt->get<uint8_t>();
|
||||||
|
@ -381,97 +387,104 @@ Pl390::writeDistributor(PacketPtr pkt)
|
||||||
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());
|
data_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
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, 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)) {
|
if (GICD_ISENABLER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
getIntEnabled(ctx, ix) |= pkt->get<uint32_t>();
|
getIntEnabled(ctx, ix) |= data;
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICENABLER.contains(daddr)) {
|
if (GICD_ICENABLER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
|
||||||
assert(ix < 32);
|
assert(ix < 32);
|
||||||
getIntEnabled(ctx, ix) &= ~pkt->get<uint32_t>();
|
getIntEnabled(ctx, ix) &= ~data;
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ISPENDR.contains(daddr)) {
|
if (GICD_ISPENDR.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
|
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
|
if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
|
||||||
getPendingInt(ctx, ix) |= mask;
|
getPendingInt(ctx, ix) |= mask;
|
||||||
updateIntState(ix);
|
updateIntState(ix);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICPENDR.contains(daddr)) {
|
if (GICD_ICPENDR.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
|
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
|
if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
|
||||||
getPendingInt(ctx, ix) &= ~mask;
|
getPendingInt(ctx, ix) &= ~mask;
|
||||||
updateIntState(ix);
|
updateIntState(ix);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ISACTIVER.contains(daddr)) {
|
if (GICD_ISACTIVER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
|
||||||
getActiveInt(ctx, ix) |= pkt->get<uint32_t>();
|
getActiveInt(ctx, ix) |= data;
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICACTIVER.contains(daddr)) {
|
if (GICD_ICACTIVER.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
|
||||||
getActiveInt(ctx, ix) &= ~pkt->get<uint32_t>();
|
getActiveInt(ctx, ix) &= ~data;
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_IPRIORITYR.contains(daddr)) {
|
if (GICD_IPRIORITYR.contains(daddr)) {
|
||||||
Addr int_num = daddr - GICD_IPRIORITYR.start();
|
Addr int_num = daddr - GICD_IPRIORITYR.start();
|
||||||
switch(pkt->getSize()) {
|
switch(data_sz) {
|
||||||
case 1:
|
case 1:
|
||||||
getIntPriority(ctx, int_num) = pkt->get<uint8_t>();
|
getIntPriority(ctx, int_num) = data;
|
||||||
break;
|
break;
|
||||||
case 2: {
|
case 2: {
|
||||||
auto tmp16 = pkt->get<uint16_t>();
|
getIntPriority(ctx, int_num) = bits(data, 7, 0);
|
||||||
getIntPriority(ctx, int_num) = bits(tmp16, 7, 0);
|
getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
|
||||||
getIntPriority(ctx, int_num + 1) = bits(tmp16, 15, 8);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
auto tmp32 = pkt->get<uint32_t>();
|
getIntPriority(ctx, int_num) = bits(data, 7, 0);
|
||||||
getIntPriority(ctx, int_num) = bits(tmp32, 7, 0);
|
getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
|
||||||
getIntPriority(ctx, int_num + 1) = bits(tmp32, 15, 8);
|
getIntPriority(ctx, int_num + 2) = bits(data, 23, 16);
|
||||||
getIntPriority(ctx, int_num + 2) = bits(tmp32, 23, 16);
|
getIntPriority(ctx, int_num + 3) = bits(data, 31, 24);
|
||||||
getIntPriority(ctx, 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());
|
data_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateIntState(-1);
|
updateIntState(-1);
|
||||||
updateRunPri();
|
updateRunPri();
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ITARGETSR.contains(daddr)) {
|
if (GICD_ITARGETSR.contains(daddr)) {
|
||||||
Addr int_num = daddr - GICD_ITARGETSR.start();
|
Addr int_num = daddr - GICD_ITARGETSR.start();
|
||||||
// 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 (data_sz == 1) {
|
||||||
uint8_t tmp = pkt->get<uint8_t>();
|
cpuTarget[int_num] = data & 0xff;
|
||||||
cpuTarget[int_num] = tmp & 0xff;
|
|
||||||
} else {
|
} else {
|
||||||
assert (pkt->getSize() == 4);
|
assert (data_sz == 4);
|
||||||
int_num = mbits(int_num, 31, 2);
|
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] = bits(tmp, 7, 0);
|
||||||
cpuTarget[int_num+1] = bits(tmp, 15, 8);
|
cpuTarget[int_num+1] = bits(tmp, 15, 8);
|
||||||
cpuTarget[int_num+2] = bits(tmp, 23, 16);
|
cpuTarget[int_num+2] = bits(tmp, 23, 16);
|
||||||
|
@ -479,43 +492,38 @@ Pl390::writeDistributor(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
updateIntState(int_num >> 2);
|
updateIntState(int_num >> 2);
|
||||||
}
|
}
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GICD_ICFGR.contains(daddr)) {
|
if (GICD_ICFGR.contains(daddr)) {
|
||||||
uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
|
uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
|
||||||
assert(ix < INT_BITS_MAX*2);
|
assert(ix < INT_BITS_MAX*2);
|
||||||
intConfig[ix] = pkt->get<uint32_t>();
|
intConfig[ix] = data;
|
||||||
if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
|
if (data & 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(daddr) {
|
switch(daddr) {
|
||||||
case GICD_CTLR:
|
case GICD_CTLR:
|
||||||
enabled = pkt->get<uint32_t>();
|
enabled = data;
|
||||||
DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
|
DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
|
||||||
break;
|
break;
|
||||||
case GICD_TYPER:
|
case GICD_TYPER:
|
||||||
/* 0x200 is a made-up flag to enable gem5 extension functionality.
|
/* 0x200 is a made-up flag to enable gem5 extension functionality.
|
||||||
* This reg is not normally written.
|
* This reg is not normally written.
|
||||||
*/
|
*/
|
||||||
gem5ExtensionsEnabled = (
|
gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions;
|
||||||
(pkt->get<uint32_t>() & 0x200) && haveGem5Extensions);
|
|
||||||
DPRINTF(GIC, "gem5 extensions %s\n",
|
DPRINTF(GIC, "gem5 extensions %s\n",
|
||||||
gem5ExtensionsEnabled ? "enabled" : "disabled");
|
gem5ExtensionsEnabled ? "enabled" : "disabled");
|
||||||
break;
|
break;
|
||||||
case GICD_SGIR:
|
case GICD_SGIR:
|
||||||
softInt(ctx, pkt->get<uint32_t>());
|
softInt(ctx, data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Tried to write Gic distributor at offset %#x\n", daddr);
|
panic("Tried to write Gic distributor at offset %#x\n", daddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
pkt->makeAtomicResponse();
|
|
||||||
return distPioDelay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tick
|
Tick
|
||||||
|
@ -525,23 +533,32 @@ Pl390::writeCpu(PacketPtr pkt)
|
||||||
|
|
||||||
assert(pkt->req->hasContextId());
|
assert(pkt->req->hasContextId());
|
||||||
const ContextID ctx = pkt->req->contextId();
|
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",
|
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) {
|
switch(daddr) {
|
||||||
case GICC_CTLR:
|
case GICC_CTLR:
|
||||||
cpuEnabled[ctx] = pkt->get<uint32_t>();
|
cpuEnabled[ctx] = data;
|
||||||
break;
|
break;
|
||||||
case GICC_PMR:
|
case GICC_PMR:
|
||||||
cpuPriority[ctx] = pkt->get<uint32_t>();
|
cpuPriority[ctx] = data;
|
||||||
break;
|
break;
|
||||||
case GICC_BPR:
|
case GICC_BPR:
|
||||||
cpuBpr[ctx] = pkt->get<uint32_t>();
|
cpuBpr[ctx] = data;
|
||||||
break;
|
break;
|
||||||
case GICC_EOIR:
|
case GICC_EOIR: {
|
||||||
iar = pkt->get<uint32_t>();
|
const IAR iar = data;
|
||||||
if (iar.ack_id < SGI_MAX) {
|
if (iar.ack_id < SGI_MAX) {
|
||||||
// Clear out the bit that corresponds to the cleared int
|
// Clear out the bit that corresponds to the cleared int
|
||||||
uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id);
|
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",
|
DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
|
||||||
ctx, iar.ack_id, iar.cpu_id);
|
ctx, iar.ack_id, iar.cpu_id);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic("Tried to write Gic cpu at offset %#x\n", daddr);
|
panic("Tried to write Gic cpu at offset %#x\n", daddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cpuEnabled[ctx]) updateIntState(-1);
|
if (cpuEnabled[ctx]) updateIntState(-1);
|
||||||
pkt->makeAtomicResponse();
|
|
||||||
return cpuPioDelay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pl390::BankedRegs&
|
Pl390::BankedRegs&
|
||||||
|
|
|
@ -393,21 +393,26 @@ class Pl390 : public BaseGic
|
||||||
* @param pkt packet to respond to
|
* @param pkt packet to respond to
|
||||||
*/
|
*/
|
||||||
Tick readDistributor(PacketPtr pkt);
|
Tick readDistributor(PacketPtr pkt);
|
||||||
|
uint32_t readDistributor(ContextID ctx, Addr daddr, size_t resp_sz);
|
||||||
|
|
||||||
/** Handle a read to the cpu portion of the GIC
|
/** Handle a read to the cpu portion of the GIC
|
||||||
* @param pkt packet to respond to
|
* @param pkt packet to respond to
|
||||||
*/
|
*/
|
||||||
Tick readCpu(PacketPtr pkt);
|
Tick readCpu(PacketPtr pkt);
|
||||||
|
uint32_t readCpu(ContextID ctx, Addr daddr);
|
||||||
|
|
||||||
/** Handle a write to the distributor portion of the GIC
|
/** Handle a write to the distributor portion of the GIC
|
||||||
* @param pkt packet to respond to
|
* @param pkt packet to respond to
|
||||||
*/
|
*/
|
||||||
Tick writeDistributor(PacketPtr pkt);
|
Tick writeDistributor(PacketPtr pkt);
|
||||||
|
void writeDistributor(ContextID ctx, Addr daddr, uint32_t data,
|
||||||
|
size_t data_sz);
|
||||||
|
|
||||||
/** Handle a write to the cpu portion of the GIC
|
/** Handle a write to the cpu portion of the GIC
|
||||||
* @param pkt packet to respond to
|
* @param pkt packet to respond to
|
||||||
*/
|
*/
|
||||||
Tick writeCpu(PacketPtr pkt);
|
Tick writeCpu(PacketPtr pkt);
|
||||||
|
void writeCpu(ContextID ctx, Addr daddr, uint32_t data);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__DEV_ARM_GIC_H__
|
#endif //__DEV_ARM_GIC_H__
|
||||||
|
|
Loading…
Reference in a new issue