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.cc26
1 files changed, 21 insertions, 5 deletions
diff --git a/src/dev/arm/gic_pl390.cc b/src/dev/arm/gic_pl390.cc
index e7f3e32ef..c114604ab 100644
--- a/src/dev/arm/gic_pl390.cc
+++ b/src/dev/arm/gic_pl390.cc
@@ -83,7 +83,7 @@ Pl390::Pl390(const Params *p)
iccrpr[x] = 0xff;
cpuEnabled[x] = false;
cpuPriority[x] = 0xff;
- cpuBpr[x] = 0;
+ cpuBpr[x] = GICC_BPR_MINIMUM;
// Initialize cpu highest int
cpuHighestInt[x] = SPURIOUS_INT;
postIntEvent[x] = new PostIntEvent(*this, x);
@@ -538,9 +538,13 @@ Pl390::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
case GICC_PMR:
cpuPriority[ctx] = data;
break;
- case GICC_BPR:
- cpuBpr[ctx] = data;
+ case GICC_BPR: {
+ auto bpr = data & 0x7;
+ if (bpr < GICC_BPR_MINIMUM)
+ bpr = GICC_BPR_MINIMUM;
+ cpuBpr[ctx] = bpr;
break;
+ }
case GICC_EOIR: {
const IAR iar = data;
if (iar.ack_id < SGI_MAX) {
@@ -666,6 +670,17 @@ Pl390::genSwiMask(int cpu)
return ULL(0x0101010101010101) << cpu;
}
+uint8_t
+Pl390::getCpuPriority(unsigned cpu)
+{
+ // see Table 3-2 in IHI0048B.b (GICv2)
+ // mask some low-order priority bits per BPR value
+ // NB: the GIC prioritization scheme is upside down:
+ // lower values are higher priority; masking off bits
+ // actually creates a higher priority, not lower.
+ return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu]));
+}
+
void
Pl390::updateIntState(int hint)
{
@@ -676,7 +691,7 @@ Pl390::updateIntState(int hint)
/*@todo use hint to do less work. */
int highest_int = SPURIOUS_INT;
// Priorities below that set in GICC_PMR can be ignored
- uint8_t highest_pri = cpuPriority[cpu];
+ uint8_t highest_pri = getCpuPriority(cpu);
// Check SGIs
for (int swi = 0; swi < SGI_MAX; swi++) {
@@ -733,7 +748,8 @@ Pl390::updateIntState(int hint)
/* @todo make this work for more than one cpu, need to handle 1:N, N:N
* models */
- if (enabled && cpuEnabled[cpu] && (highest_pri < cpuPriority[cpu]) &&
+ if (enabled && cpuEnabled[cpu] &&
+ (highest_pri < getCpuPriority(cpu)) &&
!(getActiveInt(cpu, intNumToWord(highest_int))
& (1 << intNumToBit(highest_int)))) {