From patchwork Fri Nov 11 17:11:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 13040631 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6655BC433FE for ; Fri, 11 Nov 2022 17:19:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Qsh3yM3S/BmBDIh5XP6z9aljcHiE81JWhCGGrNl+H5w=; b=dmA0Z+K2bvrroh T85nXg2744vxsVP5/6NI6JBRU1QG7LxLttSY2nlmOqe4FoYHHj7axqzbg/+odlQ9UeQgc5aXFLYmS B9NWSOToJWXYQ3wVFRu/SppV75q4hMwxbk+QALRkNrO226LfrVBF5/3sCKJI9HHs4ZLDVxWL7BdwC eSU692UFteGmBQPYkr9v5iqF8QpIqXRDSnwxl26YLTp99Y+VPG9/fnHP6jCujfaVBmWmmnRkZSbpn Zd94n+MpV/JlkQzoi0hDf8To9aAkM7DYGPdu7JDQnsUP2JzrOtyRNu4MJUvG4elKGWxLnok9ILFoh rafUqgDcZ8995qyyGvfg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1otXf7-00HAdd-3k; Fri, 11 Nov 2022 17:17:53 +0000 Received: from ams.source.kernel.org ([145.40.68.75]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1otXaA-00H7hN-Gx for linux-arm-kernel@lists.infradead.org; Fri, 11 Nov 2022 17:12:48 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 122F9B8267D; Fri, 11 Nov 2022 17:12:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DBC14C433D6; Fri, 11 Nov 2022 17:12:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1668186763; bh=jAT8NmqnR+0AJP+whSFSIznCQ7PGmdov1nT3tBNiGDk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XhIKMPJsTvqjyE+OMVFUs6kVrPFeRw7H/hL2DSg//kVwzYrsmxqBGlKA7HWP76rpN rPF2scS+d8Pp3sbafRKGvnbYcnOABjltCv8VZoSoIC0d4yVsCNxAJZDBOxUJcw3NfF 2cCsyYg76cXz9VC6ySI6konuzGVqDFnKkWM4jvntnbfRHlP90qHanSIiqL4Vy1AcxH UqM919fC4lW+TYI5YKizD5zdMbfMUbkaVQj5QECTWlRFQj3cRW72c2rr+GgaT/j4bc 7I5bdi3ADxUNBNuG4fsUeAGuIFmQVmrnNGoIVWrog/HLkfTMyYO4bcj6563aWbFdn2 WAyrkKjIWSxGg== From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org Cc: Ard Biesheuvel , Marc Zyngier , Will Deacon , Mark Rutland , Kees Cook , Catalin Marinas , Mark Brown , Anshuman Khandual Subject: [PATCH v7 11/33] arm64: idreg-override: Use relative references to override variables Date: Fri, 11 Nov 2022 18:11:39 +0100 Message-Id: <20221111171201.2088501-12-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221111171201.2088501-1-ardb@kernel.org> References: <20221111171201.2088501-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7694; i=ardb@kernel.org; h=from:subject; bh=jAT8NmqnR+0AJP+whSFSIznCQ7PGmdov1nT3tBNiGDk=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjboI7WDvLn3hazBbQ1g/cXBJHJ6wGzwHJ/E6J07tV WvSuk++JAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCY26COwAKCRDDTyI5ktmPJKiKC/ 9QGY3r17BzwVZhzTJ1Mm63Wu5YqdjtYO5kNNPR1GAbkxe1hUcyURhZ1+E4TOI3tbFCCbou4OZRzLqE 8I95gfkL9W1elIVfMZ5Uarfx7l+xc+sL3qxF5eOiM5q4zFc1r7/aI7vqx58tlDzyK4OixTHj5HI2vO qiz0alrR1sJTFJDhsl3T8EAnX7XM2Rgn+5ln1mlGTmNoTyJA/6aKRwrqbmjlN/dJngTUqYe5CkJbOq L5lBqDlSctHXkrENlKgpzL89XmEB2tWILhvKgjVAmoSgHrbwcUxa4SUTCbLs5eZoBFbAvmNTXF5+wO 9Hj4ZDOiyn0YTs4fG7FG8QBX33U+niKWPdOYMtttHYYPZgr6LviXRacyM7pLmoRprlzPyjqfx90R33 GTIEym1Am7fw+ZCiPrtHsrv/FXnWhn7W2Z56hNu5jKiXpDXHmn6HxfLmVoiJ25E+awdubleJD64uwH w/eI10b+HXji+lFTsrfXQd4Kzxf5JUL5RFsuId6fWDXME= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20221111_091246_913965_1B3CD54B X-CRM114-Status: GOOD ( 21.05 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org To prepare the idreg-override for running in a context where statically initialized absolute symbol references are not permitted, use place relative relocations to refer to the 'override' global variables in each feature override descriptor set, and populate the regs[] array using relative references as well. Signed-off-by: Ard Biesheuvel --- arch/arm64/kernel/idreg-override.c | 144 +++++++++----------- 1 file changed, 63 insertions(+), 81 deletions(-) diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c index d7fc813ba5913e27..f8ae7f6d0d9b4fd0 100644 --- a/arch/arm64/kernel/idreg-override.c +++ b/arch/arm64/kernel/idreg-override.c @@ -6,6 +6,7 @@ * Author: Marc Zyngier */ +#include #include #include #include @@ -22,18 +23,29 @@ static u64 __boot_status __initdata; struct ftr_set_desc { - char name[FTR_DESC_NAME_LEN]; - struct arm64_ftr_override *override; + s32 override_offset; // must remain first + char name[FTR_DESC_NAME_LEN]; struct { - char name[FTR_DESC_FIELD_LEN]; - u8 shift; - u8 width; - bool (*filter)(u64 val); - } fields[]; + char name[FTR_DESC_FIELD_LEN]; + u8 shift; + u8 width; + bool (*filter)(u64 val); + } fields[]; }; +static_assert(offsetof(struct ftr_set_desc, override_offset) == 0); + #define FIELD(n, s, f) { .name = n, .shift = s, .width = 4, .filter = f } +#define DEFINE_OVERRIDE(__idx, __id, __name, __ovr, ...) \ + asmlinkage const struct ftr_set_desc __initconst __id = { \ + .name = __name, \ + .fields = { __VA_ARGS__ }, \ + }; \ + asm(".globl " #__ovr "; " \ + ".reloc " #__id ", R_AARCH64_PREL32, " #__ovr "; " \ + ".reloc regs + (4 * " #__idx "), R_AARCH64_PREL32, " #__id) + static bool __init mmfr1_vh_filter(u64 val) { /* @@ -46,14 +58,9 @@ static bool __init mmfr1_vh_filter(u64 val) val == 0); } -static const struct ftr_set_desc mmfr1 __initconst = { - .name = "id_aa64mmfr1", - .override = &id_aa64mmfr1_override, - .fields = { +DEFINE_OVERRIDE(0, mmfr1, "id_aa64mmfr1", id_aa64mmfr1_override, FIELD("vh", ID_AA64MMFR1_EL1_VH_SHIFT, mmfr1_vh_filter), - {} - }, -}; + {}); static bool __init pfr0_sve_filter(u64 val) { @@ -70,14 +77,9 @@ static bool __init pfr0_sve_filter(u64 val) return true; } -static const struct ftr_set_desc pfr0 __initconst = { - .name = "id_aa64pfr0", - .override = &id_aa64pfr0_override, - .fields = { +DEFINE_OVERRIDE(1, pfr0, "id_aa64pfr0", id_aa64pfr0_override, FIELD("sve", ID_AA64PFR0_EL1_SVE_SHIFT, pfr0_sve_filter), - {} - }, -}; + {}); static bool __init pfr1_sme_filter(u64 val) { @@ -94,67 +96,46 @@ static bool __init pfr1_sme_filter(u64 val) return true; } -static const struct ftr_set_desc pfr1 __initconst = { - .name = "id_aa64pfr1", - .override = &id_aa64pfr1_override, - .fields = { +DEFINE_OVERRIDE(2, pfr1, "id_aa64pfr1", id_aa64pfr1_override, FIELD("bt", ID_AA64PFR1_EL1_BT_SHIFT, NULL ), FIELD("mte", ID_AA64PFR1_EL1_MTE_SHIFT, NULL), FIELD("sme", ID_AA64PFR1_EL1_SME_SHIFT, pfr1_sme_filter), - {} - }, -}; + {}); -static const struct ftr_set_desc isar1 __initconst = { - .name = "id_aa64isar1", - .override = &id_aa64isar1_override, - .fields = { +DEFINE_OVERRIDE(3, isar1, "id_aa64isar1", id_aa64isar1_override, FIELD("gpi", ID_AA64ISAR1_EL1_GPI_SHIFT, NULL), FIELD("gpa", ID_AA64ISAR1_EL1_GPA_SHIFT, NULL), FIELD("api", ID_AA64ISAR1_EL1_API_SHIFT, NULL), FIELD("apa", ID_AA64ISAR1_EL1_APA_SHIFT, NULL), - {} - }, -}; + {}); -static const struct ftr_set_desc isar2 __initconst = { - .name = "id_aa64isar2", - .override = &id_aa64isar2_override, - .fields = { +DEFINE_OVERRIDE(4, isar2, "id_aa64isar2", id_aa64isar2_override, FIELD("gpa3", ID_AA64ISAR2_EL1_GPA3_SHIFT, NULL), FIELD("apa3", ID_AA64ISAR2_EL1_APA3_SHIFT, NULL), - {} - }, -}; + {}); -static const struct ftr_set_desc smfr0 __initconst = { - .name = "id_aa64smfr0", - .override = &id_aa64smfr0_override, - .fields = { +DEFINE_OVERRIDE(5, smfr0, "id_aa64smfr0", id_aa64smfr0_override, /* FA64 is a one bit field... :-/ */ { "fa64", ID_AA64SMFR0_EL1_FA64_SHIFT, 1, }, - {} - }, -}; + {}); -static const struct ftr_set_desc sw_features __initconst = { - .name = "arm64_sw", - .override = &arm64_sw_feature_override, - .fields = { +DEFINE_OVERRIDE(6, sw_features, "arm64_sw", arm64_sw_feature_override, FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL), - {} - }, -}; + {}); -static const struct ftr_set_desc * const regs[] __initconst = { - &mmfr1, - &pfr0, - &pfr1, - &isar1, - &isar2, - &smfr0, - &sw_features, -}; +/* + * regs[] is populated by R_AARCH64_PREL32 directives invisible to the compiler + * so it cannot be static or const, or the compiler might try to use constant + * propagation on the values. + */ +asmlinkage s32 regs[7] __initdata = { [0 ... ARRAY_SIZE(regs) - 1] = S32_MAX }; + +static struct arm64_ftr_override * __init reg_override(int i) +{ + const struct ftr_set_desc *reg = offset_to_ptr(®s[i]); + + return offset_to_ptr(®->override_offset); +} static const struct { char alias[FTR_ALIAS_NAME_LEN]; @@ -193,15 +174,16 @@ static void __init match_options(const char *cmdline) int i; for (i = 0; i < ARRAY_SIZE(regs); i++) { + const struct ftr_set_desc *reg = offset_to_ptr(®s[i]); int f; - for (f = 0; strlen(regs[i]->fields[f].name); f++) { - u64 shift = regs[i]->fields[f].shift; - u64 width = regs[i]->fields[f].width ?: 4; + for (f = 0; strlen(reg->fields[f].name); f++) { + u64 shift = reg->fields[f].shift; + u64 width = reg->fields[f].width ?: 4; u64 mask = GENMASK_ULL(shift + width - 1, shift); u64 v; - if (find_field(cmdline, regs[i], f, &v)) + if (find_field(cmdline, reg, f, &v)) continue; /* @@ -209,16 +191,16 @@ static void __init match_options(const char *cmdline) * it by setting the value to the all-ones while * clearing the mask... Yes, this is fragile. */ - if (regs[i]->fields[f].filter && - !regs[i]->fields[f].filter(v)) { - regs[i]->override->val |= mask; - regs[i]->override->mask &= ~mask; + if (reg->fields[f].filter && + !reg->fields[f].filter(v)) { + reg_override(i)->val |= mask; + reg_override(i)->mask &= ~mask; continue; } - regs[i]->override->val &= ~mask; - regs[i]->override->val |= (v << shift) & mask; - regs[i]->override->mask |= mask; + reg_override(i)->val &= ~mask; + reg_override(i)->val |= (v << shift) & mask; + reg_override(i)->mask |= mask; return; } @@ -295,8 +277,8 @@ asmlinkage void __init init_feature_override(u64 boot_status) int i; for (i = 0; i < ARRAY_SIZE(regs); i++) { - regs[i]->override->val = 0; - regs[i]->override->mask = 0; + reg_override(i)->val = 0; + reg_override(i)->mask = 0; } __boot_status = boot_status; @@ -304,8 +286,8 @@ asmlinkage void __init init_feature_override(u64 boot_status) parse_cmdline(); for (i = 0; i < ARRAY_SIZE(regs); i++) { - dcache_clean_inval_poc((unsigned long)regs[i]->override, - (unsigned long)regs[i]->override + - sizeof(*regs[i]->override)); + dcache_clean_inval_poc((unsigned long)reg_override(i), + (unsigned long)reg_override(i) + + sizeof(struct arm64_ftr_override)); } }