Received: by 2002:a05:7412:da14:b0:e2:908c:2ebd with SMTP id fe20csp1860738rdb; Mon, 9 Oct 2023 05:30:47 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHm6Jlto7U8B2rVwNieJPW5cbPjagdKT/jetwhMxT+kmF9Tk8e2bZhs+CsXP/7YgeR4+zeU X-Received: by 2002:a05:6a20:f395:b0:16b:c62d:876 with SMTP id qr21-20020a056a20f39500b0016bc62d0876mr6253844pzb.23.1696854647298; Mon, 09 Oct 2023 05:30:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696854647; cv=none; d=google.com; s=arc-20160816; b=yN7lrs68fwTsf6n3eSuAuwH/ml8+Ogol8IpayVEnuGa59xtOi2f7RCJu1YNi6WAnKS 2TQMrPAicQUuNdhKNf6PAt+sif+HqxRDFRbV8w2LXrfPsMmHS4L7ZFG94ZVKWmhwXQum fn+ecCUyV/PynsbdxJAV87lbtvYQfG2jyF10c3UwZPffQdQTwOibgrH7xCEguVgoKnrV AM/ay3d0iGw47o8t4ZR6tECLDtJswxFPJXQZ438ILZvHUEHRuGr23foisMSvyQjCHiM9 AETfgXmJmJjisgPAey91lxTGWERqdu2Gtuk61WfgSknBttNYbbZsBN/f0lq07fw6icaf K1yg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:robot-unsubscribe :robot-id:message-id:mime-version:references:in-reply-to:cc:subject :to:reply-to:sender:from:dkim-signature:dkim-signature:date; bh=Xgzjw9IbTNiFuEXqRbyft814fDCqbYD8JjHtG9ES/cs=; fh=LWlv3U+xZ3+vQt4tlJRIlKl5VzN7iFjjE/bzRmlxKDA=; b=rMxXK6/HQMlwzxj5iwFUesiuGUcJgbp9Y8M2Ag4ElRqrqloUwThYsj2FRUcf/KEluQ JdXeDivBagO3becvEYxtF7Ci7S6n0idj2U9aIEm+DR6OFRH7HARIXO/EDg5DEw0CB5c/ V4Okqb+mmcpBgqxPOcv2m0s30es1AgABsmV+ux8l2doEzoOTkpziUthvc6MJqpmJ3Hgj FwcjmehG3VIzHN3iHr1uJmVWN803IlhuYRQXrdvv7y5lxd8j1rKALcP6n9CSGwEqTwDj CJsCWZ3hCLd9DcL7ZaFEnM/Zj4gp01s4J3IWFAHIW0Z7ojmDHi+7mZqP3Et0GQ8B1WFa 6Guw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=MVwEjhN5; dkim=neutral (no key) header.i=@linutronix.de header.b=sEO8cURR; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from fry.vger.email (fry.vger.email. [23.128.96.38]) by mx.google.com with ESMTPS id t13-20020a1709027fcd00b001c62139b16esi657793plb.4.2023.10.09.05.30.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Oct 2023 05:30:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) client-ip=23.128.96.38; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=MVwEjhN5; dkim=neutral (no key) header.i=@linutronix.de header.b=sEO8cURR; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 4B8308042E31; Mon, 9 Oct 2023 05:30:12 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376350AbjJIM3u (ORCPT + 99 others); Mon, 9 Oct 2023 08:29:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38684 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346402AbjJIM3r (ORCPT ); Mon, 9 Oct 2023 08:29:47 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE53D9C; Mon, 9 Oct 2023 05:29:45 -0700 (PDT) Date: Mon, 09 Oct 2023 12:29:43 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1696854584; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Xgzjw9IbTNiFuEXqRbyft814fDCqbYD8JjHtG9ES/cs=; b=MVwEjhN5hcYRWnZPcYlHyIQ0c5vlI3XBbceG5jQIRL9VX7We8DHY3m9QNdDlZ7UvhASD/r YS9AEERc+iACsqIpDmR1cAkHg0XSoLtlgAM9/Hc4XOUkxWKFmA3D9wAvAsBxaSwin7OhxO 5Dbv/zmImIx+LfsbmnuIfV7kglWrd3A9WSOHAXwYJOxmQqbExsDCoRhnHB3Thhsij59e5x Vvh1xHpR6Xqbr3ukg2lruEYm8VvWjyw+glJKEMlC/67rE/Bw9lEfp5xFiPD4MV24+dtez/ OPMOPRo9gW06O+o/YYG1R7sav9ISNEF4Sm/jFYjr4zAgRpWCVUKTTq6ytQ3pQw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1696854584; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Xgzjw9IbTNiFuEXqRbyft814fDCqbYD8JjHtG9ES/cs=; b=sEO8cURRwZXw4LO8s6fDqyk0EjfjB+jEvqxvpx9IBsEJdhJeDfLmHop5yoJGTlLntwlzJH +PGeZKwk4b1uUmAA== From: "tip-bot2 for Thomas Gleixner" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/microcode] x86/microcode: Prepare for minimal revision check Cc: Thomas Gleixner , "Borislav Petkov (AMD)" , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20231002115903.718904225@linutronix.de> References: <20231002115903.718904225@linutronix.de> MIME-Version: 1.0 Message-ID: <169685458358.3135.5679462071745255006.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=2.7 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Mon, 09 Oct 2023 05:30:12 -0700 (PDT) X-Spam-Level: ** The following commit has been merged into the x86/microcode branch of tip: Commit-ID: bbaea0e7fc4322ce997d6bc218ce3f2df5c64bb8 Gitweb: https://git.kernel.org/tip/bbaea0e7fc4322ce997d6bc218ce3f2df5c64bb8 Author: Thomas Gleixner AuthorDate: Mon, 02 Oct 2023 14:00:10 +02:00 Committer: Borislav Petkov (AMD) CommitterDate: Fri, 06 Oct 2023 15:12:25 +02:00 x86/microcode: Prepare for minimal revision check Applying microcode late can be fatal for the running kernel when the update changes functionality which is in use already in a non-compatible way, e.g. by removing a CPUID bit. There is no way for admins which do not have access to the vendors deep technical support to decide whether late loading of such a microcode is safe or not. Intel has added a new field to the microcode header which tells the minimal microcode revision which is required to be active in the CPU in order to be safe. Provide infrastructure for handling this in the core code and a command line switch which allows to enforce it. If the update is considered safe the kernel is not tainted and the annoying warning message not emitted. If it's enforced and the currently loaded microcode revision is not safe for late loading then the load is aborted. Signed-off-by: Thomas Gleixner Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20231002115903.718904225@linutronix.de --- Documentation/admin-guide/kernel-parameters.txt | 5 +++- arch/x86/Kconfig | 23 +++++++++++++++- arch/x86/kernel/cpu/microcode/amd.c | 3 ++- arch/x86/kernel/cpu/microcode/core.c | 19 +++++++++---- arch/x86/kernel/cpu/microcode/intel.c | 3 ++- arch/x86/kernel/cpu/microcode/internal.h | 3 ++- 6 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 0a1731a..d762e17 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3275,6 +3275,11 @@ mga= [HW,DRM] + microcode.force_minrev= [X86] + Format: + Enable or disable the microcode minimal revision + enforcement for the runtime microcode loader. + min_addr=nn[KMG] [KNL,BOOT,IA-64] All physical memory below this physical address is ignored. diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c46ebd1..d8ff206 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1322,7 +1322,28 @@ config MICROCODE_LATE_LOADING is a tricky business and should be avoided if possible. Just the sequence of synchronizing all cores and SMT threads is one fragile dance which does not guarantee that cores might not softlock after the loading. Therefore, - use this at your own risk. Late loading taints the kernel too. + use this at your own risk. Late loading taints the kernel unless the + microcode header indicates that it is safe for late loading via the + minimal revision check. This minimal revision check can be enforced on + the kernel command line with "microcode.minrev=Y". + +config MICROCODE_LATE_FORCE_MINREV + bool "Enforce late microcode loading minimal revision check" + default n + depends on MICROCODE_LATE_LOADING + help + To prevent that users load microcode late which modifies already + in use features, newer microcode patches have a minimum revision field + in the microcode header, which tells the kernel which minimum + revision must be active in the CPU to safely load that new microcode + late into the running system. If disabled the check will not + be enforced but the kernel will be tainted when the minimal + revision check fails. + + This minimal revision check can also be controlled via the + "microcode.minrev" parameter on the kernel command line. + + If unsure say Y. config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index a760e13..a2776f2 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -880,6 +880,9 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device) enum ucode_state ret = UCODE_NFOUND; const struct firmware *fw; + if (force_minrev) + return UCODE_NFOUND; + if (c->x86 >= 0x15) snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index a9c373b..591032b 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -46,6 +46,9 @@ static struct microcode_ops *microcode_ops; static bool dis_ucode_ldr = true; +bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV); +module_param(force_minrev, bool, S_IRUSR | S_IWUSR); + bool initrd_gone; /* @@ -560,15 +563,17 @@ static int load_cpus_stopped(void *unused) return 0; } -static int load_late_stop_cpus(void) +static int load_late_stop_cpus(bool is_safe) { unsigned int cpu, updated = 0, failed = 0, timedout = 0, siblings = 0; unsigned int nr_offl, offline = 0; int old_rev = boot_cpu_data.microcode; struct cpuinfo_x86 prev_info; - pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n"); - pr_err("You should switch to early loading, if possible.\n"); + if (!is_safe) { + pr_err("Late microcode loading without minimal revision check.\n"); + pr_err("You should switch to early loading, if possible.\n"); + } atomic_set(&late_cpus_in, num_online_cpus()); atomic_set(&offline_in_nmi, 0); @@ -618,7 +623,9 @@ static int load_late_stop_cpus(void) return -EIO; } - add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); + if (!is_safe || failed || timedout) + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); + pr_info("load: updated on %u primary CPUs with %u siblings\n", updated, siblings); if (failed || timedout) { pr_err("load incomplete. %u CPUs timed out or failed\n", @@ -708,7 +715,9 @@ static int load_late_locked(void) switch (microcode_ops->request_microcode_fw(0, µcode_pdev->dev)) { case UCODE_NEW: - return load_late_stop_cpus(); + return load_late_stop_cpus(false); + case UCODE_NEW_SAFE: + return load_late_stop_cpus(true); case UCODE_NFOUND: return -ENOENT; default: diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 8d03ad5..0e7ff3e 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -471,6 +471,9 @@ static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter) unsigned int curr_mc_size = 0; u8 *new_mc = NULL, *mc = NULL; + if (force_minrev) + return UCODE_NFOUND; + while (iov_iter_count(iter)) { struct microcode_header_intel mc_header; unsigned int mc_size, data_size; diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h index 5e60da8..de37255 100644 --- a/arch/x86/kernel/cpu/microcode/internal.h +++ b/arch/x86/kernel/cpu/microcode/internal.h @@ -13,6 +13,7 @@ struct device; enum ucode_state { UCODE_OK = 0, UCODE_NEW, + UCODE_NEW_SAFE, UCODE_UPDATED, UCODE_NFOUND, UCODE_ERROR, @@ -36,6 +37,8 @@ struct microcode_ops { use_nmi : 1; }; +extern bool force_minrev; + extern struct ucode_cpu_info ucode_cpu_info[]; struct cpio_data find_microcode_in_initrd(const char *path);