aboutsummaryrefslogtreecommitdiff
path: root/sys/arm64/arm64/mp_machdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arm64/arm64/mp_machdep.c')
-rw-r--r--sys/arm64/arm64/mp_machdep.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index 9c6175445572..e9b015443477 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -106,7 +106,8 @@ static void ipi_stop(void *);
static u_int fdt_cpuid;
#endif
-void mpentry(unsigned long cpuid);
+void mpentry_psci(unsigned long cpuid);
+void mpentry_spintable(void);
void init_secondary(uint64_t);
/* Synchronize AP startup. */
@@ -114,6 +115,7 @@ static struct mtx ap_boot_mtx;
/* Used to initialize the PCPU ahead of calling init_secondary(). */
void *bootpcpu;
+uint64_t ap_cpuid;
/* Stacks for AP initialization, discarded once idle threads are started. */
void *bootstack;
@@ -420,18 +422,25 @@ enable_cpu_spin(uint64_t cpu, vm_paddr_t entry, vm_paddr_t release_paddr)
{
vm_paddr_t *release_addr;
- release_addr = pmap_mapdev(release_paddr, sizeof(*release_addr));
+ ap_cpuid = cpu & CPU_AFF_MASK;
+
+ release_addr = pmap_mapdev_attr(release_paddr, sizeof(*release_addr),
+ VM_MEMATTR_DEFAULT);
if (release_addr == NULL)
return (ENOMEM);
*release_addr = entry;
+ cpu_dcache_wbinv_range(release_addr, sizeof(*release_addr));
pmap_unmapdev(release_addr, sizeof(*release_addr));
__asm __volatile(
- "dsb sy \n"
"sev \n"
::: "memory");
+ /* Wait for the target CPU to start */
+ while (atomic_load_64(&ap_cpuid) != 0)
+ __asm __volatile("wfe");
+
return (0);
}
@@ -475,7 +484,6 @@ start_cpu(u_int cpuid, uint64_t target_cpu, int domain, vm_paddr_t release_addr)
bootstack = (char *)bootstacks[cpuid] + MP_BOOTSTACK_SIZE;
printf("Starting CPU %u (%lx)\n", cpuid, target_cpu);
- pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry);
/*
* A limited set of hardware we support can only do spintables and
@@ -483,10 +491,13 @@ start_cpu(u_int cpuid, uint64_t target_cpu, int domain, vm_paddr_t release_addr)
* PSCI branch here.
*/
MPASS(release_addr == 0 || !psci_present);
- if (release_addr != 0)
+ if (release_addr != 0) {
+ pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry_spintable);
err = enable_cpu_spin(target_cpu, pa, release_addr);
- else
+ } else {
+ pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry_psci);
err = enable_cpu_psci(target_cpu, pa, cpuid);
+ }
if (err != 0) {
pcpu_destroy(pcpup);