Enable SMP and IPI support, including remote function invocation.
There are a number of subtle issues fixed in this patch. I believe it
is a candidate for merging.
I have tested this extensively on JS21 and model 884221X JS20 blades,
and to a degree on Maple. I would appreciate further testing on Maple
and model 884241X JS20 blades.
Signed-off-by: Amos Waterland <[EMAIL PROTECTED]>
---
changeset : 25c51961bd3f
machines: kpblade1 cso91 cso103
pass: 162
fail: 0
transient : 1
total : 163
reliability : 100%
---
arch/powerpc/external.c| 32 +
arch/powerpc/mpic.c|9 -
arch/powerpc/mpic_init.c | 48
arch/powerpc/setup.c | 49 +
arch/powerpc/smp.c | 135 +++--
include/asm-powerpc/mach-default/irq_vectors.h | 22
include/asm-powerpc/smp.h | 17 +++
7 files changed, 256 insertions(+), 56 deletions(-)
diff -r 3dfeb3e4a03f xen/arch/powerpc/external.c
--- a/xen/arch/powerpc/external.c Fri Oct 13 11:00:32 2006 -0400
+++ b/xen/arch/powerpc/external.c Thu Oct 26 16:49:44 2006 -0400
@@ -82,7 +82,16 @@ void do_external(struct cpu_user_regs *r
vec = xen_mpic_get_irq(regs);
-if (vec != -1) {
+if (vector_is_ipi(vec)) {
+ /* do_IRQ is fundamentally broken for reliable IPI delivery. */
+ irq_desc_t *desc = &irq_desc[vec];
+ regs->entry_vector = vec;
+ spin_lock(&desc->lock);
+ desc->handler->ack(vec);
+ desc->action->handler(vector_to_irq(vec), desc->action->dev_id, regs);
+ desc->handler->end(vec);
+ spin_unlock(&desc->lock);
+} else if (vec != -1) {
DBG("EE:0x%lx isrc: %d\n", regs->msr, vec);
regs->entry_vector = vec;
do_IRQ(regs);
@@ -253,3 +262,24 @@ int ioapic_guest_write(unsigned long phy
BUG_ON(val != val);
return 0;
}
+
+void send_IPI_mask(cpumask_t mask, int vector)
+{
+unsigned int cpus;
+int const bits = 8 * sizeof(cpus);
+
+switch(vector) {
+case CALL_FUNCTION_VECTOR:
+case EVENT_CHECK_VECTOR:
+ break;
+default:
+ BUG();
+ return;
+}
+
+BUG_ON(NR_CPUS > bits);
+BUG_ON(fls(mask.bits[0]) > bits);
+
+cpus = mask.bits[0];
+mpic_send_ipi(vector, cpus);
+}
diff -r 3dfeb3e4a03f xen/arch/powerpc/mpic.c
--- a/xen/arch/powerpc/mpic.c Fri Oct 13 11:00:32 2006 -0400
+++ b/xen/arch/powerpc/mpic.c Mon Oct 23 22:57:51 2006 -0400
@@ -27,10 +27,6 @@
#define alloc_bootmem(x) xmalloc_bytes(x)
-#define request_irq(irq, handler, f, devname, dev_id) \
-panic("IPI requested: %d: %p: %s: %p\n", irq, handler, devname, dev_id)
-
-typedef int irqreturn_t;
#define IRQ_NONE (0)
#define IRQ_HANDLED(1)
@@ -96,11 +92,6 @@ typedef int irqreturn_t;
#endif
#include
#include
-
-static inline void smp_message_recv(int msg, struct pt_regs *regs)
-{
-return;
-}
#ifdef DEBUG
#define DBG(fmt...) printk(fmt)
diff -r 3dfeb3e4a03f xen/arch/powerpc/mpic_init.c
--- a/xen/arch/powerpc/mpic_init.c Fri Oct 13 11:00:32 2006 -0400
+++ b/xen/arch/powerpc/mpic_init.c Thu Oct 26 16:48:19 2006 -0400
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include "mpic_init.h"
#include "oftree.h"
#include "of-devtree.h"
@@ -358,6 +359,42 @@ static struct hw_interrupt_type *share_m
#endif
+static unsigned int mpic_startup_ipi(unsigned int irq)
+{
+mpic->hc_ipi.enable(irq);
+return 0;
+}
+
+int request_irq(unsigned int irq,
+ irqreturn_t (*handler)(int, void *, struct cpu_user_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id)
+{
+int retval;
+struct irqaction *action;
+void (*func)(int, void *, struct cpu_user_regs *);
+
+action = xmalloc(struct irqaction);
+if (!action) {
+ BUG();
+ return -ENOMEM;
+}
+
+/* Xen's handler prototype is slightly different than Linux's. */
+func = (void (*)(int, void *, struct cpu_user_regs *))handler;
+
+action->handler = func;
+action->name = devname;
+action->dev_id = dev_id;
+
+retval = setup_irq(irq, action);
+if (retval) {
+ BUG();
+ xfree(action);
+}
+
+return retval;
+}
+
struct hw_interrupt_type *xen_mpic_init(struct hw_interrupt_type *xen_irq)
{
unsigned int isu_size;
@@ -397,6 +434,11 @@ struct hw_interrupt_type *xen_mpic_init(
hit = share_mpic(&mpic->hc_irq, xen_irq);
printk("%s: success\n", __func__);
+
+mpic->hc_ipi.ack = xen_irq->ack;
+mpic->hc_ipi.startup = mpic_startup_ipi;
+mpic_request_ipis();
+
return hit;
}
@@ -406,3 +448,9 @@ int xen_mpic_get_irq(struct cpu_user_reg
return mpic_get_one_irq(mpic, regs);
}
+
+int vector_is_ipi(int vector)
+{
+BUG_ON(!mpic);
+return (mpic->ipi_offset <= vector) && (vector < mpic->ipi_offset + 4);
+}