Index: sys/arm64/arm64/mp_machdep.c =================================================================== --- sys/arm64/arm64/mp_machdep.c +++ sys/arm64/arm64/mp_machdep.c @@ -146,6 +146,9 @@ /* Set to 1 once we're ready to let the APs out of the pen. */ static volatile int aps_ready; +static vm_offset_t pcpu_mem[MAXMEMDOM]; +static vm_offset_t pcpu_off[MAXMEMDOM]; + /* Temporary variables for init_secondary() */ void *dpcpu[MAXCPU - 1]; @@ -484,6 +487,28 @@ return (1); } +static vm_offset_t +alloc_pcpu(int domain, vm_size_t size) +{ + vm_offset_t addr; + + domain = domain % MAXMEMDOM; + + if (pcpu_mem[domain] == 0 || + (pcpu_off[domain] + size) >= (pcpu_mem[domain] + L2_SIZE)) { + pcpu_mem[domain] = kmem_alloc_contig_domainset( + DOMAINSET_PREF(domain), L2_SIZE, M_WAITOK | M_ZERO, + 0, ~(vm_paddr_t)0, L2_SIZE, 0, VM_MEMATTR_DEFAULT); + pcpu_off[domain] = pcpu_mem[domain]; + } + + addr = pcpu_off[domain]; + /* Align the next allocation */ + pcpu_off[domain] = roundup2(addr + size, _Alignof(void *)); + + return (addr); +} + /* * Starts a given CPU. If the CPU is already running, i.e. it is the boot CPU, * do nothing. Returns true if the CPU is present and running. @@ -505,13 +530,11 @@ KASSERT(cpuid < MAXCPU, ("Too many CPUs")); - pcpup = (void *)kmem_malloc_domainset(DOMAINSET_PREF(domain), - sizeof(*pcpup), M_WAITOK | M_ZERO); + pcpup = (void *)alloc_pcpu(domain, sizeof(*pcpup)); pcpu_init(pcpup, cpuid, sizeof(struct pcpu)); pcpup->pc_mpidr = target_cpu & CPU_AFF_MASK; - dpcpu[cpuid - 1] = (void *)kmem_malloc_domainset( - DOMAINSET_PREF(domain), DPCPU_SIZE, M_WAITOK | M_ZERO); + dpcpu[cpuid - 1] = (void *)alloc_pcpu(domain, DPCPU_SIZE); dpcpu_init(dpcpu[cpuid - 1], cpuid); bootstacks[cpuid] = (void *)kmem_malloc_domainset( @@ -535,9 +558,7 @@ cpuid, target_cpu, err)); pcpu_destroy(pcpup); - kmem_free((vm_offset_t)dpcpu[cpuid - 1], DPCPU_SIZE); dpcpu[cpuid - 1] = NULL; - kmem_free((vm_offset_t)bootstacks[cpuid], PAGE_SIZE); bootstacks[cpuid] = NULL; mp_ncpus--; return (false);