Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/arm64/mp_machdep.c
Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <dev/ofw/ofw_cpu.h> | #include <dev/ofw/ofw_cpu.h> | ||||
#endif | #endif | ||||
#include <dev/psci/psci.h> | #include <dev/psci/psci.h> | ||||
#include "pic_if.h" | #include "pic_if.h" | ||||
#define MP_BOOTSTACK_SIZE (kstack_pages * PAGE_SIZE) | |||||
#define MP_QUIRK_CPULIST 0x01 /* The list of cpus may be wrong, */ | #define MP_QUIRK_CPULIST 0x01 /* The list of cpus may be wrong, */ | ||||
/* don't panic if one fails to start */ | /* don't panic if one fails to start */ | ||||
static uint32_t mp_quirks; | static uint32_t mp_quirks; | ||||
#ifdef FDT | #ifdef FDT | ||||
static struct { | static struct { | ||||
const char *compat; | const char *compat; | ||||
uint32_t quirks; | uint32_t quirks; | ||||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | smp_after_idle_runnable(void *arg __unused) | ||||
* the APs have entered the scheduler at least once, so the boot stacks | * the APs have entered the scheduler at least once, so the boot stacks | ||||
* are safe to free. | * are safe to free. | ||||
*/ | */ | ||||
smp_rendezvous(smp_no_rendezvous_barrier, NULL, | smp_rendezvous(smp_no_rendezvous_barrier, NULL, | ||||
smp_no_rendezvous_barrier, NULL); | smp_no_rendezvous_barrier, NULL); | ||||
for (cpu = 1; cpu < mp_ncpus; cpu++) { | for (cpu = 1; cpu < mp_ncpus; cpu++) { | ||||
if (bootstacks[cpu] != NULL) | if (bootstacks[cpu] != NULL) | ||||
kmem_free((vm_offset_t)bootstacks[cpu], PAGE_SIZE); | kmem_free((vm_offset_t)bootstacks[cpu], | ||||
MP_BOOTSTACK_SIZE); | |||||
} | } | ||||
} | } | ||||
SYSINIT(smp_after_idle_runnable, SI_SUB_SMP, SI_ORDER_ANY, | SYSINIT(smp_after_idle_runnable, SI_SUB_SMP, SI_ORDER_ANY, | ||||
smp_after_idle_runnable, NULL); | smp_after_idle_runnable, NULL); | ||||
/* | /* | ||||
* Send IPI thru interrupt controller. | * Send IPI thru interrupt controller. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | start_cpu(u_int cpuid, uint64_t target_cpu, int domain) | ||||
pcpu_init(pcpup, cpuid, sizeof(struct pcpu)); | pcpu_init(pcpup, cpuid, sizeof(struct pcpu)); | ||||
pcpup->pc_mpidr_low = target_cpu & CPU_AFF_MASK; | pcpup->pc_mpidr_low = target_cpu & CPU_AFF_MASK; | ||||
pcpup->pc_mpidr_high = (target_cpu & CPU_AFF_MASK) >> 32; | pcpup->pc_mpidr_high = (target_cpu & CPU_AFF_MASK) >> 32; | ||||
dpcpu[cpuid - 1] = (void *)(pcpup + 1); | dpcpu[cpuid - 1] = (void *)(pcpup + 1); | ||||
dpcpu_init(dpcpu[cpuid - 1], cpuid); | dpcpu_init(dpcpu[cpuid - 1], cpuid); | ||||
bootstacks[cpuid] = (void *)kmem_malloc_domainset( | bootstacks[cpuid] = (void *)kmem_malloc_domainset( | ||||
DOMAINSET_PREF(domain), PAGE_SIZE, M_WAITOK | M_ZERO); | DOMAINSET_PREF(domain), MP_BOOTSTACK_SIZE, M_WAITOK | M_ZERO); | ||||
naps = atomic_load_int(&aps_started); | naps = atomic_load_int(&aps_started); | ||||
bootstack = (char *)bootstacks[cpuid] + PAGE_SIZE; | bootstack = (char *)bootstacks[cpuid] + MP_BOOTSTACK_SIZE; | ||||
printf("Starting CPU %u (%lx)\n", cpuid, target_cpu); | printf("Starting CPU %u (%lx)\n", cpuid, target_cpu); | ||||
pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry); | pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry); | ||||
err = psci_cpu_on(target_cpu, pa, cpuid); | err = psci_cpu_on(target_cpu, pa, cpuid); | ||||
if (err != PSCI_RETVAL_SUCCESS) { | if (err != PSCI_RETVAL_SUCCESS) { | ||||
/* | /* | ||||
* Panic here if INVARIANTS are enabled and PSCI failed to | * Panic here if INVARIANTS are enabled and PSCI failed to | ||||
* start the requested CPU. psci_cpu_on() returns PSCI_MISSING | * start the requested CPU. psci_cpu_on() returns PSCI_MISSING | ||||
* to indicate we are unable to use it to start the given CPU. | * to indicate we are unable to use it to start the given CPU. | ||||
*/ | */ | ||||
KASSERT(err == PSCI_MISSING || | KASSERT(err == PSCI_MISSING || | ||||
(mp_quirks & MP_QUIRK_CPULIST) == MP_QUIRK_CPULIST, | (mp_quirks & MP_QUIRK_CPULIST) == MP_QUIRK_CPULIST, | ||||
("Failed to start CPU %u (%lx), error %d\n", | ("Failed to start CPU %u (%lx), error %d\n", | ||||
cpuid, target_cpu, err)); | cpuid, target_cpu, err)); | ||||
pcpu_destroy(pcpup); | pcpu_destroy(pcpup); | ||||
dpcpu[cpuid - 1] = NULL; | dpcpu[cpuid - 1] = NULL; | ||||
kmem_free((vm_offset_t)bootstacks[cpuid], PAGE_SIZE); | kmem_free((vm_offset_t)bootstacks[cpuid], MP_BOOTSTACK_SIZE); | ||||
kmem_free(pcpu_mem, size); | kmem_free(pcpu_mem, size); | ||||
bootstacks[cpuid] = NULL; | bootstacks[cpuid] = NULL; | ||||
mp_ncpus--; | mp_ncpus--; | ||||
return (false); | return (false); | ||||
} | } | ||||
/* Wait for the AP to switch to its boot stack. */ | /* Wait for the AP to switch to its boot stack. */ | ||||
while (atomic_load_int(&aps_started) < naps + 1) | while (atomic_load_int(&aps_started) < naps + 1) | ||||
▲ Show 20 Lines • Show All 402 Lines • Show Last 20 Lines |