From patchwork Tue Sep 12 14:16:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 13381771 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 231ACCA0EEB for ; Tue, 12 Sep 2023 14:18:32 +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:Cc:To:From:Subject:Message-ID: References:Mime-Version:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=+rOBwHODUr9HlHhX1cfjEOkBqEenZgZkZVwdUmbVbw8=; b=TYEgfLQxqxwtiShMSnMGeoTfrl x10oePzWVpONmTbt9XK6/fa8JENrGSqphza5zacEwqIdFZsqwKNhr7FvuBXCMWSyDrIBuFoh4cfvl iC9VuhaCoeCnC9lHb9Ucc4to75Q9Ephn4aXeYnX6z+pYaaWCpSuCrPp3jCi39249IAIUNMEgiwpQ2 1z+JaTKIOFNhT2z62GVHEFE7HaX5nIAm5QgdwafvGYgh/FAFZ56dEWuA8IAaDgCB9NM00uCnkX4V+ 5vbErlfV/YJzAUjRCQCP6cP8IN2eORI+alNs1/NHHNja+lnwCRyCAmsUNAmCxa+A7iRGYIs9nh134 xhxl+d2w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qg4DM-003WKV-0l; Tue, 12 Sep 2023 14:18:04 +0000 Received: from mail-wr1-x44a.google.com ([2a00:1450:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qg4DA-003W8V-0Z for linux-arm-kernel@lists.infradead.org; Tue, 12 Sep 2023 14:17:53 +0000 Received: by mail-wr1-x44a.google.com with SMTP id ffacd0b85a97d-31ad77537ebso3755983f8f.0 for ; Tue, 12 Sep 2023 07:17:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1694528270; x=1695133070; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=02lVXddcaK3RQ83APdc0qFSnsO4qXZyNWprlqvJrxN8=; b=NbG/3Jrp80KYd7/wrc366/rQvZ/DFhgjpE4k8DJRs4Kx25ZIzlo6wn3DNSQR+jLsb3 aUsvq67eZAojzpv+Rgh1OSYTyivUkYI3vgJ/MZuH6kaDh73+E2uUx2iNt/nc6Tjfw7ro zyYfb29kjUJcjhTcpH7ycHYoJt7ST7eJyJSxSLD2r6fidGEdNe0un91ehlRFSlVMLbSa 9XFPsNGuN73SZCOmvyDy9HQXOB9QJ8V0TCA7Rb7oRYVH25a9GK9O72GWdtqZxKcmBiK0 R56WXXstgYAZgrdvWpXGj6GiLaX34mDyRK7z1IXWZkqh7snRiwPwQ0dIlZo4Aq1tDIuv LeRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694528270; x=1695133070; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=02lVXddcaK3RQ83APdc0qFSnsO4qXZyNWprlqvJrxN8=; b=GbOiIa+x/SuZUjNWmwiVu2CzRyQLwQUJofGTeXN1HImHW5nIGmZmiW9iF3qP6Svw2t GNggFckkVR2FAI8u3cH3qbXbneI6Ghmy4YJcQEqpf96syjTdHe3kN9cLSDTa+rYXWRz+ f0aJ1HI/ON+yXM0dCYy6aXOeeWE9B3UzSJO+egxwqYulXumOaAZJ+yW6DxiYlhfp5AcA 4Wxr4PhmnQBPWby7Wd2AnoeZH9ewdbZ0ViaavSUamR4uDJl37YXZMu3475T3HpfhoEmj 2dWn9Z7Dk9XUHJyHtKmXgVWDbpexeYiKEtE18WvWJW9/1CtDlOEWXhgt/csDUDWkKyX9 nHrA== X-Gm-Message-State: AOJu0YxJh8N+8pY2XJmDTZvfWMw/RXsAqikn/5zTFKDE4wM89R/7t1WQ L0VkkDothRz0XSyMzUowytPYzMqVrusn49JXhexnqordCt8r0d7YBJx0s5QSMOCMRr76H5Q6YBS nvTP8F0XGWFh0vdjmeApedycKKj5AjWk33YtviAc9hJmeSx1Kuc+EVqYf/y+QeuBUpNV89goYI0 g= X-Google-Smtp-Source: AGHT+IE7V3PNzWt5wMTJ4+as401aV2F2tm1W5Qj9hLMpmVv0/Egh+h43dSdUsq8xpH9cmmKVikx9UQas X-Received: from palermo.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:118a]) (user=ardb job=sendgmr) by 2002:a5d:61c6:0:b0:318:bfe:455b with SMTP id q6-20020a5d61c6000000b003180bfe455bmr146916wrv.5.1694528270075; Tue, 12 Sep 2023 07:17:50 -0700 (PDT) Date: Tue, 12 Sep 2023 14:16:05 +0000 In-Reply-To: <20230912141549.278777-63-ardb@google.com> Mime-Version: 1.0 References: <20230912141549.278777-63-ardb@google.com> X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-Developer-Signature: v=1; a=openpgp-sha256; l=7404; i=ardb@kernel.org; h=from:subject; bh=VHwbQklrHHarXJdq4lwq90XZWzEI7OYiEMQKAxOXrSk=; b=owGbwMvMwCFmkMcZplerG8N4Wi2JIZWhaKn3vmC3hTeycrR2LVxQ/GFlpcraM28SWeKsnab+2 aWuX5DeUcrCIMbBICumyCIw+++7nacnStU6z5KFmcPKBDKEgYtTACaieoeRoTVt6tYpS89Y3XAt rDc+uapkjp/K16lqm3l25BXKeh84LM7wv/z0Co6UFOH0F4evrZuz7krdo03rp64NWfguel3DrgV XpjIDAA== X-Mailer: git-send-email 2.42.0.283.g2d96d420d3-goog Message-ID: <20230912141549.278777-78-ardb@google.com> Subject: [PATCH v4 15/61] arm64: idreg-override: Prepare for place relative reloc patching From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org Cc: Ard Biesheuvel , Catalin Marinas , Will Deacon , Marc Zyngier , Mark Rutland , Ryan Roberts , Anshuman Khandual , Kees Cook , Joey Gouly X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230912_071752_214189_DFC3771B X-CRM114-Status: GOOD ( 22.32 ) 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 From: Ard Biesheuvel The ID reg override handling code uses a rather elaborate data structure that relies on statically initialized absolute address values in pointer fields. This means that this code cannot run until relocation fixups have been applied, and this is unfortunate, because it means we cannot discover overrides for KASLR or LVA/LPA without creating the kernel mapping and performing the relocations first. This can be solved by switching to place-relative relocations, which can be applied by the linker at build time. This means some additional arithmetic is required when dereferencing these pointers, as we can no longer dereference the pointer members directly. So let's implement this for idreg-override.c in a preliminary way, i.e., convert all the references in code to use a special accessor that produces the correct absolute value at runtime. To preserve the strong type checking for the static initializers, use union types for representing the hybrid quantities. Signed-off-by: Ard Biesheuvel --- arch/arm64/kernel/idreg-override.c | 98 +++++++++++++------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c index 536bc33859bc..4e32a44560bf 100644 --- a/arch/arm64/kernel/idreg-override.c +++ b/arch/arm64/kernel/idreg-override.c @@ -21,14 +21,32 @@ static u64 __boot_status __initdata; +// temporary __prel64 related definitions +// to be removed when this code is moved under pi/ + +#define __prel64_initconst __initconst + +typedef void *prel64_t; + +static void *prel64_to_pointer(const prel64_t *p) +{ + return *p; +} + struct ftr_set_desc { char name[FTR_DESC_NAME_LEN]; - struct arm64_ftr_override *override; + union { + struct arm64_ftr_override *override; + prel64_t override_prel; + }; struct { char name[FTR_DESC_FIELD_LEN]; u8 shift; u8 width; - bool (*filter)(u64 val); + union { + bool (*filter)(u64 val); + prel64_t filter_prel; + }; } fields[]; }; @@ -46,7 +64,7 @@ static bool __init mmfr1_vh_filter(u64 val) val == 0); } -static const struct ftr_set_desc mmfr1 __initconst = { +static const struct ftr_set_desc mmfr1 __prel64_initconst = { .name = "id_aa64mmfr1", .override = &id_aa64mmfr1_override, .fields = { @@ -70,7 +88,7 @@ static bool __init pfr0_sve_filter(u64 val) return true; } -static const struct ftr_set_desc pfr0 __initconst = { +static const struct ftr_set_desc pfr0 __prel64_initconst = { .name = "id_aa64pfr0", .override = &id_aa64pfr0_override, .fields = { @@ -94,7 +112,7 @@ static bool __init pfr1_sme_filter(u64 val) return true; } -static const struct ftr_set_desc pfr1 __initconst = { +static const struct ftr_set_desc pfr1 __prel64_initconst = { .name = "id_aa64pfr1", .override = &id_aa64pfr1_override, .fields = { @@ -105,7 +123,7 @@ static const struct ftr_set_desc pfr1 __initconst = { }, }; -static const struct ftr_set_desc isar1 __initconst = { +static const struct ftr_set_desc isar1 __prel64_initconst = { .name = "id_aa64isar1", .override = &id_aa64isar1_override, .fields = { @@ -117,7 +135,7 @@ static const struct ftr_set_desc isar1 __initconst = { }, }; -static const struct ftr_set_desc isar2 __initconst = { +static const struct ftr_set_desc isar2 __prel64_initconst = { .name = "id_aa64isar2", .override = &id_aa64isar2_override, .fields = { @@ -128,7 +146,7 @@ static const struct ftr_set_desc isar2 __initconst = { }, }; -static const struct ftr_set_desc smfr0 __initconst = { +static const struct ftr_set_desc smfr0 __prel64_initconst = { .name = "id_aa64smfr0", .override = &id_aa64smfr0_override, .fields = { @@ -149,7 +167,7 @@ static bool __init hvhe_filter(u64 val) ID_AA64MMFR1_EL1_VH_SHIFT)); } -static const struct ftr_set_desc sw_features __initconst = { +static const struct ftr_set_desc sw_features __prel64_initconst = { .name = "arm64_sw", .override = &arm64_sw_feature_override, .fields = { @@ -159,14 +177,17 @@ static const struct ftr_set_desc sw_features __initconst = { }, }; -static const struct ftr_set_desc * const regs[] __initconst = { - &mmfr1, - &pfr0, - &pfr1, - &isar1, - &isar2, - &smfr0, - &sw_features, +static const union { + const struct ftr_set_desc *reg; + prel64_t reg_prel; +} regs[] __prel64_initconst = { + { .reg = &mmfr1 }, + { .reg = &pfr0 }, + { .reg = &pfr1 }, + { .reg = &isar1 }, + { .reg = &isar2 }, + { .reg = &smfr0 }, + { .reg = &sw_features }, }; static const struct { @@ -214,15 +235,20 @@ static void __init match_options(const char *cmdline) int i; for (i = 0; i < ARRAY_SIZE(regs); i++) { + const struct ftr_set_desc *reg = prel64_to_pointer(®s[i].reg_prel); + struct arm64_ftr_override *override; 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; + override = prel64_to_pointer(®->override_prel); + + 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); + bool (*filter)(u64 val); u64 v; - if (find_field(cmdline, regs[i], f, &v)) + if (find_field(cmdline, reg, f, &v)) continue; /* @@ -230,16 +256,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; + filter = prel64_to_pointer(®->fields[f].filter_prel); + if (filter && !filter(v)) { + override->val |= mask; + override->mask &= ~mask; continue; } - regs[i]->override->val &= ~mask; - regs[i]->override->val |= (v << shift) & mask; - regs[i]->override->mask |= mask; + override->val &= ~mask; + override->val |= (v << shift) & mask; + override->mask |= mask; return; } @@ -313,11 +339,16 @@ void init_feature_override(u64 boot_status); asmlinkage void __init init_feature_override(u64 boot_status) { + struct arm64_ftr_override *override; + const struct ftr_set_desc *reg; int i; for (i = 0; i < ARRAY_SIZE(regs); i++) { - regs[i]->override->val = 0; - regs[i]->override->mask = 0; + reg = prel64_to_pointer(®s[i].reg_prel); + override = prel64_to_pointer(®->override_prel); + + override->val = 0; + override->mask = 0; } __boot_status = boot_status; @@ -325,8 +356,9 @@ 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)); + reg = prel64_to_pointer(®s[i].reg_prel); + override = prel64_to_pointer(®->override_prel); + dcache_clean_inval_poc((unsigned long)override, + (unsigned long)(override + 1)); } }