Expose the complete set of ID registers as defined in the current version
authorkettenis <kettenis@openbsd.org>
Thu, 24 Nov 2022 14:43:16 +0000 (14:43 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 24 Nov 2022 14:43:16 +0000 (14:43 +0000)
of ARMv8/ARMv9.  Make sure we only expose the features that we know about
and support in our kernel.  This matches what Linux does.  For now, mostly
restrict ourselves to features defined in ARMv8.5 which means that we only
actually implement support for ID_AA64ISAR0_EL1, ID_AA64ISAR1_EL1,
ID_AA64PFR0_EL1 and ID_AA64PFR1_EL1.  For the other registers we simply
always return 0.

ok deraadt@

sys/arch/arm64/arm64/cpu.c
sys/arch/arm64/arm64/machdep.c
sys/arch/arm64/include/cpu.h

index 04dde3f..2104d06 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.72 2022/11/08 16:53:40 kettenis Exp $       */
+/*     $OpenBSD: cpu.c,v 1.73 2022/11/24 14:43:16 kettenis Exp $       */
 
 /*
  * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
@@ -200,6 +200,8 @@ int cpu_node;
 
 uint64_t cpu_id_aa64isar0;
 uint64_t cpu_id_aa64isar1;
+uint64_t cpu_id_aa64pfr0;
+uint64_t cpu_id_aa64pfr1;
 
 #ifdef CRYPTO
 int arm64_has_aes;
@@ -380,6 +382,14 @@ cpu_identify(struct cpu_info *ci)
                printf("\n%s: mismatched ID_AA64ISAR1_EL1",
                    ci->ci_dev->dv_xname);
        }
+       if (READ_SPECIALREG(id_aa64pfr0_el1) != cpu_id_aa64pfr0) {
+               printf("\n%s: mismatched ID_AA64PFR0_EL1",
+                   ci->ci_dev->dv_xname);
+       }
+       if (READ_SPECIALREG(id_aa64pfr1_el1) != cpu_id_aa64pfr1) {
+               printf("\n%s: mismatched ID_AA64PFR1_EL1",
+                   ci->ci_dev->dv_xname);
+       }
 
        printf("\n%s: ", ci->ci_dev->dv_xname);
 
@@ -732,6 +742,8 @@ cpu_attach(struct device *parent, struct device *dev, void *aux)
 #endif
                cpu_id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
                cpu_id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1);
+               cpu_id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
+               cpu_id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1);
 
                cpu_identify(ci);
 
index 36d5070..311d8bb 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.76 2022/11/21 20:19:21 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.77 2022/11/24 14:43:16 kettenis Exp $ */
 /*
  * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
@@ -315,6 +315,8 @@ cpu_switchto(struct proc *old, struct proc *new)
 
 extern uint64_t cpu_id_aa64isar0;
 extern uint64_t cpu_id_aa64isar1;
+extern uint64_t cpu_id_aa64pfr0;
+extern uint64_t cpu_id_aa64pfr1;
 
 /*
  * machine dependent system variables.
@@ -326,6 +328,7 @@ cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
 {
        char *compatible;
        int node, len, error;
+       uint64_t value;
 
        /* all sysctl names at this level are terminal */
        if (namelen != 1)
@@ -344,9 +347,30 @@ cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                free(compatible, M_TEMP, len);
                return error;
        case CPU_ID_AA64ISAR0:
-               return sysctl_rdquad(oldp, oldlenp, newp, cpu_id_aa64isar0);
+               value = cpu_id_aa64isar0 & ID_AA64ISAR0_MASK;
+               value &= ~ID_AA64ISAR0_TLB_MASK;
+               return sysctl_rdquad(oldp, oldlenp, newp, value);
        case CPU_ID_AA64ISAR1:
-               return sysctl_rdquad(oldp, oldlenp, newp, cpu_id_aa64isar1);
+               value = cpu_id_aa64isar1 & ID_AA64ISAR1_MASK;
+               value &= ~ID_AA64ISAR1_SPECRES_MASK;
+               return sysctl_rdquad(oldp, oldlenp, newp, value);
+       case CPU_ID_AA64PFR0:
+               value = 0;
+               value |= cpu_id_aa64pfr0 & ID_AA64PFR0_FP_MASK;
+               value |= cpu_id_aa64pfr0 & ID_AA64PFR0_ADV_SIMD_MASK;
+               value |= cpu_id_aa64pfr0 & ID_AA64PFR0_DIT_MASK;
+               return sysctl_rdquad(oldp, oldlenp, newp, value);
+       case CPU_ID_AA64PFR1:
+               value = 0;
+               value |= cpu_id_aa64pfr1 & ID_AA64PFR1_SBSS_MASK;
+               return sysctl_rdquad(oldp, oldlenp, newp, value);
+       case CPU_ID_AA64ISAR2:
+       case CPU_ID_AA64MMFR0:
+       case CPU_ID_AA64MMFR1:
+       case CPU_ID_AA64MMFR2:
+       case CPU_ID_AA64SMFR0:
+       case CPU_ID_AA64ZFR0:
+               return sysctl_rdquad(oldp, oldlenp, newp, 0);
        default:
                return (EOPNOTSUPP);
        }
index f1eea12..30154c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.30 2022/11/08 20:41:36 mlarkin Exp $ */
+/* $OpenBSD: cpu.h,v 1.31 2022/11/24 14:43:16 kettenis Exp $ */
 /*
  * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
  *
 #define        CPU_COMPATIBLE          1       /* compatible property */
 #define        CPU_ID_AA64ISAR0        2
 #define        CPU_ID_AA64ISAR1        3
-#define        CPU_MAXID               4       /* number of valid machdep ids */
+#define        CPU_ID_AA64ISAR2        4
+#define        CPU_ID_AA64MMFR0        5
+#define        CPU_ID_AA64MMFR1        6
+#define        CPU_ID_AA64MMFR2        7
+#define        CPU_ID_AA64PFR0         8
+#define        CPU_ID_AA64PFR1         9
+#define        CPU_ID_AA64SMFR0       10
+#define        CPU_ID_AA64ZFR0        11
+#define        CPU_MAXID              12       /* number of valid machdep ids */
 
 #define        CTL_MACHDEP_NAMES { \
        { 0, 0 }, \
        { "compatible", CTLTYPE_STRING }, \
        { "id_aa64isar0", CTLTYPE_QUAD }, \
        { "id_aa64isar1", CTLTYPE_QUAD }, \
+       { "id_aa64isar2", CTLTYPE_QUAD }, \
+       { "id_aa64mmfr0", CTLTYPE_QUAD }, \
+       { "id_aa64mmfr1", CTLTYPE_QUAD }, \
+       { "id_aa64mmfr2", CTLTYPE_QUAD }, \
+       { "id_aa64pfr0", CTLTYPE_QUAD }, \
+       { "id_aa64pfr1", CTLTYPE_QUAD }, \
+       { "id_aa64smfr0", CTLTYPE_QUAD }, \
+       { "id_aa64zfr0", CTLTYPE_QUAD }, \
 }
 
 #ifdef _KERNEL