git: b9c0003f0fa3 - main - arm64: Initialize x18 for APs earlier during boot

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 13 Nov 2023 15:51:17 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=b9c0003f0fa39ead4bb3953b9118ae6f08e560f8

commit b9c0003f0fa39ead4bb3953b9118ae6f08e560f8
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-11-13 15:44:45 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-11-13 15:44:45 +0000

    arm64: Initialize x18 for APs earlier during boot
    
    When KMSAN is configured, the instrumentation inserts calls to
    __msan_get_context_state() into all function prologues.  The
    implementation dereferences curthread and thus assumes that x18 points
    to the PCPU area.  This applies in particular to init_secondary(), which
    currently is responsible for initializing x18 for APs.
    
    Move initialization into locore to avoid this problem.  No functional
    change intended.
    
    Reviewed by:    kib, andrew
    MFC after:      2 weeks
    Sponsored by:   Juniper Networks, Inc.
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D42533
---
 sys/arm64/arm64/locore.S     |  8 ++++++++
 sys/arm64/arm64/mp_machdep.c | 14 +++++---------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S
index d55a21e9c55e..d77963d42461 100644
--- a/sys/arm64/arm64/locore.S
+++ b/sys/arm64/arm64/locore.S
@@ -247,6 +247,14 @@ mp_virtdone:
 	dsb	sy
 	isb
 
+	/*
+	 * Initialize the per-CPU pointer before calling into C code, for the
+	 * benefit of kernel sanitizers.
+	 */
+	adrp	x18, bootpcpu
+	ldr	x18, [x18, :lo12:bootpcpu]
+	msr	tpidr_el1, x18
+
 	b	init_secondary
 END(mpentry)
 #endif
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index 1c9bea2349de..5d598b4189a9 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -134,6 +134,9 @@ void init_secondary(uint64_t);
 /* Synchronize AP startup. */
 static struct mtx ap_boot_mtx;
 
+/* Used to initialize the PCPU ahead of calling init_secondary(). */
+void *bootpcpu;
+
 /* Stacks for AP initialization, discarded once idle threads are started. */
 void *bootstack;
 static void *bootstacks[MAXCPU];
@@ -225,15 +228,6 @@ init_secondary(uint64_t cpu)
 			panic("MPIDR for this CPU is not in pcpu table");
 	}
 
-	pcpup = cpuid_to_pcpu[cpu];
-	/*
-	 * Set the pcpu pointer with a backup in tpidr_el1 to be
-	 * loaded when entering the kernel from userland.
-	 */
-	__asm __volatile(
-	    "mov x18, %0 \n"
-	    "msr tpidr_el1, %0" :: "r"(pcpup));
-
 	/*
 	 * Identify current CPU. This is necessary to setup
 	 * affinity registers and to provide support for
@@ -242,6 +236,7 @@ init_secondary(uint64_t cpu)
 	 * We need this before signalling the CPU is ready to
 	 * let the boot CPU use the results.
 	 */
+	pcpup = cpuid_to_pcpu[cpu];
 	pcpup->pc_midr = get_midr();
 	identify_cpu(cpu);
 
@@ -555,6 +550,7 @@ start_cpu(u_int cpuid, uint64_t target_cpu, int domain, vm_paddr_t release_addr)
 	pmap_disable_promotion((vm_offset_t)pcpup, size);
 	pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
 	pcpup->pc_mpidr = target_cpu & CPU_AFF_MASK;
+	bootpcpu = pcpup;
 
 	dpcpu[cpuid - 1] = (void *)(pcpup + 1);
 	dpcpu_init(dpcpu[cpuid - 1], cpuid);