Page MenuHomeFreeBSD

D47812.diff
No OneTemporary

D47812.diff

diff --git a/sys/arm64/arm64/cpu_feat.c b/sys/arm64/arm64/cpu_feat.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/arm64/cpu_feat.c
@@ -0,0 +1,119 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Arm Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <machine/cpu.h>
+#include <machine/cpu_feat.h>
+
+/* TODO: Make this a list if we ever grow a callback other than smccc_errata */
+static cpu_feat_errata_check_fn cpu_feat_check_cb = NULL;
+
+void
+enable_cpu_feat(uint32_t stage)
+{
+ struct cpu_feat **featp, *feat;
+ uint32_t midr;
+ u_int errata_count, *errata_list;
+ cpu_feat_errata errata_status;
+
+ MPASS((stage & ~CPU_FEAT_STAGE_MASK) == 0);
+
+ midr = get_midr();
+ SET_FOREACH(featp, cpu_feat_set) {
+ feat = *featp;
+
+ /* Run the enablement code at the correct stage of boot */
+ if ((feat->feat_flags & CPU_FEAT_STAGE_MASK) != stage)
+ continue;
+
+ /* If the feature is system wide run on a single CPU */
+ if ((feat->feat_flags & CPU_FEAT_SCOPE_MASK)==CPU_FEAT_SYSTEM &&
+ PCPU_GET(cpuid) != 0)
+ continue;
+
+ if (feat->feat_check != NULL && !feat->feat_check(feat, midr))
+ continue;
+
+ /*
+ * Check if the feature has any errata that may need a
+ * workaround applied (or it is to install the workaround for
+ * known errata.
+ */
+ errata_status = ERRATA_NONE;
+ errata_list = NULL;
+ errata_count = 0;
+ if (feat->feat_has_errata != NULL) {
+ if (feat->feat_has_errata(feat, midr, &errata_list,
+ &errata_count)) {
+ /* Assume we are affected */
+ errata_status = ERRATA_AFFECTED;
+ }
+ }
+
+ if (errata_status == ERRATA_AFFECTED &&
+ cpu_feat_check_cb != NULL) {
+ for (int i = 0; i < errata_count; i++) {
+ cpu_feat_errata new_status;
+
+ /* Check if affected by this erratum */
+ new_status = cpu_feat_check_cb(feat,
+ errata_list[i]);
+ if (new_status != ERRATA_UNKNOWN) {
+ errata_status = new_status;
+ errata_list = &errata_list[i];
+ errata_count = 1;
+ break;
+ }
+ }
+ }
+
+ /* Shouldn't be possible */
+ MPASS(errata_status != ERRATA_UNKNOWN);
+
+ feat->feat_enable(feat, errata_status, errata_list,
+ errata_count);
+ }
+}
+
+static void
+enable_cpu_feat_after_dev(void *dummy __unused)
+{
+ MPASS(PCPU_GET(cpuid) == 0);
+ enable_cpu_feat(CPU_FEAT_AFTER_DEV);
+}
+SYSINIT(enable_cpu_feat_after_dev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE,
+ enable_cpu_feat_after_dev, NULL);
+
+void
+cpu_feat_register_errata_check(cpu_feat_errata_check_fn cb)
+{
+ MPASS(cpu_feat_check_cb == NULL);
+ cpu_feat_check_cb = cb;
+}
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -77,6 +77,7 @@
#include <machine/armreg.h>
#include <machine/cpu.h>
+#include <machine/cpu_feat.h>
#include <machine/debug_monitor.h>
#include <machine/hypervisor.h>
#include <machine/kdb.h>
@@ -999,6 +1000,9 @@
panic("Invalid bus configuration: %s",
kern_getenv("kern.cfg.order"));
+ /* Detect early CPU feature support */
+ enable_cpu_feat(CPU_FEAT_EARLY_BOOT);
+
/*
* Check if pointer authentication is available on this system, and
* if so enable its use. This needs to be called before init_proc0
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
@@ -56,6 +56,7 @@
#include <machine/machdep.h>
#include <machine/cpu.h>
+#include <machine/cpu_feat.h>
#include <machine/debug_monitor.h>
#include <machine/intr.h>
#include <machine/smp.h>
@@ -224,6 +225,9 @@
/* Ensure the stores in identify_cpu have completed */
atomic_thread_fence_acq_rel();
+ /* Detect early CPU feature support */
+ enable_cpu_feat(CPU_FEAT_EARLY_BOOT);
+
/* Signal the BSP and spin until it has released all APs. */
atomic_add_int(&aps_started, 1);
while (!atomic_load_int(&aps_ready))
@@ -241,6 +245,7 @@
pcpup->pc_curpmap = pmap0;
install_cpu_errata();
+ enable_cpu_feat(CPU_FEAT_AFTER_DEV);
intr_pic_init_secondary();
diff --git a/sys/arm64/include/cpu_feat.h b/sys/arm64/include/cpu_feat.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/include/cpu_feat.h
@@ -0,0 +1,88 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Arm Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_CPU_FEAT_H_
+#define _MACHINE_CPU_FEAT_H_
+
+#include <sys/linker_set.h>
+
+typedef enum {
+ ERRATA_UNKNOWN, /* Unknown erratum */
+ ERRATA_NONE, /* No errata for this feature on this system. */
+ ERRATA_AFFECTED, /* There is errata on this system. */
+ ERRATA_FW_MITIGAION, /* There is errata, and a firmware */
+ /* mitigation. The mitigation may need a */
+ /* kernel component. */
+} cpu_feat_errata;
+
+#define CPU_FEAT_STAGE_MASK 0x00000001
+#define CPU_FEAT_EARLY_BOOT 0x00000000
+#define CPU_FEAT_AFTER_DEV 0x00000001
+
+#define CPU_FEAT_SCOPE_MASK 0x00000010
+#define CPU_FEAT_PER_CPU 0x00000000
+#define CPU_FEAT_SYSTEM 0x00000010
+
+struct cpu_feat;
+
+typedef bool (cpu_feat_check)(const struct cpu_feat *, u_int);
+typedef bool (cpu_feat_has_errata)(const struct cpu_feat *, u_int,
+ u_int **, u_int *);
+typedef void (cpu_feat_enable)(const struct cpu_feat *, cpu_feat_errata,
+ u_int *, u_int);
+
+struct cpu_feat {
+ const char *feat_name;
+ cpu_feat_check *feat_check;
+ cpu_feat_has_errata *feat_has_errata;
+ cpu_feat_enable *feat_enable;
+ uint32_t feat_flags;
+};
+SET_DECLARE(cpu_feat_set, struct cpu_feat);
+
+/*
+ * Allow drivers to mark an erratum as worked around, e.g. the Errata
+ * Management ABI may know the workaround isn't needed on a given system.
+ */
+typedef cpu_feat_errata (*cpu_feat_errata_check_fn)(const struct cpu_feat *,
+ u_int);
+void cpu_feat_register_errata_check(cpu_feat_errata_check_fn);
+
+void enable_cpu_feat(uint32_t);
+
+/* Check if an erratum is in the list of errata */
+static inline bool
+cpu_feat_has_erratum(u_int *errata_list, u_int errata_count, u_int erratum)
+{
+ for (u_int i = 0; i < errata_count; i++)
+ if (errata_list[0] == erratum)
+ return (true);
+
+ return (false);
+}
+
+#endif /* _MACHINE_CPU_FEAT_H_ */
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -32,6 +32,7 @@
arm64/arm64/clock.c standard
arm64/arm64/copyinout.S standard
arm64/arm64/cpu_errata.c standard
+arm64/arm64/cpu_feat.c standard
arm64/arm64/cpufunc_asm.S standard
arm64/arm64/db_disasm.c optional ddb
arm64/arm64/db_interface.c optional ddb

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 24, 4:44 PM (6 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16092671
Default Alt Text
D47812.diff (8 KB)

Event Timeline