Tolerate difference in some of the features advertised by the
authorkettenis <kettenis@openbsd.org>
Wed, 17 May 2023 21:45:41 +0000 (21:45 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 17 May 2023 21:45:41 +0000 (21:45 +0000)
ID_AA64PFR0_EL1 register across cores.  The CSV2/CSV3 features are handled
on a per-core basis so it is fine if they are different.  And we only
support 64-bit userland so it is fine if the EL0/EL1/EL2/EL3 fields are
different too.

This prevents us from printing a warning on the Rockchip RK3588 SoC which
combines Cortex-A55 with Cortex-A76 that implement a sightly different
feature set.

ok deraadt@, mlarkin@

sys/arch/arm64/arm64/cpu.c

index 631b9f1..8366279 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.89 2023/04/29 08:50:53 kettenis Exp $       */
+/*     $OpenBSD: cpu.c,v 1.90 2023/05/17 21:45:41 kettenis Exp $       */
 
 /*
  * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
@@ -477,7 +477,16 @@ cpu_identify(struct cpu_info *ci)
                printf("\n%s: mismatched ID_AA64ISAR2_EL1",
                    ci->ci_dev->dv_xname);
        }
-       if (READ_SPECIALREG(id_aa64pfr0_el1) != cpu_id_aa64pfr0) {
+       id = READ_SPECIALREG(id_aa64pfr0_el1);
+       /* Allow CSV2/CVS3 to be different. */
+       id &= ~ID_AA64PFR0_CSV2_MASK;
+       id &= ~ID_AA64PFR0_CSV3_MASK;
+       /* Ignore 32-bit support in all exception levels. */
+       id &= ~ID_AA64PFR0_EL0_MASK;
+       id &= ~ID_AA64PFR0_EL1_MASK;
+       id &= ~ID_AA64PFR0_EL2_MASK;
+       id &= ~ID_AA64PFR0_EL3_MASK;
+       if (id != cpu_id_aa64pfr0) {
                printf("\n%s: mismatched ID_AA64PFR0_EL1",
                    ci->ci_dev->dv_xname);
        }
@@ -884,6 +893,25 @@ cpu_attach(struct device *parent, struct device *dev, void *aux)
                cpu_id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
                cpu_id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1);
 
+               /*
+                * The CSV2/CSV3 "features" are handled on a
+                * per-processor basis.  So it is fine if these fields
+                * differ between CPU cores.  Mask off these fields to
+                * prevent exporting these to userland.
+                */
+               cpu_id_aa64pfr0 &= ~ID_AA64PFR0_CSV2_MASK;
+               cpu_id_aa64pfr0 &= ~ID_AA64PFR0_CSV3_MASK;
+
+               /*
+                * We only support 64-bit mode, so we don't care about
+                * differences in support for 32-bit mode between
+                * cores.  Mask off these fields as well.
+                */
+               cpu_id_aa64pfr0 &= ~ID_AA64PFR0_EL0_MASK;
+               cpu_id_aa64pfr0 &= ~ID_AA64PFR0_EL1_MASK;
+               cpu_id_aa64pfr0 &= ~ID_AA64PFR0_EL2_MASK;
+               cpu_id_aa64pfr0 &= ~ID_AA64PFR0_EL3_MASK;
+
                cpu_identify(ci);
 
                if (OF_getproplen(ci->ci_node, "clocks") > 0) {