WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

Re: [XenPPC] [PATCH] SMP/IPI/MB combined

To: Amos Waterland <apw@xxxxxxxxxx>
Subject: Re: [XenPPC] [PATCH] SMP/IPI/MB combined
From: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
Date: Wed, 22 Nov 2006 14:56:38 -0500
Cc: xen-ppc-devel <xen-ppc-devel@xxxxxxxxxxxxxxxxxxx>
Delivery-date: Wed, 22 Nov 2006 11:56:44 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <20061122033020.GA20989@xxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-ppc-devel-request@lists.xensource.com?subject=help>
List-id: Xen PPC development <xen-ppc-devel.lists.xensource.com>
List-post: <mailto:xen-ppc-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=unsubscribe>
References: <20061122033020.GA20989@xxxxxxxxxxxxxxxxxxxxx>
Sender: xen-ppc-devel-bounces@xxxxxxxxxxxxxxxxxxx
thanks Amos.. pushed
And with that we are now officially an SMP hypervisor.

-JX
On Nov 21, 2006, at 10:30 PM, Amos Waterland wrote:

This patch rolls up and rebases the following patches for submission
against current tip of tree:

 * Memory barrier after SP store
 * IPI support
 * SMP support

The only changes from the previous submission other than trivial
fast-forward merges are to remove the ERAT flush, since it was comitted
seperately, and to make the status messages about waiting for remote
function completion ACKs only kick in after a full second has passed.

Note that this path REQUIRES that some form of the dom0 Linux patch
titled "Make Linux bail out of IPI vector reset" be applied.

Signed-off-by: Amos Waterland <apw@xxxxxxxxxx>

---

 arch/powerpc/external.c                        |   32 +++++
 arch/powerpc/mpic.c                            |    9 -
 arch/powerpc/mpic_init.c                       |   48 ++++++++
 arch/powerpc/setup.c                           |   50 +++++----
arch/powerpc/smp.c | 135 +++++++++++++ ++++++++++--
 include/asm-powerpc/mach-default/irq_vectors.h |   22 ----
 include/asm-powerpc/smp.h                      |   16 ++
 7 files changed, 256 insertions(+), 56 deletions(-)

diff -r 79015565d348 xen/arch/powerpc/external.c
--- a/xen/arch/powerpc/external.c       Tue Nov 21 15:25:02 2006 -0600
+++ b/xen/arch/powerpc/external.c       Tue Nov 21 20:41:27 2006 -0500
@@ -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 79015565d348 xen/arch/powerpc/mpic.c
--- a/xen/arch/powerpc/mpic.c   Tue Nov 21 15:25:02 2006 -0600
+++ b/xen/arch/powerpc/mpic.c   Tue Nov 21 20:41:27 2006 -0500
@@ -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 <asm/mpic.h>
 #include <asm/smp.h>
-
-static inline void smp_message_recv(int msg, struct pt_regs *regs)
-{
-    return;
-}

 #ifdef DEBUG
 #define DBG(fmt...) printk(fmt)
diff -r 79015565d348 xen/arch/powerpc/mpic_init.c
--- a/xen/arch/powerpc/mpic_init.c      Tue Nov 21 15:25:02 2006 -0600
+++ b/xen/arch/powerpc/mpic_init.c      Tue Nov 21 20:41:27 2006 -0500
@@ -22,6 +22,7 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <asm/mpic.h>
+#include <errno.h>
 #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);
+}
diff -r 79015565d348 xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c  Tue Nov 21 15:25:02 2006 -0600
+++ b/xen/arch/powerpc/setup.c  Tue Nov 21 20:41:54 2006 -0500
@@ -38,6 +38,7 @@
 #include <xen/numa.h>
 #include <acm/acm_hooks.h>
 #include <public/version.h>
+#include <asm/mpic.h>
 #include <asm/processor.h>
 #include <asm/desc.h>
 #include <asm/cache.h>
@@ -86,6 +87,8 @@ struct ns16550_defaults ns16550;

 extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];

+static struct domain *idle_domain;
+
 volatile struct processor_area * volatile global_cpu_table[NR_CPUS];

 int is_kernel_text(unsigned long addr)
