[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 6 of 9] arm: Boot secondary CPUs into C
# HG changeset patch # User Tim Deegan <tim@xxxxxxx> # Date 1331300346 0 # Node ID 1b26b83318b378a6e41916e230e27030ee4539e0 # Parent 469d9fc8e755b8bd0de386c8cd505229ecdf061f arm: Boot secondary CPUs into C Secondary CPUs come up directly onto the stack of the appropriate idle vcpu; the boot CPU starts on a statically allocated stack and switches over to the idle vcpu's one once the idle domain has been built. Signed-off-by: Tim Deegan <tim@xxxxxxx> diff -r 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/gic.c --- a/xen/arch/arm/gic.c Fri Mar 09 13:39:06 2012 +0000 +++ b/xen/arch/arm/gic.c Fri Mar 09 13:39:06 2012 +0000 @@ -245,7 +245,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; @@ -278,6 +277,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 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/gic.h --- a/xen/arch/arm/gic.h Fri Mar 09 13:39:06 2012 +0000 +++ b/xen/arch/arm/gic.h Fri Mar 09 13:39:06 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 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/head.S --- a/xen/arch/arm/head.S Fri Mar 09 13:39:06 2012 +0000 +++ b/xen/arch/arm/head.S Fri Mar 09 13:39:06 2012 +0000 @@ -307,17 +307,23 @@ 1: ldrex r1, [r0] /* * 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_stack /* Find the boot-time stack */ + ldr sp, [r0] 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 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/setup.c --- a/xen/arch/arm/setup.c Fri Mar 09 13:39:06 2012 +0000 +++ b/xen/arch/arm/setup.c Fri Mar 09 13:39:06 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); @@ -197,7 +196,6 @@ void __init start_xen(unsigned long boot __set_current((struct vcpu *)0xfffff000); /* debug sanity */ idle_vcpu[0] = current; - set_processor_id(0); /* needed early, for smp_processor_id() */ smp_prepare_cpus(cpus); @@ -284,7 +282,11 @@ void __init start_xen(unsigned long boot domain_unpause_by_systemcontroller(dom0); - reset_stack_and_jump(init_done); + /* Switch on to the dynamically allocated stack for the idle vcpu + * since the static one we're running on is about to be freed. */ + memcpy(idle_vcpu[0]->arch.cpu_info, get_cpu_info(), + sizeof(struct cpu_info)); + switch_stack_and_jump(idle_vcpu[0]->arch.cpu_info, init_done); } void arch_get_xen_caps(xen_capabilities_info_t *info) diff -r 469d9fc8e755 -r 1b26b83318b3 xen/arch/arm/smpboot.c --- a/xen/arch/arm/smpboot.c Fri Mar 09 13:39:06 2012 +0000 +++ b/xen/arch/arm/smpboot.c Fri Mar 09 13:39:06 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,13 @@ 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 __initdata cpu0_boot_stack[STACK_SIZE] + __attribute__((__aligned__(STACK_SIZE))); + +/* Pointer to the stack, used by head.S when entering C */ +unsigned char *init_stack = cpu0_boot_stack; + void __init smp_prepare_cpus (unsigned int max_cpus) { @@ -43,11 +55,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 +101,26 @@ void __cpu_disable(void) BUG(); } +/* Bring up a remote CPU */ +int __cpu_up(unsigned int cpu) +{ + /* Tell the remote CPU which stack to boot on. */ + init_stack = idle_vcpu[cpu]->arch.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) { diff -r 469d9fc8e755 -r 1b26b83318b3 xen/include/asm-arm/current.h --- a/xen/include/asm-arm/current.h Fri Mar 09 13:39:06 2012 +0000 +++ b/xen/include/asm-arm/current.h Fri Mar 09 13:39:06 2012 +0000 @@ -47,10 +47,10 @@ static inline struct cpu_info *get_cpu_i #define guest_cpu_user_regs() (&get_cpu_info()->guest_cpu_user_regs) -#define reset_stack_and_jump(__fn) \ - __asm__ __volatile__ ( \ - "mov sp,%0; b "STR(__fn) \ - : : "r" (guest_cpu_user_regs()) : "memory" ) +#define switch_stack_and_jump(stack, fn) \ + asm volatile ("mov sp,%0; b " STR(fn) : : "r" (stack) : "memory" ) + +#define reset_stack_and_jump(fn) switch_stack_and_jump(get_cpu_info(), fn) #endif _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |