aboutsummaryrefslogtreecommitdiff
path: root/hw/openpic.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2011-07-21 01:36:44 +0200
committerAlexander Graf <agraf@suse.de>2011-10-06 09:43:33 +0200
commita675155e2d78b083b47774c118990041333308b5 (patch)
treea8b73f3919299c7ec60908e8cb751cbe347111b9 /hw/openpic.c
parentbc59d9c9163abbe3646a70bca5ff59e73e07904a (diff)
downloadqemu-a675155e2d78b083b47774c118990041333308b5.zip
qemu-a675155e2d78b083b47774c118990041333308b5.tar.gz
qemu-a675155e2d78b083b47774c118990041333308b5.tar.bz2
PPC: Fix IPI support in MPIC
The current IPI support in the MPIC code is incomplete and doesn't work. This code adds proper support for IPIs in MPIC by using the IDE register to remember which CPUs IPIs are still outstanding to. New triggers through the IPI trigger register only add to the list of CPUs we want to IPI. Signed-off-by: Alexander Graf <agraf@suse.de> --- v1 -> v2: - Use MAX_IPI instead of hardcoded 4 Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/openpic.c')
-rw-r--r--hw/openpic.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/hw/openpic.c b/hw/openpic.c
index f7d5583..9710ac0 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -57,7 +57,7 @@
#define MAX_MBX 4
#define MAX_TMR 4
#define VECTOR_BITS 8
-#define MAX_IPI 0
+#define MAX_IPI 4
#define VID (0x00000000)
@@ -840,7 +840,9 @@ static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
case 0x60:
case 0x70:
idx = (addr - 0x40) >> 4;
- write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
+ /* we use IDE as mask which CPUs to deliver the IPI to still. */
+ write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE,
+ opp->src[opp->irq_ipi0 + idx].ide | val);
openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
break;
@@ -934,6 +936,17 @@ static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
reset_bit(&src->ipvp, IPVP_ACTIVITY);
src->pending = 0;
}
+
+ if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
+ src->ide &= ~(1 << idx);
+ if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
+ /* trigger on CPUs that didn't know about it yet */
+ openpic_set_irq(opp, n_IRQ, 1);
+ openpic_set_irq(opp, n_IRQ, 0);
+ /* if all CPUs knew about it, set active bit again */
+ set_bit(&src->ipvp, IPVP_ACTIVITY);
+ }
+ }
}
break;
case 0xB0: /* PEOI */