lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250822004422.2908427-1-sohil.mehta@intel.com>
Date: Thu, 21 Aug 2025 17:44:22 -0700
From: Sohil Mehta <sohil.mehta@...el.com>
To: Dave Hansen <dave.hansen@...ux.intel.com>,
	x86@...nel.org
Cc: Borislav Petkov <bp@...en8.de>,
	Thomas Gleixner <tglx@...utronix.de>,
	Ingo Molnar <mingo@...hat.com>,
	"H . Peter Anvin" <hpa@...or.com>,
	Peter Zijlstra <peterz@...radead.org>,
	Josh Poimboeuf <jpoimboe@...nel.org>,
	Pawan Gupta <pawan.kumar.gupta@...ux.intel.com>,
	Dave Hansen <dave.hansen@...el.com>,
	Nikolay Borisov <nik.borisov@...e.com>,
	Andrew Cooper <andrew.cooper3@...rix.com>,
	Sohil Mehta <sohil.mehta@...el.com>,
	linux-kernel@...r.kernel.org
Subject: [PATCH v2] scripts/x86/intel: Add a script to update the minimum ucode revisions

The kernel maintains a table of minimum expected microcode revisions for
Intel CPUs in intel-ucode-defs.h. Systems with microcode older than
these revisions are flagged with X86_BUG_OLD_MICROCODE. For more
details, refer to Documentation/admin-guide/hw-vuln/old_microcode.rst.

Add a simple script to keep the header file up-to-date based on released
microcode updates.

Originally-by: Dave Hansen <dave.hansen@...ux.intel.com>
Signed-off-by: Sohil Mehta <sohil.mehta@...el.com>
---
v2:
 - Remove the extra command line arguments.
 - Print to stdout instead of directly updating the header file.
 - Take multiple directories as input.

v1: https://lore.kernel.org/lkml/20250818190137.3525414-1-sohil.mehta@intel.com/
---
 MAINTAINERS                        |   1 +
 scripts/update-intel-ucode-defs.py | 118 +++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)
 create mode 100755 scripts/update-intel-ucode-defs.py

diff --git a/MAINTAINERS b/MAINTAINERS
index daf520a13bdf..a819559ec672 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27260,6 +27260,7 @@ S:	Maintained
 F:	Documentation/admin-guide/hw-vuln/
 F:	arch/x86/include/asm/nospec-branch.h
 F:	arch/x86/kernel/cpu/bugs.c
+F:	scripts/update-intel-ucode-defs.py
 
 X86 MCE INFRASTRUCTURE
 M:	Tony Luck <tony.luck@...el.com>
diff --git a/scripts/update-intel-ucode-defs.py b/scripts/update-intel-ucode-defs.py
new file mode 100755
index 000000000000..96e91640033a
--- /dev/null
+++ b/scripts/update-intel-ucode-defs.py
@@ -0,0 +1,118 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: GPL-2.0
+import argparse
+import re
+import shutil
+import subprocess
+import sys
+import os
+
+script = os.path.relpath(__file__)
+
+DESCRIPTION = f"""
+For Intel CPUs, update the microcode revisions that determine
+X86_BUG_OLD_MICROCODE.
+
+The script takes the Intel microcode files as input and uses the
+iucode-tool to extract the revision information. It prints the output in
+the format expected by intel-ucode-defs.h.
+
+A typical usage is to get the desired release of the Intel Microcode
+Update Package at:
+https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files.git
+
+And run:
+    ./{script} /path/to/microcode/files > /path/to/intel-ucode-defs.h
+
+Note: The microcode revisions are usually updated shortly after a new
+microcode package is released, allowing a reasonable time for systems to
+get the update.
+"""
+
+parser = argparse.ArgumentParser(description=DESCRIPTION,
+                                 formatter_class=argparse.RawDescriptionHelpFormatter)
+parser.add_argument('ucode_files', nargs='+', help='Path(s) to the microcode files')
+
+args = parser.parse_args()
+
+# Process the microcode files using iucode-tool
+if shutil.which("iucode-tool") is None:
+    print("Error: iucode-tool not found, please install it", file=sys.stderr)
+    sys.exit(1)
+
+cmd = ['iucode-tool', '--list-all' ]
+cmd.extend(args.ucode_files)
+
+process = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
+process.wait()
+if process.returncode != 0:
+    print("Error: iucode-tool ran into an error, exiting", file=sys.stderr)
+    sys.exit(1)
+
+# Functions to extract family, model, and stepping
+def bits(val, bottom, top):
+    mask = (1 << (top + 1 - bottom)) - 1
+    mask = mask << bottom
+    return (val & mask) >> bottom
+
+def family(sig):
+    if bits(sig, 8, 11) == 0xf:
+        return bits(sig, 8, 11) + bits(sig, 20, 27)
+    return bits(sig, 8, 11)
+
+def model(sig):
+    return bits(sig, 4, 7)  | (bits(sig, 16, 19) << 4)
+
+def step(sig):
+    return bits(sig, 0, 3)
+
+# Parse the output of iucode-tool
+siglist = []
+for line in process.stdout:
+    if line.find(" sig ") == -1:
+        continue
+    sig = re.search('sig (0x[0-9a-fA-F]+)', line).group(1)
+    rev = re.search('rev (0x[0-9a-fA-F]+)', line).group(1)
+    sig = int(sig, 16)
+    rev = int(rev, 16)
+    debug_rev = bits(rev, 31, 31)
+    if debug_rev != 0:
+        print("Error: Debug ucode file found, exiting", file=sys.stderr)
+        sys.exit(1);
+
+    sigrev = {}
+    sigrev['sig'] = sig
+    sigrev['rev'] = rev
+    siglist = siglist + [ sigrev ]
+
+# Remove duplicates, if any
+sigdict = {}
+for sr in siglist:
+    existing = sigdict.get(sr['sig'])
+    if existing != None:
+        # If the existing one is newer, just move on:
+        if existing['rev'] > sr['rev']:
+            continue
+    sigdict[sr['sig']] = sr
+
+# Prepare the microcode entries
+ucode_entries = []
+for sig in sigdict:
+    rev = sigdict[sig]
+    ucode_entries.append({
+        'family': family(sig),
+        'model': model(sig),
+        'steppings': 1 << step(sig),
+        'rev': rev['rev'],
+        'sig': sig
+    })
+
+if not ucode_entries:
+    print("Error: No valid microcode files found, exiting", file=sys.stderr)
+    sys.exit(1)
+
+# Sort and print the microcode entries
+ucode_entries.sort(key=lambda x: (x['family'], x['model'], x['steppings']))
+for entry in ucode_entries:
+    print("{ .flags = X86_CPU_ID_FLAG_ENTRY_VALID, .vendor = X86_VENDOR_INTEL, .family = 0x%x,  .model = 0x%02x, .steppings = 0x%04x, .driver_data = 0x%x }," %
+          (entry['family'], entry['model'], entry['steppings'], entry['rev']))
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