[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 08 of 10] arm: Boot secondary CPUs into C
# HG changeset patch # User Tim Deegan <tim@xxxxxxx> # Date 1330018799 0 # Node ID d35b52e5fde829dfbaf3da73e0716d004faded2f # Parent fd78d23ba19de4129e21cdc7303848b105057227 arm: Boot secondary CPUs into C Signed-off-by: Tim Deegan <tim@xxxxxxx> diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/gic.c --- a/xen/arch/arm/gic.c Thu Feb 23 17:39:59 2012 +0000 +++ b/xen/arch/arm/gic.c Thu Feb 23 17:39:59 2012 +0000 @@ -241,7 +241,6 @@ static void __cpuinit gic_hyp_init(void) vtr = GICH[GICH_VTR]; nr_lrs = (vtr & GICH_VTR_NRLRGS) + 1; - printk("GICH: %d list registers available\n", nr_lrs); GICH[GICH_HCR] = GICH_HCR_EN; GICH[GICH_MISR] = GICH_MISR_EOI; @@ -274,6 +273,15 @@ int __init gic_init(void) return gic.cpus; } +/* Set up the per-CPU parts of the GIC for a secondary CPU */ +void __cpuinit gic_init_secondary_cpu(void) +{ + spin_lock(&gic.lock); + gic_cpu_init(); + gic_hyp_init(); + spin_unlock(&gic.lock); +} + void gic_route_irqs(void) { /* XXX should get these from DT */ diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/gic.h --- a/xen/arch/arm/gic.h Thu Feb 23 17:39:59 2012 +0000 +++ b/xen/arch/arm/gic.h Thu Feb 23 17:39:59 2012 +0000 @@ -140,6 +140,8 @@ extern int gic_route_irq_to_guest(struct extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq); /* Bring up the interrupt controller, and report # cpus attached */ extern int gic_init(void); +/* Bring up a secondary CPU's per-CPU GIC interface */ +extern void gic_init_secondary_cpu(void); /* setup the gic virtual interface for a guest */ extern void gicv_setup(struct domain *d); #endif diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/head.S --- a/xen/arch/arm/head.S Thu Feb 23 17:39:59 2012 +0000 +++ b/xen/arch/arm/head.S Thu Feb 23 17:39:59 2012 +0000 @@ -305,17 +305,23 @@ paging: * and brought up the memory allocator, non-boot CPUs can get their * own stacks and enter C. */ 1: wfe - b 1b + dsb + ldr r0, =smp_up_cpu + ldr r1, [r0] /* Which CPU is being booted? */ + teq r1, r12 /* Is it us? */ + bne 1b launch: - ldr sp, =init_stack /* Supply a stack */ + ldr r0, =init_stacks /* Find the boot-time stack */ + ldr sp, [r0, r12, lsl #2] /* (the one for this CPU) */ add sp, #STACK_SIZE /* (which grows down from the top). */ sub sp, #CPUINFO_sizeof /* Make room for CPU save record */ mov r0, r10 /* Marshal args: - phys_offset */ mov r1, r7 /* - machine type */ mov r2, r8 /* - ATAG address */ - mov r3, r12 /* - CPU ID */ - b start_xen /* and disappear into the land of C */ + movs r3, r12 /* - CPU ID */ + beq start_xen /* and disappear into the land of C */ + b start_secondary /* (to the appropriate entry point) */ /* Fail-stop * r0: string explaining why */ diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/setup.c --- a/xen/arch/arm/setup.c Thu Feb 23 17:39:59 2012 +0000 +++ b/xen/arch/arm/setup.c Thu Feb 23 17:39:59 2012 +0000 @@ -38,9 +38,6 @@ #include <asm/setup.h> #include "gic.h" -/* Xen stack for bringing up the first CPU. */ -unsigned char __initdata init_stack[STACK_SIZE] __attribute__((__aligned__(STACK_SIZE))); - extern const char __init_begin[], __init_end[], __bss_start[]; /* Spinlock for serializing CPU bringup */ @@ -179,6 +176,8 @@ void __init start_xen(unsigned long boot console_init_preirq(); #endif + percpu_init_areas(); + cpus = gic_init(); printk("Waiting for %i other CPUs to be ready\n", cpus - 1); diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/smpboot.c --- a/xen/arch/arm/smpboot.c Thu Feb 23 17:39:59 2012 +0000 +++ b/xen/arch/arm/smpboot.c Thu Feb 23 17:39:59 2012 +0000 @@ -16,10 +16,15 @@ * GNU General Public License for more details. */ +#include <xen/cpu.h> #include <xen/cpumask.h> +#include <xen/errno.h> +#include <xen/init.h> +#include <xen/mm.h> +#include <xen/sched.h> #include <xen/smp.h> -#include <xen/init.h> -#include <xen/errno.h> +#include <xen/softirq.h> +#include "gic.h" cpumask_t cpu_online_map; EXPORT_SYMBOL(cpu_online_map); @@ -28,6 +33,14 @@ EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); +/* Xen stack for bringing up the first CPU. */ +static unsigned char cpu0_stack[STACK_SIZE] + __attribute__((__aligned__(STACK_SIZE))); + +/* Remember where the boot-time stacks live */ +/* TODO: overhaul this, and get_processor_id(), for per-vcpu stacks */ +unsigned char *init_stacks[NR_CPUS] = { cpu0_stack, 0 }; + void __init smp_prepare_cpus (unsigned int max_cpus) { @@ -43,11 +56,43 @@ smp_prepare_cpus (unsigned int max_cpus) cpumask_copy(&cpu_present_map, &cpu_possible_map); } -/* Bring up a non-boot CPU */ -int __cpu_up(unsigned int cpu) +/* Shared state for coordinating CPU bringup */ +unsigned long smp_up_cpu = 0; + +/* Boot the current CPU */ +void __cpuinit start_secondary(unsigned long boot_phys_offset, + unsigned long arm_type, + unsigned long atag_paddr, + unsigned long cpuid) { - /* Not yet... */ - return -ENODEV; + memset(get_cpu_info(), 0, sizeof (struct cpu_info)); + + /* TODO: handle boards where CPUIDs are not contiguous */ + set_processor_id(cpuid); + + /* Setup Hyp vector base */ + WRITE_CP32((uint32_t) hyp_traps_vector, HVBAR); + + dprintk(XENLOG_DEBUG, "CPU %li awake.\n", cpuid); + + gic_init_secondary_cpu(); + + set_current(idle_vcpu[cpuid]); + this_cpu(curr_vcpu) = current; + + /* Run local notifiers */ + notify_cpu_starting(cpuid); + wmb(); + + /* Now report this CPU is up */ + cpumask_set_cpu(cpuid, &cpu_online_map); + wmb(); + + local_irq_enable(); + + dprintk(XENLOG_DEBUG, "CPU %li booted.\n", cpuid); + + startup_cpu_idle_loop(); } /* Shut down the current CPU */ @@ -57,6 +102,32 @@ void __cpu_disable(void) BUG(); } +/* Bring up a remote CPU */ +int __cpu_up(unsigned int cpu) +{ + unsigned char *stack; + + /* Remote CPU needs a stack to boot on. */ + stack = alloc_xenheap_pages(STACK_ORDER, 0); + if ( !stack ) + return -ENOMEM; + ASSERT(init_stacks[cpu] == NULL); + init_stacks[cpu] = stack; + + /* Unblock the CPU. It should be waiting in the loop in head.S + * for an event to arrive when smp_up_cpu matches its cpuid. */ + smp_up_cpu = cpu; + asm volatile("dsb; isb; sev"); + + while ( !cpu_online(cpu) ) + { + cpu_relax(); + process_pending_softirqs(); + } + + return 0; +} + /* Wait for a remote CPU to die */ void __cpu_die(unsigned int cpu) { _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |