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

View file

@ -172,16 +172,11 @@ class Pl390 : public BaseGic
* interrupt priority for SGIs and PPIs */ * interrupt priority for SGIs and PPIs */
uint8_t intPriority[SGI_MAX + PPI_MAX]; 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 serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override; void unserialize(CheckpointIn &cp) override;
BankedRegs() : BankedRegs() :
intEnabled(0), pendingInt(0), activeInt(0), intEnabled(0), pendingInt(0), activeInt(0), intPriority {0}
intPriority {0}, cpuTarget {0}
{} {}
}; };
std::vector<BankedRegs*> bankedRegs; std::vector<BankedRegs*> bankedRegs;
@ -252,12 +247,23 @@ class Pl390 : public BaseGic
*/ */
uint8_t cpuTarget[GLOBAL_INT_LINES]; 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); assert(ix < INT_LINES_MAX);
if (ix < SGI_MAX + PPI_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 { } 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_intEnabled = intEnabled[0]
b_pendingInt = pendingInt[0] b_pendingInt = pendingInt[0]
b_activeInt = activeInt[0] b_activeInt = activeInt[0]
b_cpuTarget = cpuTarget[0:32]
del intEnabled[0] del intEnabled[0]
del pendingInt[0] del pendingInt[0]
@ -78,4 +77,3 @@ def upgrader(cpt):
cpt.set(new_sec, 'pendingInt', b_pendingInt) cpt.set(new_sec, 'pendingInt', b_pendingInt)
cpt.set(new_sec, 'activeInt', b_activeInt) cpt.set(new_sec, 'activeInt', b_activeInt)
cpt.set(new_sec, 'intPriority',' '.join(intPriority)) cpt.set(new_sec, 'intPriority',' '.join(intPriority))
cpt.set(new_sec, 'cpuTarget', ' '.join(b_cpuTarget))