The Lenovo X13s has broken firmware that makes it impossible to use PAC.
authorkettenis <kettenis@openbsd.org>
Thu, 10 Aug 2023 19:29:32 +0000 (19:29 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 10 Aug 2023 19:29:32 +0000 (19:29 +0000)
But other machines that use the same SoC work just fine.  So instead of
disabling this feature on all CPUs that implement the architectured
algorithm, add an SMBIOS-based check that just disables the feature on
these machines.  This means we need to attach smbios0 before cpu0, which
in turn means attaching efi0 earlier.

tested by patrick@

sys/arch/arm64/arm64/cpu.c
sys/arch/arm64/arm64/pmap.c
sys/arch/arm64/dev/mainbus.c

index 8213130..d2d4381 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpu.c,v 1.97 2023/07/16 16:13:46 kettenis Exp $       */
+/*     $OpenBSD: cpu.c,v 1.98 2023/08/10 19:29:32 kettenis Exp $       */
 
 /*
  * Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
@@ -919,6 +919,16 @@ cpu_attach(struct device *parent, struct device *dev, void *aux)
                cpu_id_aa64pfr0 &= ~ID_AA64PFR0_EL2_MASK;
                cpu_id_aa64pfr0 &= ~ID_AA64PFR0_EL3_MASK;
 
+               /*
+                * Lenovo X13s ships with broken EL2 firmware that
+                * hangs the machine if we enable PAuth.
+                */
+               if (hw_vendor && strcmp(hw_vendor, "LENOVO") == 0 &&
+                   hw_prod && strncmp(hw_prod, "21BX", 4) == 0) {
+                       cpu_id_aa64isar1 &= ~ID_AA64ISAR1_APA_MASK;
+                       cpu_id_aa64isar1 &= ~ID_AA64ISAR1_GPA_MASK;
+               }
+
                cpu_identify(ci);
 
                if (OF_getproplen(ci->ci_node, "clocks") > 0) {
@@ -945,7 +955,6 @@ cpu_init(void)
 {
        uint64_t id_aa64mmfr1, sctlr;
        uint64_t id_aa64pfr0;
-       uint64_t id_aa64isar1;
        uint64_t tcr;
 
        WRITE_SPECIALREG(ttbr0_el1, pmap_kernel()->pm_pt0pa);
@@ -971,8 +980,8 @@ cpu_init(void)
                __asm volatile (".arch armv8.4-a; msr dit, #1");
 
        /* Enable PAuth. */
-       id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1);
-       if (ID_AA64ISAR1_API(id_aa64isar1) >= ID_AA64ISAR1_API_BASE) {
+       if (ID_AA64ISAR1_APA(cpu_id_aa64isar1) >= ID_AA64ISAR1_APA_BASE ||
+           ID_AA64ISAR1_API(cpu_id_aa64isar1) >= ID_AA64ISAR1_API_BASE) {
                sctlr = READ_SPECIALREG(sctlr_el1);
                sctlr |= SCTLR_EnIA | SCTLR_EnDA;
                sctlr |= SCTLR_EnIB | SCTLR_EnDB;
index 6903db0..7bb689d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.98 2023/06/11 21:42:01 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.99 2023/08/10 19:29:32 kettenis Exp $ */
 /*
  * Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com>
  *
@@ -2231,7 +2231,8 @@ pmap_show_mapping(uint64_t va)
 void
 pmap_setpauthkeys(struct pmap *pm)
 {
-       if (ID_AA64ISAR1_API(cpu_id_aa64isar1) >= ID_AA64ISAR1_API_BASE) {
+       if (ID_AA64ISAR1_APA(cpu_id_aa64isar1) >= ID_AA64ISAR1_APA_BASE ||
+           ID_AA64ISAR1_API(cpu_id_aa64isar1) >= ID_AA64ISAR1_API_BASE) {
                __asm volatile (".arch armv8.3-a; msr apiakeylo_el1, %0"
                    :: "r"(pm->pm_apiakey[0]));
                __asm volatile (".arch armv8.3-a; msr apiakeyhi_el1, %0"
@@ -2250,7 +2251,8 @@ pmap_setpauthkeys(struct pmap *pm)
                    :: "r"(pm->pm_apdbkey[1]));
        }
 
-       if (ID_AA64ISAR1_GPI(cpu_id_aa64isar1) >= ID_AA64ISAR1_GPI_IMPL) {
+       if (ID_AA64ISAR1_GPA(cpu_id_aa64isar1) >= ID_AA64ISAR1_GPA_IMPL ||
+           ID_AA64ISAR1_GPI(cpu_id_aa64isar1) >= ID_AA64ISAR1_GPI_IMPL) {
                __asm volatile (".arch armv8.3-a; msr apgakeylo_el1, %0"
                    :: "r"(pm->pm_apgakey[0]));
                __asm volatile (".arch armv8.3-a; msr apgakeyhi_el1, %0"
index 192e45c..495a4ca 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.27 2023/07/19 21:52:55 kettenis Exp $ */
+/* $OpenBSD: mainbus.c,v 1.28 2023/08/10 19:29:32 kettenis Exp $ */
 /*
  * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
@@ -133,6 +133,7 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
        }
 
        mainbus_attach_psci(self);
+       mainbus_attach_efi(self);
 
        /* Attach primary CPU first. */
        mainbus_attach_cpus(self, mainbus_match_primary);
@@ -140,7 +141,6 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
        /* Attach secondary CPUs. */
        mainbus_attach_cpus(self, mainbus_match_secondary);
 
-       mainbus_attach_efi(self);
        mainbus_attach_firmware(self);
        mainbus_attach_resvmem(self);