Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115635062
D42899.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D42899.diff
View Options
diff --git a/sys/arm64/arm64/genassym.c b/sys/arm64/arm64/genassym.c
--- a/sys/arm64/arm64/genassym.c
+++ b/sys/arm64/arm64/genassym.c
@@ -76,3 +76,4 @@
ASSYM(TF_SPSR, offsetof(struct trapframe, tf_spsr));
ASSYM(TF_ESR, offsetof(struct trapframe, tf_esr));
ASSYM(TF_X, offsetof(struct trapframe, tf_x));
+ASSYM(CPU_AFF_MASK, CPU_AFF_MASK);
diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S
--- a/sys/arm64/arm64/locore.S
+++ b/sys/arm64/arm64/locore.S
@@ -191,6 +191,33 @@
END(_start)
#ifdef SMP
+/*
+ * mpentry_spin(void)
+ *
+ * Called by a core when it's brought online via spin-table method. Since
+ * u-boot fills `x0` with the entry pointer (here), we ignore it, and check
+ * validity from `ap_cpuid` set by the BSP. Each core will loop and check for
+ * its cpuid, matching against a masked `mpidr_el1` value. It's assumed that
+ * `ap_cpuid` is filled with a value that matches the masked `mpidr_el1`
+ * (CPU_AFF_MASK), provided by the device tree.
+ *
+ * `x0` ends as the cpu number (contents of `ap_cpuid`), which mpentry()
+ * expects.
+ */
+ENTRY(mpentry_spin)
+ mrs x1, mpidr_el1
+ ldr x2, =CPU_AFF_MASK
+ and x1, x1, x2
+ adrp x2, ap_cpuid
+ add x2, x2, :lo12:ap_cpuid
+1:
+ dc cvac, x2
+ ldr x0, [x2]
+ cmp x0, x1
+ mov x0, #0
+ beq mpentry
+ b 1b
+END(mpentry_spin)
/*
* mpentry(unsigned long)
*
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -107,6 +107,7 @@
#endif
void mpentry(unsigned long cpuid);
+void mpentry_spin(unsigned long cpuid);
void init_secondary(uint64_t);
/* Synchronize AP startup. */
@@ -115,6 +116,8 @@
/* 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;
static void *bootstacks[MAXCPU];
@@ -419,13 +422,21 @@
enable_cpu_spin(uint64_t cpu, vm_paddr_t entry, vm_paddr_t release_paddr)
{
vm_paddr_t *release_addr;
+ vm_offset_t release_vaddr;
- release_addr = pmap_mapdev(release_paddr, sizeof(*release_addr));
- if (release_addr == NULL)
+ cpu_dcache_wb_range(&bootpcpu, sizeof(bootpcpu));
+ ap_cpuid = cpu & CPU_AFF_MASK;
+ cpu_dcache_wb_range(&ap_cpuid, sizeof(ap_cpuid));
+ release_vaddr = kva_alloc(PAGE_SIZE);
+ if (release_vaddr == 0)
return (ENOMEM);
+ pmap_kenter(release_vaddr, PAGE_SIZE, trunc_page(release_paddr),
+ VM_MEMATTR_DEFAULT);
+ release_addr = (vm_paddr_t *)(release_vaddr + (release_paddr & PAGE_MASK));
*release_addr = entry;
- pmap_unmapdev(release_addr, sizeof(*release_addr));
+ pmap_kremove(release_vaddr);
+ kva_free(release_vaddr, PAGE_SIZE);
__asm __volatile(
"dsb sy \n"
@@ -475,7 +486,10 @@
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);
+ if (release_addr != 0)
+ pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry_spin);
+ else
+ pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry);
/*
* A limited set of hardware we support can only do spintables and
@@ -595,9 +609,9 @@
static bool
start_cpu_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
{
+ char table_prop[sizeof("spin-table")];
uint64_t target_cpu;
vm_paddr_t release_addr;
- char *enable_method;
int domain;
int cpuid;
@@ -619,16 +633,14 @@
*/
release_addr = 0;
if (!psci_present && cpuid != 0) {
- if (OF_getprop_alloc(node, "enable-method",
- (void **)&enable_method) <= 0)
+ if (OF_getprop(node, "enable-method",
+ (void *)table_prop, sizeof(table_prop)) <= 0)
return (false);
- if (strcmp(enable_method, "spin-table") != 0) {
- OF_prop_free(enable_method);
+ if (strcmp(table_prop, "spin-table") != 0) {
return (false);
}
- OF_prop_free(enable_method);
populate_release_addr(node, &release_addr);
if (release_addr == 0) {
printf("Failed to fetch release address for CPU %u",
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 27, 8:16 AM (12 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17815267
Default Alt Text
D42899.diff (3 KB)
Attached To
Mode
D42899: arm64: Make SMP `spin-table` boot method work for more than Apple Silicon
Attached
Detach File
Event Timeline
Log In to Comment