aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/arm/smpboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'xen/arch/arm/smpboot.c')
-rw-r--r--xen/arch/arm/smpboot.c57
1 files changed, 19 insertions, 38 deletions
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index 234748e92d..2cb0f36683 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -56,12 +56,10 @@ struct init_info __initdata init_data =
};
/* Shared state for coordinating CPU bringup */
-unsigned long smp_up_cpu = 0;
+unsigned long smp_up_cpu = MPIDR_INVALID;
+/* Shared state for coordinating CPU teardown */
static bool_t cpu_is_dead = 0;
-/* Number of non-boot CPUs ready to enter C */
-unsigned long __initdata ready_cpus = 0;
-
/* ID of the PCPU we're running on */
DEFINE_PER_CPU(unsigned int, cpu_id);
/* XXX these seem awfully x86ish... */
@@ -103,7 +101,6 @@ smp_get_max_cpus (void)
return max_cpus;
}
-
void __init
smp_prepare_cpus (unsigned int max_cpus)
{
@@ -112,32 +109,6 @@ smp_prepare_cpus (unsigned int max_cpus)
setup_cpu_sibling_map(0);
}
-void __init
-make_cpus_ready(unsigned int max_cpus, unsigned long boot_phys_offset)
-{
- unsigned long *gate;
- paddr_t gate_pa;
- int i;
-
- printk("Waiting for %i other CPUs to be ready\n", max_cpus - 1);
- /* We use the unrelocated copy of smp_up_cpu as that's the one the
- * others can see. */
- gate_pa = ((paddr_t) (unsigned long) &smp_up_cpu) + boot_phys_offset;
- gate = map_domain_page(gate_pa >> PAGE_SHIFT) + (gate_pa & ~PAGE_MASK);
- for ( i = 1; i < max_cpus; i++ )
- {
- /* Tell the next CPU to get ready */
- *gate = cpu_logical_map(i);
- flush_xen_dcache(*gate);
- isb();
- sev();
- /* And wait for it to respond */
- while ( ready_cpus < i )
- smp_rmb();
- }
- unmap_domain_page(gate);
-}
-
/* Boot the current CPU */
void __cpuinit start_secondary(unsigned long boot_phys_offset,
unsigned long fdt_paddr,
@@ -176,6 +147,7 @@ void __cpuinit start_secondary(unsigned long boot_phys_offset,
wmb();
/* Now report this CPU is up */
+ smp_up_cpu = MPIDR_INVALID;
cpumask_set_cpu(cpuid, &cpu_online_map);
wmb();
@@ -226,6 +198,8 @@ int __cpu_up(unsigned int cpu)
{
int rc;
+ printk("Bringing up CPU%d\n", cpu);
+
rc = init_secondary_pagetables(cpu);
if ( rc < 0 )
return rc;
@@ -236,14 +210,22 @@ int __cpu_up(unsigned int cpu)
/* Tell the remote CPU what is it's logical CPU ID */
init_data.cpuid = cpu;
- /* 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. */
+ /* Open the gate for this CPU */
smp_up_cpu = cpu_logical_map(cpu);
- /* we need to make sure that the change to smp_up_cpu is visible to
- * secondary cpus with D-cache off */
flush_xen_dcache(smp_up_cpu);
- isb();
- sev();
+
+ rc = arch_cpu_up(cpu);
+
+ if ( rc < 0 )
+ {
+ printk("Failed to bring up CPU%d\n", cpu);
+ return rc;
+ }
+
+ /* We don't know the GIC ID of the CPU until it has woken up, so just signal
+ * everyone and rely on our own smp_up_cpu gate to ensure only the one we
+ * want gets through. */
+ send_SGI_allbutself(GIC_SGI_EVENT_CHECK);
while ( !cpu_online(cpu) )
{
@@ -272,7 +254,6 @@ void __cpu_die(unsigned int cpu)
mb();
}
-
/*
* Local variables:
* mode: C