From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9FCEC283FFB for ; Wed, 8 Jul 2026 21:43:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783547040; cv=none; b=oX0lmwdTsAXaZPSyFZ4WBDGzLpnzJp5IwlbqKf6+kTKq8UsTd3ImPouq2X2lrmYACES50+T3sa6WBHlrSR0q2crLBtRHzFp6iicyWcc76j0wOUDZzFTCBgsUFVAVlox6U0e4b0J6P6TJCL4pfuIFzDSFq32/i7FuEpWXetg3Pzo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783547040; c=relaxed/simple; bh=1djFyZ+1nU9uNGXgpLP6jNaydJsbDeQKO7H5nXYofUQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IFIrLwwnXEP4kBqa/nYV7jkoc6NY8WiaoZWh/r0xgR0sVRyLcdS2Try1jx0m4IAg5OIj/ekKZXsi5zTP0bZt1arBgjd7TZMtW1lnHGr9yoOvTXZI0wPnUveTopL+cvxrDFODdMbXqxuLUcp//EEhuhz/0Cm+2Lg0vdhbZyx9EXA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=funUb0vy; arc=none smtp.client-ip=198.175.65.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="funUb0vy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1783547039; x=1815083039; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1djFyZ+1nU9uNGXgpLP6jNaydJsbDeQKO7H5nXYofUQ=; b=funUb0vy12EJHZoBZKH1n7xzAQJGoaIWrRFlcZ84ovgII2gemoFyR/MP CqebzzMvaexCLJUGzT/eFuniw1WzQYROdSkq8d2VHnGwx5Zggdmn54Yfu 9GkbaEBr9T4r04WKpdE2LPo0lP7NA81Mju8SbaoW4CZMc3xpBXJHEtg2f zxjYjd//lLyQbzycboei+kOiItpxPqD+neIras2uJrqMe3R8Q9lbaJbJk ksJ/Yu8RfLbyugmd7RGQG4Pe9f/B+EIlCkNm6ih1OrJTN1Z28W5tZZKi8 9y5QA0ufE5ZL/m1oZJuTlc01GzWNy5qb2+cTVoPQAPgVIr3FE2ry859Yu Q==; X-CSE-ConnectionGUID: O2DIRmBEQW6clcQyECKFHg== X-CSE-MsgGUID: e6kkOwtsSpOg6dBqhdy7Kw== X-IronPort-AV: E=McAfee;i="6800,10657,11841"; a="84319516" X-IronPort-AV: E=Sophos;i="6.25,153,1779174000"; d="scan'208";a="84319516" Received: from orviesa009.jf.intel.com ([10.64.159.149]) by orvoesa110.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jul 2026 14:43:58 -0700 X-CSE-ConnectionGUID: 8nDTdQu6S+6YfjPt336K4Q== X-CSE-MsgGUID: Eji5LX11QbSG8SY71BcNyg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.25,153,1779174000"; d="scan'208";a="255046749" Received: from chang-linux-3.sc.intel.com (HELO chang-linux-3) ([172.25.66.174]) by orviesa009.jf.intel.com with ESMTP; 08 Jul 2026 14:43:57 -0700 From: "Chang S. Bae" To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@kernel.org, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, hpa@zytor.com, chang.seok.bae@intel.com Subject: [PATCH v2] x86/microcode/intel: Taint kernel on partial update Date: Wed, 8 Jul 2026 21:18:03 +0000 Message-ID: <20260708211803.402467-1-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260630191350.3837-1-chang.seok.bae@intel.com> References: <20260630191350.3837-1-chang.seok.bae@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit A modern individual microcode update contains firmware for many pieces of silicon inside the CPU. Sometimes, a single update operation successfully updates some components and not others leaving a partially-applied update. This may leave the system in an undefined and unreliable state. Fatal failures are expected to be handled by the CPU itself, by raising #MC for example. If the CPU instead reports a partial update, warn and taint the kernel at least. A partial update may still update the revision. Continue checking the revision rather than an immediate error return so the update result remains consistent with the revision changes. Signed-off-by: Chang S. Bae --- V1 -> V2: Do not raise panic, inline cpuid check and massage the changelog (Dave) --- arch/x86/include/asm/msr-index.h | 4 +++ arch/x86/kernel/cpu/microcode/intel.c | 37 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 18c4be75e927..7273d340470d 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -977,6 +977,10 @@ #define MSR_IA32_MCU_ENUMERATION 0x0000007b #define MCU_STAGING BIT(4) +#define MSR_IA32_MCU_STATUS 0x0000007c +#define MCU_PARTIAL_UPDATE BIT(0) +#define AUTH_FAIL_ON_MCU_COMPONENT BIT(1) + #define MSR_IA32_UCODE_REV 0x0000008b /* Intel SGX Launch Enclave Public Key Hash MSRs */ diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index f4a444e6114d..913b0b32e39b 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -69,6 +69,9 @@ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin"; #define MBOX_XACTION_TIMEOUT_MS (10 * MSEC_PER_SEC) +#define CPUID_EDX_ARCH_CAP BIT(29) +#define MCU_STATUS_FAILURE_MASK (MCU_PARTIAL_UPDATE | AUTH_FAIL_ON_MCU_COMPONENT) + /* Current microcode patch used in early patching on the APs. */ static struct microcode_intel *ucode_patch_va __read_mostly; static struct microcode_intel *ucode_patch_late __read_mostly; @@ -679,6 +682,24 @@ static void stage_microcode(void) pr_info("Staging of patch revision 0x%x succeeded.\n", ucode_patch_late->hdr.rev); } +/* + * __apply_microcode() is the only caller which may be invoked in the early + * loading path. Use raw CPUID/RDMSR functions. + */ +static bool update_status_available(void) +{ + if (native_cpuid_eax(0) < 7) + return false; + + if (!(native_cpuid_edx(7) & CPUID_EDX_ARCH_CAP)) + return false; + + if (!(native_rdmsrq(MSR_IA32_ARCH_CAPABILITIES) & ARCH_CAP_MCU_ENUM)) + return false; + + return true; +} + static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci, struct microcode_intel *mc, u32 *cur_rev) @@ -702,6 +723,22 @@ static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci, /* write microcode via MSR 0x79 */ native_wrmsrq(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); + /* + * Warn and taint the kernel on a partial update. Fatal conditions are + * expected to be handled by the CPU itself. + * + * Then, continue checking the revision since a partial update may still + * advance the microcode revision. + */ + if (update_status_available()) { + u64 status = native_rdmsrq(MSR_IA32_MCU_STATUS); + + if (status & MCU_STATUS_FAILURE_MASK) { + pr_warn_once("update incomplete (MSR_IA32_MCU_STATUS=0x%llx).\n", status); + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); + } + } + rev = intel_get_microcode_revision(); if (rev != mc->hdr.rev) return UCODE_ERROR; -- 2.51.0