diff options
author | Sai Pavan Boddu <sai.pavan.boddu@xilinx.com> | 2020-02-24 15:09:22 +0530 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-02-28 16:14:57 +0000 |
commit | 11411489da890ae40c182be7fa745c647e8ce399 (patch) | |
tree | d5dfccb3bf091f06dede10850f31029440ab0104 /hw/intc | |
parent | 5df2cfbc8b61e0c5d050a69814f713d2ba045ec5 (diff) | |
download | qemu-11411489da890ae40c182be7fa745c647e8ce399.zip qemu-11411489da890ae40c182be7fa745c647e8ce399.tar.gz qemu-11411489da890ae40c182be7fa745c647e8ce399.tar.bz2 |
arm_gic: Mask the un-supported priority bits
The GICv2 allows the implementation to implement a variable number
of priority bits; unimplemented bits in the priority registers
are read as zeros, writes ignored. We were previously always
implementing a full 8 bits of priority, which is allowed but not
what the real hardware typically does (which is usually to have
4 or 5 bits of priority).
Add a new device property to allow the number of implemented
property bits to be specified.
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
Message-id: 1582537164-764-2-git-send-email-sai.pavan.boddu@xilinx.com
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: improved commit message]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/arm_gic.c | 33 | ||||
-rw-r--r-- | hw/intc/arm_gic_common.c | 1 |
2 files changed, 32 insertions, 2 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 1d7da7b..c60dc6b 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -641,6 +641,23 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs) return ret; } +static uint32_t gic_fullprio_mask(GICState *s, int cpu) +{ + /* + * Return a mask word which clears the unimplemented priority + * bits from a priority value for an interrupt. (Not to be + * confused with the group priority, whose mask depends on BPR.) + */ + int priBits; + + if (gic_is_vcpu(cpu)) { + priBits = GIC_VIRT_MAX_GROUP_PRIO_BITS; + } else { + priBits = s->n_prio_bits; + } + return ~0U << (8 - priBits); +} + void gic_dist_set_priority(GICState *s, int cpu, int irq, uint8_t val, MemTxAttrs attrs) { @@ -651,6 +668,8 @@ void gic_dist_set_priority(GICState *s, int cpu, int irq, uint8_t val, val = 0x80 | (val >> 1); /* Non-secure view */ } + val &= gic_fullprio_mask(s, cpu); + if (irq < GIC_INTERNAL) { s->priority1[irq][cpu] = val; } else { @@ -669,7 +688,7 @@ static uint32_t gic_dist_get_priority(GICState *s, int cpu, int irq, } prio = (prio << 1) & 0xff; /* Non-secure view */ } - return prio; + return prio & gic_fullprio_mask(s, cpu); } static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask, @@ -684,7 +703,7 @@ static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask, return; } } - s->priority_mask[cpu] = pmask; + s->priority_mask[cpu] = pmask & gic_fullprio_mask(s, cpu); } static uint32_t gic_get_priority_mask(GICState *s, int cpu, MemTxAttrs attrs) @@ -2055,6 +2074,16 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) return; } + if (s->n_prio_bits > GIC_MAX_PRIORITY_BITS || + (s->virt_extn ? s->n_prio_bits < GIC_VIRT_MAX_GROUP_PRIO_BITS : + s->n_prio_bits < GIC_MIN_PRIORITY_BITS)) { + error_setg(errp, "num-priority-bits cannot be greater than %d" + " or less than %d", GIC_MAX_PRIORITY_BITS, + s->virt_extn ? GIC_VIRT_MAX_GROUP_PRIO_BITS : + GIC_MIN_PRIORITY_BITS); + return; + } + /* This creates distributor, main CPU interface (s->cpuiomem[0]) and if * enabled, virtualization extensions related interfaces (main virtual * interface (s->vifaceiomem[0]) and virtual CPU interface). diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index e6c4fe7..7b44d56 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -357,6 +357,7 @@ static Property arm_gic_common_properties[] = { DEFINE_PROP_BOOL("has-security-extensions", GICState, security_extn, 0), /* True if the GIC should implement the virtualization extensions */ DEFINE_PROP_BOOL("has-virtualization-extensions", GICState, virt_extn, 0), + DEFINE_PROP_UINT32("num-priority-bits", GICState, n_prio_bits, 8), DEFINE_PROP_END_OF_LIST(), }; |