@@ -1033,8 +1033,9 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
n_IRQ = IRQ_get_next(opp, &dst->raised);
if (n_IRQ != -1) {
src = &opp->src[n_IRQ];
- if (s_IRQ == -1 ||
- IVPR_PRIORITY(src->ivpr) > dst->servicing.priority) {
+ if (IVPR_PRIORITY(src->ivpr) > dst->ctpr &&
+ (s_IRQ == -1 ||
+ IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
DPRINTF("Raise OpenPIC INT output cpu %d irq %d",
idx, n_IRQ);
qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
@@ -1070,12 +1071,13 @@ static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
}
src = &opp->src[irq];
- if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
- !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
+ if (!(src->ivpr & IVPR_ACTIVITY_MASK)) {
error_report("%s: bad raised IRQ %d ctpr %d ivpr 0x%08x",
__func__, irq, dst->ctpr, src->ivpr);
openpic_update_irq(opp, irq);
retval = opp->spve;
+ } else if (IVPR_PRIORITY(src->ivpr) <= dst->ctpr) {
+ return opp->spve;
} else {
/* IRQ enter servicing state */
IRQ_setbit(&dst->servicing, irq);
OpenBSD exposes this by raising CTPR while handling interrupts. If an edge remains pending when EOI lowers the servicing priority, QEMU reasserts INT without checking CTPR; IACK then returns the spurious vector and consumes the masked edge before CTPR permits delivery. Signed-off-by: Kirill A. Korinsky <kirill@korins.ky> --- hw/intc/openpic.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)