@@ -157,8 +160,6 @@ static void percpu_free_unused_areas(voi

 static void __init start_of_day(void)
 {
-    struct domain *idle_domain;
-
     init_IRQ();

     scheduler_init();
@@ -173,23 +174,6 @@ static void __init start_of_day(void)
/* for some reason we need to set our own bit in the thread map */
     cpu_set(0, cpu_sibling_map[0]);

-    percpu_free_unused_areas();
-
-    {
-        /* FIXME: Xen assumes that an online CPU is a schedualable
- * CPU, but we just are not there yet. Remove this fragment when
-         * scheduling processors actually works. */
-        int cpuid;
-
-        printk("WARNING!: Taking all secondary CPUs offline\n");
-
-        for_each_online_cpu(cpuid) {
-            if (cpuid == 0)
-                continue;
-            cpu_clear(cpuid, cpu_online_map);
-        }
-    }
-
     initialize_keytable();
     /* Register another key that will allow for the the Harware Probe
      * to be contacted, this works with RiscWatch probes and should
@@ -199,7 +183,6 @@ static void __init start_of_day(void)
     timer_init();
     serial_init_postirq();
     do_initcalls();
-    schedulers_start();
 }

 void startup_cpu_idle_loop(void)
@@ -241,6 +224,7 @@ static void init_parea(int cpuid)
     pa->whoami = cpuid;
     pa->hard_id = cpu_hard_id[cpuid];
     pa->hyp_stack_base = (void *)((ulong)stack + STACK_SIZE);
+    mb();

     /* This store has the effect of invoking secondary_cpu_init.  */
     global_cpu_table[cpuid] = pa;
@@ -273,9 +257,22 @@ static int kick_secondary_cpus(int maxcp
 /* This is the first C code that secondary processors invoke.  */
 int secondary_cpu_init(int cpuid, unsigned long r4)
 {
+    struct vcpu *vcpu;
+
     cpu_initialize(cpuid);
     smp_generic_take_timebase();
+
+    /* If we are online, we must be able to ACK IPIs.  */
+    mpic_setup_this_cpu();
     cpu_set(cpuid, cpu_online_map);
+
+    vcpu = alloc_vcpu(idle_domain, cpuid, cpuid);
+    BUG_ON(vcpu == NULL);
+
+    set_current(idle_domain->vcpu[cpuid]);
+    idle_vcpu[cpuid] = current;
+    startup_cpu_idle_loop();
+
     while(1);
 }

@@ -353,6 +350,10 @@ static void __init __start_xen(multiboot
         debugger_trap_immediate();
 #endif

+    start_of_day();
+
+    mpic_setup_this_cpu();
+
     /* Deal with secondary processors.  */
     if (opt_nosmp || ofd_boot_cpu == -1) {
printk("nosmp: leaving secondary processors spinning forever\n");
@@ -361,7 +362,11 @@ static void __init __start_xen(multiboot
         kick_secondary_cpus(max_cpus);
     }

-    start_of_day();
+    /* Secondary processors must be online before we call this.  */
+    schedulers_start();
+
+ /* This cannot be called before secondary cpus are marked online. */
+    percpu_free_unused_areas();

     /* Create initial domain 0. */
     dom0 = domain_create(0, 0);
@@ -420,6 +425,9 @@ static void __init __start_xen(multiboot
     console_end_sync();

     domain_unpause_by_systemcontroller(dom0);
+#ifdef DEBUG_IPI
+    ipi_torture_test();
+#endif
     startup_cpu_idle_loop();
 }

diff -r 79015565d348 xen/arch/powerpc/smp.c
--- a/xen/arch/powerpc/smp.c    Tue Nov 21 15:25:02 2006 -0600
+++ b/xen/arch/powerpc/smp.c    Tue Nov 21 21:21:55 2006 -0500
@@ -22,6 +22,8 @@
 #include <xen/smp.h>
 #include <asm/flushtlb.h>
 #include <asm/debugger.h>
+#include <asm/mpic.h>
+#include <asm/mach-default/irq_vectors.h>

 int smp_num_siblings = 1;
 int smp_num_cpus = 1;
@@ -50,7 +52,7 @@ void smp_send_event_check_mask(cpumask_t
 {
     cpu_clear(smp_processor_id(), mask);
     if (!cpus_empty(mask))
-        unimplemented();
+        send_IPI_mask(mask, EVENT_CHECK_VECTOR);
 }


@@ -65,8 +67,20 @@ int smp_call_function(void (*func) (void

 void smp_send_stop(void)
 {
-    unimplemented();
-}
+    BUG();
+}
+
+struct call_data_struct {
+    void (*func) (void *info);
+    void *info;
+    int wait;
+    atomic_t started;
+    atomic_t finished;
+    cpumask_t selected;
+};
+
+static DEFINE_SPINLOCK(call_lock);
+static struct call_data_struct call_data;

 int on_selected_cpus(
     cpumask_t selected,
@@ -75,6 +89,115 @@ int on_selected_cpus(
     int retry,
     int wait)
 {
-    unimplemented();
-    return 0;
-}
+    int t, retval = 0, nr_cpus = cpus_weight(selected);
+
+    spin_lock(&call_lock);
+
+    call_data.func = func;
+    call_data.info = info;
+    call_data.wait = wait;
+    call_data.wait = 1;  /* Until we get RCU around call_data.  */
+    atomic_set(&call_data.started, 0);
+    atomic_set(&call_data.finished, 0);
+    mb();
+
+    send_IPI_mask(selected, CALL_FUNCTION_VECTOR);
+
+    /* We always wait for an initiation ACK from remote CPU.  */
+    for (t = 0; atomic_read(&call_data.started) != nr_cpus; t++) {
+       if (t && t % timebase_freq == 0) {
+           printk("IPI start stall: %d ACKS to %d SYNS\n",
+                  atomic_read(&call_data.started), nr_cpus);
+       }
+    }
+
+    /* If told to, we wait for a completion ACK from remote CPU.  */
+    if (wait) {
+       for (t = 0; atomic_read(&call_data.finished) != nr_cpus; t++) {
+           if (t > timebase_freq && t % timebase_freq == 0) {
+               printk("IPI finish stall: %d ACKS to %d SYNS\n",
+                      atomic_read(&call_data.finished), nr_cpus);
+           }
+       }
+    }
+
+    spin_unlock(&call_lock);
+
+    return retval;
+}
+
+void smp_call_function_interrupt(struct cpu_user_regs *regs)
+{
+
+    void (*func)(void *info) = call_data.func;
+    void *info = call_data.info;
+    int wait = call_data.wait;
+
+    atomic_inc(&call_data.started);
+    mb();
+    (*func)(info);
+    mb();
+
+    if (wait)
+       atomic_inc(&call_data.finished);
+
+    return;
+}
+
+void smp_event_check_interrupt(void)
+{
+    /* We are knocked out of NAP state at least.  */
+    return;
+}
+
+void smp_message_recv(int msg, struct cpu_user_regs *regs)
+{
+    switch(msg) {
+    case CALL_FUNCTION_VECTOR:
+       smp_call_function_interrupt(regs);
+       break;
+    case EVENT_CHECK_VECTOR:
+        smp_event_check_interrupt();
+       break;
+    default:
+       BUG();
+       break;
+    }
+}
+
+#ifdef DEBUG_IPI
+static void debug_ipi_ack(void *info)
+{
+    return;
+}
+
+void ipi_torture_test(void)
+{
+    int cpu;
+    unsigned long before, after, delta;
+    unsigned long min = ~0, max = 0, mean = 0, sum = 0, tick = 0;
+    cpumask_t mask;
+
+    cpus_clear(mask);
+
+    while (tick < 1000000) {
+       for_each_online_cpu(cpu) {
+           cpu_set(cpu, mask);
+           before = mftb();
+           on_selected_cpus(mask, debug_ipi_ack, NULL, 1, 1);
+           after = mftb();
+           cpus_clear(mask);
+
+           delta = after - before;
+           if (delta > max) max = delta;
+           if (delta < min) min = delta;
+           sum += delta;
+           tick++;
+       }
+    }
+
+    mean = sum / tick;
+
+ printk("IPI tb ticks: min = %ld max = %ld mean = %ld\n", min, max, mean);
+}
+#endif
diff -r 79015565d348 xen/include/asm-powerpc/mach-default/ irq_vectors.h --- a/xen/include/asm-powerpc/mach-default/irq_vectors.h Tue Nov 21 15:25:02 2006 -0600 +++ b/xen/include/asm-powerpc/mach-default/irq_vectors.h Tue Nov 21 20:41:27 2006 -0500
@@ -37,26 +37,10 @@
 #define FAST_TRAP -1 /* 0x80 */
 #define FIRST_SYSTEM_VECTOR    -1

+#define CALL_FUNCTION_VECTOR   0x0
+#define EVENT_CHECK_VECTOR     0x1
+
 #if 0
-
-/*
- * Vectors 0-16 in some cases are used for ISA interrupts.
- */
-
-/*
- * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
- *
- *  some of the following vectors are 'rare', they are merged
- *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
- *  TLB, reschedule and local APIC vectors are performance-critical.
- *
- *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
- */
-#define SPURIOUS_APIC_VECTOR   0xff
-#define ERROR_APIC_VECTOR      0xfe
-#define INVALIDATE_TLB_VECTOR  0xfd
-#define EVENT_CHECK_VECTOR     0xfc
-#define CALL_FUNCTION_VECTOR   0xfb

 #define THERMAL_APIC_VECTOR    0xf0
 /*
diff -r 79015565d348 xen/include/asm-powerpc/smp.h
--- a/xen/include/asm-powerpc/smp.h     Tue Nov 21 15:25:02 2006 -0600
+++ b/xen/include/asm-powerpc/smp.h     Tue Nov 21 20:42:08 2006 -0500
@@ -42,4 +42,20 @@ extern void __devinit smp_generic_take_t
 extern void __devinit smp_generic_take_timebase(void);
 extern void __devinit smp_generic_give_timebase(void);

+#define SA_INTERRUPT   0x20000000u
+typedef int irqreturn_t;
+extern int request_irq(unsigned int irq,
+    irqreturn_t (*handler)(int, void *, struct cpu_user_regs *),
+    unsigned long irqflags, const char * devname, void *dev_id);
+void smp_message_recv(int msg, struct cpu_user_regs *regs);
+void smp_call_function_interrupt(struct cpu_user_regs *regs);
+void smp_event_check_interrupt(void);
+void send_IPI_mask(cpumask_t mask, int vector);
+int vector_is_ipi(int vector);
+
+#undef DEBUG_IPI
+#ifdef DEBUG_IPI
+void ipi_torture_test(void);
 #endif
+
+#endif

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel


_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel

<Prev in Thread] Current Thread [Next in Thread>