From 691835f2a10b41cce4664c5fe7046f49ad3e0535 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 17 Apr 2013 13:52:32 +0100 Subject: [PATCH] arm: gic: implement IPIs using SGI mechanism Signed-off-by: Ian Campbell Acked-by: Stefano Stabellini --- xen/arch/arm/arm32/mode_switch.S | 2 +- xen/arch/arm/gic.c | 85 +++++++++++++++++++++++++++++--- xen/arch/arm/smp.c | 14 ++---- xen/include/asm-arm/gic.h | 22 ++++++++- 4 files changed, 105 insertions(+), 18 deletions(-) diff --git a/xen/arch/arm/arm32/mode_switch.S b/xen/arch/arm/arm32/mode_switch.S index bc2be7472a..d6741d0bf4 100644 --- a/xen/arch/arm/arm32/mode_switch.S +++ b/xen/arch/arm/arm32/mode_switch.S @@ -43,7 +43,7 @@ kick_cpus: mov r2, #0x1 str r2, [r0, #(GICD_CTLR * 4)] /* enable distributor */ mov r2, #0xfe0000 - str r2, [r0, #(GICD_SGIR * 4)] /* send IPI to everybody */ + str r2, [r0, #(GICD_SGIR * 4)] /* send IPI to everybody, SGI0 = Event check */ dsb str r2, [r0, #(GICD_CTLR * 4)] /* disable distributor */ mov pc, lr diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 3124da3c7a..0d1ab5a1cc 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -358,10 +358,52 @@ void __init gic_init(void) spin_unlock(&gic.lock); } +void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi) +{ + unsigned long mask = cpumask_bits(cpumask)[0]; + + ASSERT(sgi < 16); /* There are only 16 SGIs */ + + mask &= cpumask_bits(&cpu_online_map)[0]; + + ASSERT(mask < 0x100); /* The target bitmap only supports 8 CPUs */ + + dsb(); + + GICD[GICD_SGIR] = GICD_SGI_TARGET_LIST + | (mask<= 16 && irq < 1021) ) + { + local_irq_enable(); do_IRQ(regs, irq, is_fiq); + local_irq_disable(); + } + else if (unlikely(irq < 16)) + { + unsigned int cpu = (intack & GICC_IA_CPU_MASK) >> GICC_IA_CPU_SHIFT; + do_sgi(regs, cpu, irq); + } else + { + local_irq_disable(); break; - - local_irq_disable(); + } } while (1); } diff --git a/xen/arch/arm/smp.c b/xen/arch/arm/smp.c index 12260f4fae..2a429bdb39 100644 --- a/xen/arch/arm/smp.c +++ b/xen/arch/arm/smp.c @@ -3,10 +3,11 @@ #include #include #include +#include void flush_tlb_mask(const cpumask_t *mask) { - /* XXX IPI other processors */ + /* No need to IPI other processors on ARM, the processor takes care of it. */ flush_xen_data_tlb(); } @@ -15,17 +16,12 @@ void smp_call_function( void *info, int wait) { - /* TODO: No SMP just now, does not include self so nothing to do. - cpumask_t allbutself = cpu_online_map; - cpu_clear(smp_processor_id(), allbutself); - on_selected_cpus(&allbutself, func, info, wait); - */ + printk("%s not implmented\n", __func__); } + void smp_send_event_check_mask(const cpumask_t *mask) { - /* TODO: No SMP just now, does not include self so nothing to do. - send_IPI_mask(mask, EVENT_CHECK_VECTOR); - */ + send_SGI_mask(mask, GIC_SGI_EVENT_CHECK); } /* diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index 6bf50bbd95..24c0d5cf7b 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -51,6 +51,13 @@ #define GICD_SPENDSGIRN (0xF2C/4) #define GICD_ICPIDR2 (0xFE8/4) +#define GICD_SGI_TARGET_LIST (0UL<<24) +#define GICD_SGI_TARGET_OTHERS (1UL<<24) +#define GICD_SGI_TARGET_SELF (2UL<<24) +#define GICD_SGI_TARGET_SHIFT (16) +#define GICD_SGI_TARGET_MASK (0xFFUL<