arm, dev: refactor GIC Pl390 GICD_ITARGETSRn handling

The aforementioned registers (Interrupt Processor Targets Registers) are
banked per-CPU, but are read-only.  This patch eliminates the per-CPU
storage of these values that are simply computed.

Change-Id: I52cafc2f58e87dd54239a71326c01f4923544689
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2442
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
This commit is contained in:
Curtis Dunham 2017-01-31 17:11:24 +00:00 committed by Andreas Sandberg
parent bbdd34d628
commit 2f14baaabc
3 changed files with 38 additions and 51 deletions

View file

@ -217,31 +217,15 @@ Pl390::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz)
int_num);
assert(int_num < INT_LINES_MAX);
// First 31 interrupts only target single processor (SGI)
if (int_num > 31) {
if (resp_sz == 1) {
return cpuTarget[int_num];
} else {
assert(resp_sz == 4);
int_num = mbits(int_num, 31, 2);
return (cpuTarget[int_num] |
cpuTarget[int_num+1] << 8 |
cpuTarget[int_num+2] << 16 |
cpuTarget[int_num+3] << 24) ;
}
if (resp_sz == 1) {
return getCpuTarget(ctx, int_num);
} else {
assert(ctx < sys->numRunningContexts());
uint32_t ctx_mask;
if (gem5ExtensionsEnabled) {
ctx_mask = ctx;
} else {
// convert the CPU id number into a bit mask
ctx_mask = power(2, ctx);
}
// replicate the 8-bit mask 4 times in a 32-bit word
ctx_mask |= ctx_mask << 8;
ctx_mask |= ctx_mask << 16;
return ctx_mask;
assert(resp_sz == 4);
int_num = mbits(int_num, 31, 2);
return (getCpuTarget(ctx, int_num) |
getCpuTarget(ctx, int_num+1) << 8 |
getCpuTarget(ctx, int_num+2) << 16 |
getCpuTarget(ctx, int_num+3) << 24) ;
}
}
@ -477,18 +461,18 @@ Pl390::writeDistributor(ContextID ctx, Addr daddr, uint32_t data,
if (GICD_ITARGETSR.contains(daddr)) {
Addr int_num = daddr - GICD_ITARGETSR.start();
// First 31 interrupts only target single processor
if (int_num >= SGI_MAX) {
// Interrupts 0-31 are read only
unsigned offset = SGI_MAX + PPI_MAX;
if (int_num >= offset) {
unsigned ix = int_num - offset; // index into cpuTarget array
if (data_sz == 1) {
cpuTarget[int_num] = data & 0xff;
cpuTarget[ix] = data & 0xff;
} else {
assert (data_sz == 4);
int_num = mbits(int_num, 31, 2);
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);
cpuTarget[int_num+3] = bits(tmp, 31, 24);
cpuTarget[ix] = bits(data, 7, 0);
cpuTarget[ix+1] = bits(data, 15, 8);
cpuTarget[ix+2] = bits(data, 23, 16);
cpuTarget[ix+3] = bits(data, 31, 24);
}
updateIntState(int_num >> 2);
}
@ -733,8 +717,8 @@ Pl390::updateIntState(int hint)
(getIntPriority(cpu, int_nm) < highest_pri))
if ((!mp_sys) ||
(gem5ExtensionsEnabled
? (cpuTarget[int_nm] == cpu)
: (cpuTarget[int_nm] & (1 << cpu)))) {
? (getCpuTarget(cpu, int_nm) == cpu)
: (getCpuTarget(cpu, int_nm) & (1 << cpu)))) {
highest_pri = getIntPriority(cpu, int_nm);
highest_int = int_nm;
}
@ -792,13 +776,14 @@ Pl390::updateRunPri()
void
Pl390::sendInt(uint32_t num)
{
uint8_t target = getCpuTarget(0, num);
DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n",
num, cpuTarget[num]);
if ((cpuTarget[num] & (cpuTarget[num] - 1)) && !gem5ExtensionsEnabled)
num, target);
if ((target & (target - 1)) && !gem5ExtensionsEnabled)
panic("Multiple targets for peripheral interrupts is not supported\n");
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);
getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num);
updateIntState(intNumToWord(num));
}
@ -896,7 +881,6 @@ Pl390::BankedRegs::serialize(CheckpointOut &cp) const
SERIALIZE_SCALAR(pendingInt);
SERIALIZE_SCALAR(activeInt);
SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
SERIALIZE_ARRAY(cpuTarget, SGI_MAX + PPI_MAX);
}
void
@ -955,7 +939,6 @@ Pl390::BankedRegs::unserialize(CheckpointIn &cp)
UNSERIALIZE_SCALAR(pendingInt);
UNSERIALIZE_SCALAR(activeInt);
UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
UNSERIALIZE_ARRAY(cpuTarget, SGI_MAX + PPI_MAX);
}
Pl390 *

View file

@ -172,16 +172,11 @@ class Pl390 : public BaseGic
* interrupt priority for SGIs and PPIs */
uint8_t intPriority[SGI_MAX + PPI_MAX];
/** GICD_ITARGETSR{0..7}
* 8b CPU target ID for each SGI and PPI */
uint8_t cpuTarget[SGI_MAX + PPI_MAX];
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
BankedRegs() :
intEnabled(0), pendingInt(0), activeInt(0),
intPriority {0}, cpuTarget {0}
intEnabled(0), pendingInt(0), activeInt(0), intPriority {0}
{}
};
std::vector<BankedRegs*> bankedRegs;
@ -252,12 +247,23 @@ class Pl390 : public BaseGic
*/
uint8_t cpuTarget[GLOBAL_INT_LINES];
uint8_t& getCpuTarget(ContextID ctx, uint32_t ix) {
uint8_t getCpuTarget(ContextID ctx, uint32_t ix) {
assert(ctx < sys->numRunningContexts());
assert(ix < INT_LINES_MAX);
if (ix < SGI_MAX + PPI_MAX) {
return getBankedRegs(ctx).cpuTarget[ix];
// "GICD_ITARGETSR0 to GICD_ITARGETSR7 are read-only, and each
// field returns a value that corresponds only to the processor
// reading the register."
uint32_t ctx_mask;
if (gem5ExtensionsEnabled) {
ctx_mask = ctx;
} else {
// convert the CPU id number into a bit mask
ctx_mask = power(2, ctx);
}
return ctx_mask;
} else {
return cpuTarget[ix - (SGI_MAX + PPI_MAX)];
return cpuTarget[ix - 32];
}
}

View file

@ -52,7 +52,6 @@ def upgrader(cpt):
b_intEnabled = intEnabled[0]
b_pendingInt = pendingInt[0]
b_activeInt = activeInt[0]
b_cpuTarget = cpuTarget[0:32]
del intEnabled[0]
del pendingInt[0]
@ -78,4 +77,3 @@ def upgrader(cpt):
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))