From 83e0a8ee3ac8e296e818d14426c6708a905425f2 Mon Sep 17 00:00:00 2001 From: kettenis Date: Thu, 10 Aug 2023 19:29:32 +0000 Subject: [PATCH] The Lenovo X13s has broken firmware that makes it impossible to use PAC. 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 | 17 +++++++++++++---- sys/arch/arm64/arm64/pmap.c | 8 +++++--- sys/arch/arm64/dev/mainbus.c | 4 ++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/sys/arch/arm64/arm64/cpu.c b/sys/arch/arm64/arm64/cpu.c index 8213130c3a6..d2d4381d19c 100644 --- a/sys/arch/arm64/arm64/cpu.c +++ b/sys/arch/arm64/arm64/cpu.c @@ -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 @@ -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; diff --git a/sys/arch/arm64/arm64/pmap.c b/sys/arch/arm64/arm64/pmap.c index 6903db003b5..7bb689d5040 100644 --- a/sys/arch/arm64/arm64/pmap.c +++ b/sys/arch/arm64/arm64/pmap.c @@ -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 * @@ -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" diff --git a/sys/arch/arm64/dev/mainbus.c b/sys/arch/arm64/dev/mainbus.c index 192e45c2f95..495a4ca286a 100644 --- a/sys/arch/arm64/dev/mainbus.c +++ b/sys/arch/arm64/dev/mainbus.c @@ -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 * Copyright (c) 2017 Mark Kettenis @@ -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); -- 2.20.1