git: 5fb3aea2d8c4 - main - linuxkpi: Add x86 CPU ID matching functions and macros
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 14 Sep 2026 20:12:14 UTC
The branch main has been updated by dumbbell:
URL: https://cgit.FreeBSD.org/src/commit/?id=5fb3aea2d8c436afa87605d8d7798ae8b09d558c
commit 5fb3aea2d8c436afa87605d8d7798ae8b09d558c
Author: Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
AuthorDate: 2026-06-17 14:01:05 +0000
Commit: Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
CommitDate: 2026-09-14 20:06:50 +0000
linuxkpi: Add x86 CPU ID matching functions and macros
There are two parts that go together:
* `X86_MATCH_VFM()` to declare a matching pattern
* `x86_match_cpu()` to check if the current CPU matches one of the
patterns in an array.
The i915 DRM driver started to use this in Linux 6.14.
Reviewed by: kib
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D57700
---
.../linuxkpi/common/include/asm/cpu_device_id.h | 25 +++++++++++++++
sys/compat/linuxkpi/common/include/linux/bits.h | 2 ++
.../common/include/linux/mod_devicetable.h | 17 ++++++++++
sys/compat/linuxkpi/common/src/linux_compat.c | 37 ++++++++++++++++++++++
4 files changed, 81 insertions(+)
diff --git a/sys/compat/linuxkpi/common/include/asm/cpu_device_id.h b/sys/compat/linuxkpi/common/include/asm/cpu_device_id.h
index a01d63a75a7e..5741cddd52b1 100644
--- a/sys/compat/linuxkpi/common/include/asm/cpu_device_id.h
+++ b/sys/compat/linuxkpi/common/include/asm/cpu_device_id.h
@@ -7,6 +7,8 @@
#ifndef _LINUXKPI_ASM_CPU_DEVICE_ID_H_
#define _LINUXKPI_ASM_CPU_DEVICE_ID_H_
+#include <linux/bits.h>
+
#define VFM_MODEL_BIT 0
#define VFM_FAMILY_BIT 8
#define VFM_VENDOR_BIT 16
@@ -30,4 +32,27 @@
#include <asm/intel-family.h>
#include <asm/processor.h>
+#define X86_CPU_ID_FLAG_ENTRY_VALID BIT(0)
+
+#define X86_MATCH_VENDORID_FAM_MODEL_STEPPINGS_FEATURE( \
+ _vendor, _family, _model, _steppings, _feature) { \
+ .vendor = _vendor, \
+ .family = _family, \
+ .model = _model, \
+ .steppings = _steppings, \
+ .feature = _feature, \
+ .flags = X86_CPU_ID_FLAG_ENTRY_VALID, \
+}
+
+#define X86_MATCH_VFM(_vfm, _data) \
+ X86_MATCH_VENDORID_FAM_MODEL_STEPPINGS_FEATURE( \
+ VFM_VENDOR(_vfm), \
+ VFM_FAMILY(_vfm), \
+ VFM_MODEL(_vfm), \
+ X86_STEPPING_ANY, \
+ X86_FEATURE_ANY)
+
+const struct x86_cpu_id *linuxkpi_x86_match_cpu(const struct x86_cpu_id *match_array);
+#define x86_match_cpu(match_array) linuxkpi_x86_match_cpu(match_array)
+
#endif /* _LINUXKPI_ASM_CPU_DEVICE_ID_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/bits.h b/sys/compat/linuxkpi/common/include/linux/bits.h
index 53deb7cbbe88..f5e688cdb7c0 100644
--- a/sys/compat/linuxkpi/common/include/linux/bits.h
+++ b/sys/compat/linuxkpi/common/include/linux/bits.h
@@ -8,6 +8,8 @@
#ifndef _LINUXKPI_LINUX_BITS_H_
#define _LINUXKPI_LINUX_BITS_H_
+#include <linux/bitops.h>
+
#define GENMASK(h, l) (((~0UL) >> (BITS_PER_LONG - (h) - 1)) & ((~0UL) << (l)))
#define GENMASK_ULL(h, l) (((~0ULL) >> (BITS_PER_LONG_LONG - (h) - 1)) & ((~0ULL) << (l)))
diff --git a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h
index b345b98325e1..e015bde5061e 100644
--- a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h
+++ b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h
@@ -81,6 +81,23 @@ struct dmi_system_id {
#define ACPI_ID_LEN 16
+struct x86_cpu_id {
+ uint16_t vendor;
+ uint16_t family;
+ uint16_t model;
+ uint16_t steppings;
+ uint16_t feature;
+ uint16_t flags;
+};
+
+#define X86_VENDOR_ANY 0xffff
+#define X86_FAMILY_ANY 0
+#define X86_MODEL_ANY 0
+#define X86_STEPPING_ANY 0
+#define X86_STEP_MIN 0
+#define X86_STEP_MAX 0xf
+#define X86_FEATURE_ANY 0
+
/* -----------------------------------------------------------------------------
* USB
*/
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index 8fb09d5914fb..3cdeb8e2d297 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -100,8 +100,11 @@
#include <linux/printk.h>
#include <linux/seq_file.h>
#include <linux/uuid.h>
+#include <linux/mod_devicetable.h>
#if defined(__i386__) || defined(__amd64__)
+#include <asm/cpu_device_id.h>
+#include <asm/cpufeature.h>
#include <asm/smp.h>
#include <asm/processor.h>
#endif
@@ -3084,6 +3087,40 @@ linux_compat_uninit(void *arg)
}
SYSUNINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_uninit, NULL);
+const struct x86_cpu_id *
+linuxkpi_x86_match_cpu(const struct x86_cpu_id *match_array)
+{
+ const struct x86_cpu_id *match;
+
+ for (match = match_array;
+ (match->flags & X86_CPU_ID_FLAG_ENTRY_VALID) != 0;
+ match++) {
+ if (match->vendor != X86_VENDOR_ANY &&
+ match->vendor != boot_cpu_data.x86_vendor)
+ continue;
+
+ if (match->family != X86_FAMILY_ANY &&
+ match->family != boot_cpu_data.x86)
+ continue;
+
+ if (match->model != X86_MODEL_ANY &&
+ match->model != boot_cpu_data.x86_model)
+ continue;
+
+ if (match->model != X86_STEPPING_ANY &&
+ (match->steppings & BIT(boot_cpu_data.x86_stepping)) == 0)
+ continue;
+
+ if (match->feature != X86_FEATURE_ANY &&
+ !static_cpu_has(match->feature))
+ continue;
+
+ return (match);
+ }
+
+ return (NULL);
+}
+
/*
* NOTE: Linux frequently uses "unsigned long" for pointer to integer
* conversion and vice versa, where in FreeBSD "uintptr_t" would be