[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/3] arm: gic: implement IPIs using SGI mechanism
On Wed, 17 Apr 2013, Ian Campbell wrote: > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> > --- > v2: Drop GROUP1 bit, it has no meaning unless you are in secure mode. > printk not panic in smp_call_function to avoid infinite loop. Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> > 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 bc2be74..d6741d0 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 12f2e7f..07c816b 100644 > --- a/xen/arch/arm/gic.c > +++ b/xen/arch/arm/gic.c > @@ -356,10 +356,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<<GICD_SGI_TARGET_SHIFT) > + | sgi; > +} > + > +void send_SGI_one(unsigned int cpu, enum gic_sgi sgi) > +{ > + ASSERT(cpu < 7); /* Targets bitmap only supports 8 CPUs */ > + send_SGI_mask(cpumask_of(cpu), sgi); > +} > + > +void send_SGI_self(enum gic_sgi sgi) > +{ > + ASSERT(sgi < 16); /* There are only 16 SGIs */ > + > + dsb(); > + > + GICD[GICD_SGIR] = GICD_SGI_TARGET_SELF > + | sgi; > +} > + > +void send_SGI_allbutself(enum gic_sgi sgi) > +{ > + ASSERT(sgi < 16); /* There are only 16 SGIs */ > + > + dsb(); > + > + GICD[GICD_SGIR] = GICD_SGI_TARGET_OTHERS > + | sgi; > +} > + > void smp_send_state_dump(unsigned int cpu) > { > - printk("WARNING: unable to send state dump request to CPU%d\n", cpu); > - /* XXX TODO -- send an SGI */ > + send_SGI_one(cpu, GIC_SGI_DUMP_STATE); > } > > /* Set up the per-CPU parts of the GIC for a secondary CPU */ > @@ -592,6 +634,28 @@ out: > return retval; > } > > +static void do_sgi(struct cpu_user_regs *regs, int othercpu, enum gic_sgi > sgi) > +{ > + /* Lower the priority */ > + GICC[GICC_EOIR] = sgi; > + > + switch (sgi) > + { > + case GIC_SGI_EVENT_CHECK: > + /* Nothing to do, will check for events on return path */ > + break; > + case GIC_SGI_DUMP_STATE: > + dump_execstate(regs); > + break; > + default: > + panic("Unhandled SGI %d on CPU%d\n", sgi, smp_processor_id()); > + break; > + } > + > + /* Deactivate */ > + GICC[GICC_DIR] = sgi; > +} > + > /* Accept an interrupt from the GIC and dispatch its handler */ > void gic_interrupt(struct cpu_user_regs *regs, int is_fiq) > { > @@ -602,14 +666,23 @@ void gic_interrupt(struct cpu_user_regs *regs, int > is_fiq) > do { > intack = GICC[GICC_IAR]; > irq = intack & GICC_IA_IRQ; > - local_irq_enable(); > > - if (likely(irq < 1021)) > + if ( likely(irq >= 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 12260f4..2a429bd 100644 > --- a/xen/arch/arm/smp.c > +++ b/xen/arch/arm/smp.c > @@ -3,10 +3,11 @@ > #include <asm/smp.h> > #include <asm/cpregs.h> > #include <asm/page.h> > +#include <asm/gic.h> > > 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 6bf50bb..24c0d5c 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<<GICD_SGI_TARGET_SHIFT) > +#define GICD_SGI_GROUP1 (1UL<<15) > + > #define GICC_CTLR (0x0000/4) > #define GICC_PMR (0x0004/4) > #define GICC_BPR (0x0008/4) > @@ -83,8 +90,9 @@ > #define GICC_CTL_ENABLE 0x1 > #define GICC_CTL_EOI (0x1 << 9) > > -#define GICC_IA_IRQ 0x03ff > -#define GICC_IA_CPU 0x1c00 > +#define GICC_IA_IRQ 0x03ff > +#define GICC_IA_CPU_MASK 0x1c00 > +#define GICC_IA_CPU_SHIFT 10 > > #define GICH_HCR_EN (1 << 0) > #define GICH_HCR_UIE (1 << 1) > @@ -157,6 +165,16 @@ extern int gicv_setup(struct domain *d); > extern void gic_save_state(struct vcpu *v); > extern void gic_restore_state(struct vcpu *v); > > +/* SGI (AKA IPIs) */ > +enum gic_sgi { > + GIC_SGI_EVENT_CHECK = 0, > + GIC_SGI_DUMP_STATE = 1, > +}; > +extern void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi); > +extern void send_SGI_one(unsigned int cpu, enum gic_sgi sgi); > +extern void send_SGI_self(enum gic_sgi sgi); > +extern void send_SGI_allbutself(enum gic_sgi sgi); > + > /* print useful debug info */ > extern void gic_dump_info(struct vcpu *v); > > -- > 1.7.2.5 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |