The branch main has been updated by andrew:

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

commit 77d5df3b9261173f10afb7ba739f98c62a41395f
Author:     Andrew Turner <and...@freebsd.org>
AuthorDate: 2025-05-27 19:39:20 +0000
Commit:     Andrew Turner <and...@freebsd.org>
CommitDate: 2025-05-27 19:50:11 +0000

    arm64: Move CPU feature & errata setup earlier
    
    To allow for the state of some errata to be detected we need devices,
    e.g. to call into the SMCCC firmware. Because of this we need to check
    this after devices drivers are ready.
    
    As the presence of this errata may require us to mask out some fields
    from the ID register views, and these register views are used to build
    the userspace hwcap values and used in late kernel ifunc resolvers we
    need to ensure they have run by a known point.
    
    Add a synchronisation point for APs at SI_SUB_CONFIGURE,
    SI_ORDER_MIDDLE + 1. This is early enough that we can move setting the
    hwcap values just after this, and late enough for devices to be present.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D50367
---
 sys/arm64/arm64/mp_machdep.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index 88d48bceb892..e4d011df3a06 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -124,7 +124,7 @@ static void *bootstacks[MAXCPU];
 static volatile int aps_started;
 
 /* Set to 1 once we're ready to let the APs out of the pen. */
-static volatile int aps_ready;
+static volatile int aps_after_dev, aps_ready;
 
 /* Temporary variables for init_secondary()  */
 static void *dpcpu[MAXCPU - 1];
@@ -160,6 +160,26 @@ wait_for_aps(void)
        return (false);
 }
 
+static void
+release_aps_after_dev(void *dummy __unused)
+{
+       /* Only release CPUs if they exist */
+       if (mp_ncpus == 1)
+               return;
+
+       atomic_store_int(&aps_started, 0);
+       atomic_store_rel_int(&aps_after_dev, 1);
+       /* Wake up the other CPUs */
+       __asm __volatile(
+           "dsb ishst  \n"
+           "sev        \n"
+           ::: "memory");
+
+       wait_for_aps();
+}
+SYSINIT(aps_after_dev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE + 1,
+    release_aps_after_dev, NULL);
+
 static void
 release_aps(void *dummy __unused)
 {
@@ -237,8 +257,20 @@ init_secondary(uint64_t cpu)
        /* Detect early CPU feature support */
        enable_cpu_feat(CPU_FEAT_EARLY_BOOT);
 
-       /* Signal the BSP and spin until it has released all APs. */
+       /* Signal we are waiting for aps_after_dev */
        atomic_add_int(&aps_started, 1);
+
+       /* Wait for devices to be ready */
+       while (!atomic_load_int(&aps_after_dev))
+               __asm __volatile("wfe");
+
+       install_cpu_errata();
+       enable_cpu_feat(CPU_FEAT_AFTER_DEV);
+
+       /* Signal we are done */
+       atomic_add_int(&aps_started, 1);
+
+       /* Wait until we can run the scheduler */
        while (!atomic_load_int(&aps_ready))
                __asm __volatile("wfe");
 
@@ -253,9 +285,6 @@ init_secondary(uint64_t cpu)
            ("pmap0 doesn't match cpu %ld's ttbr0", cpu));
        pcpup->pc_curpmap = pmap0;
 
-       install_cpu_errata();
-       enable_cpu_feat(CPU_FEAT_AFTER_DEV);
-
        intr_pic_init_secondary();
 
        /* Start per-CPU event timers. */

Reply via email to