x86/cpu/vfm: Add new macros to work with (vendor/family/model) values
authorTony Luck <tony.luck@intel.com>
Tue, 16 Apr 2024 21:19:04 +0000 (14:19 -0700)
committerBorislav Petkov (AMD) <bp@alien8.de>
Mon, 22 Apr 2024 09:43:55 +0000 (11:43 +0200)
To avoid adding a slew of new macros for each new Intel CPU family
switch over from providing CPU model number #defines to a new
scheme that encodes vendor, family, and model in a single number.

  [ bp: s/casted/cast/g ]

Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240416211941.9369-3-tony.luck@intel.com
arch/x86/include/asm/cpu_device_id.h

index bf4e065cf1e2fc0f2a05bdf56e8d282a2ef57d86..970a232009c3064056b6e09416e11c923e3d8493 100644 (file)
@@ -2,6 +2,39 @@
 #ifndef _ASM_X86_CPU_DEVICE_ID
 #define _ASM_X86_CPU_DEVICE_ID
 
+/*
+ * Can't use <linux/bitfield.h> because it generates expressions that
+ * cannot be used in structure initializers. Bitfield construction
+ * here must match the union in struct cpuinfo_86:
+ *     union {
+ *             struct {
+ *                     __u8    x86_model;
+ *                     __u8    x86;
+ *                     __u8    x86_vendor;
+ *                     __u8    x86_reserved;
+ *             };
+ *             __u32           x86_vfm;
+ *     };
+ */
+#define VFM_MODEL_BIT  0
+#define VFM_FAMILY_BIT 8
+#define VFM_VENDOR_BIT 16
+#define VFM_RSVD_BIT   24
+
+#define        VFM_MODEL_MASK  GENMASK(VFM_FAMILY_BIT - 1, VFM_MODEL_BIT)
+#define        VFM_FAMILY_MASK GENMASK(VFM_VENDOR_BIT - 1, VFM_FAMILY_BIT)
+#define        VFM_VENDOR_MASK GENMASK(VFM_RSVD_BIT - 1, VFM_VENDOR_BIT)
+
+#define VFM_MODEL(vfm) (((vfm) & VFM_MODEL_MASK) >> VFM_MODEL_BIT)
+#define VFM_FAMILY(vfm)        (((vfm) & VFM_FAMILY_MASK) >> VFM_FAMILY_BIT)
+#define VFM_VENDOR(vfm)        (((vfm) & VFM_VENDOR_MASK) >> VFM_VENDOR_BIT)
+
+#define        VFM_MAKE(_vendor, _family, _model) (    \
+       ((_model) << VFM_MODEL_BIT) |           \
+       ((_family) << VFM_FAMILY_BIT) |         \
+       ((_vendor) << VFM_VENDOR_BIT)           \
+)
+
 /*
  * Declare drivers belonging to specific x86 CPUs
  * Similar in spirit to pci_device_id and related PCI functions
        .driver_data    = (unsigned long) _data                         \
 }
 
+#define X86_MATCH_VENDORID_FAM_MODEL_STEPPINGS_FEATURE(_vendor, _family, _model, \
+                                                   _steppings, _feature, _data) { \
+       .vendor         = _vendor,                                      \
+       .family         = _family,                                      \
+       .model          = _model,                                       \
+       .steppings      = _steppings,                                   \
+       .feature        = _feature,                                     \
+       .driver_data    = (unsigned long) _data                         \
+}
+
 /**
  * X86_MATCH_VENDOR_FAM_MODEL_FEATURE - Macro for CPU matching
  * @_vendor:   The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
        X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6, INTEL_FAM6_##model, \
                                                     steppings, X86_FEATURE_ANY, data)
 
+/**
+ * X86_MATCH_VFM - Match encoded vendor/family/model
+ * @vfm:       Encoded 8-bits each for vendor, family, model
+ * @data:      Driver specific data or NULL. The internal storage
+ *             format is unsigned long. The supplied value, pointer
+ *             etc. is cast to unsigned long internally.
+ *
+ * Stepping and feature are set to wildcards
+ */
+#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, data)
+
+/**
+ * X86_MATCH_VFM_STEPPINGS - Match encoded vendor/family/model/stepping
+ * @vfm:       Encoded 8-bits each for vendor, family, model
+ * @steppings: Bitmask of steppings to match
+ * @data:      Driver specific data or NULL. The internal storage
+ *             format is unsigned long. The supplied value, pointer
+ *             etc. is cast to unsigned long internally.
+ *
+ * feature is set to wildcard
+ */
+#define X86_MATCH_VFM_STEPPINGS(vfm, steppings, data)  \
+       X86_MATCH_VENDORID_FAM_MODEL_STEPPINGS_FEATURE( \
+               VFM_VENDOR(vfm),                        \
+               VFM_FAMILY(vfm),                        \
+               VFM_MODEL(vfm),                         \
+               steppings, X86_FEATURE_ANY, data)
+
+/**
+ * X86_MATCH_VFM_FEATURE - Match encoded vendor/family/model/feature
+ * @vfm:       Encoded 8-bits each for vendor, family, model
+ * @feature:   A X86_FEATURE bit
+ * @data:      Driver specific data or NULL. The internal storage
+ *             format is unsigned long. The supplied value, pointer
+ *             etc. is cast to unsigned long internally.
+ *
+ * Steppings is set to wildcard
+ */
+#define X86_MATCH_VFM_FEATURE(vfm, feature, data)      \
+       X86_MATCH_VENDORID_FAM_MODEL_STEPPINGS_FEATURE( \
+               VFM_VENDOR(vfm),                        \
+               VFM_FAMILY(vfm),                        \
+               VFM_MODEL(vfm),                         \
+               X86_STEPPING_ANY, feature, data)
+
 /*
  * Match specific microcode revisions.
  *