History

Merge tag 'x86-urgent-2025-11-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar: - Fix AMD PCI root device caching regression that triggers on certain firmware variants - Fix the zen5_rdseed_microcode[] array to be NULL-terminated - Add more AMD models to microcode signature checking * tag 'x86-urgent-2025-11-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/microcode/AMD: Add more known models to entry sign checking x86/CPU/AMD: Add missing terminator for zen5_rdseed_microcode x86/amd_node: Fix AMD root device caching

Linus Torvalds committed 1 year ago

Commit 0d7bee12 parents b5c0946 d23550e4 files · +54 −100Browse files

Unified · Split

4 files
  1. arch/x86/include/asm/amd/node.h +0 −1
  2. arch/x86/kernel/amd_node.c +51 −99
  3. arch/x86/kernel/cpu/amd.c +1 −0
  4. arch/x86/kernel/cpu/microcode/amd.c +2 −0
arch/x86/include/asm/amd/node.h+0−1
@@ -23,7 +23,6 @@ · 22 unmodified lines
23#define AMD_NODE0_PCI_SLOT 0x1823#define AMD_NODE0_PCI_SLOT 0x18
24 24
25struct pci_dev *amd_node_get_func(u16 node, u8 func);25struct pci_dev *amd_node_get_func(u16 node, u8 func);
26struct pci_dev *amd_node_get_root(u16 node);
27 26
28static inline u16 amd_num_nodes(void)27static inline u16 amd_num_nodes(void)
29{28{
arch/x86/kernel/amd_node.c+51−99
@@ -34,62 +34,6 @@ struct pci_dev *amd_node_get_func(u16 node, u8 func) · 33 unmodified lines
34 return pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(AMD_NODE0_PCI_SLOT + node, func));34 return pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(AMD_NODE0_PCI_SLOT + node, func));
35}35}
36 36
37#define DF_BLK_INST_CNT 0x040
38#define DF_CFG_ADDR_CNTL_LEGACY 0x084
39#define DF_CFG_ADDR_CNTL_DF4 0xC04
40
41#define DF_MAJOR_REVISION GENMASK(27, 24)
42
43static u16 get_cfg_addr_cntl_offset(struct pci_dev *df_f0)
44{
45 u32 reg;
46
47 /*
48 * Revision fields added for DF4 and later.
49 *
50 * Major revision of '0' is found pre-DF4. Field is Read-as-Zero.
51 */
52 if (pci_read_config_dword(df_f0, DF_BLK_INST_CNT, &reg))
53 return 0;
54
55 if (reg & DF_MAJOR_REVISION)
56 return DF_CFG_ADDR_CNTL_DF4;
57
58 return DF_CFG_ADDR_CNTL_LEGACY;
59}
60
61struct pci_dev *amd_node_get_root(u16 node)
62{
63 struct pci_dev *root;
64 u16 cntl_off;
65 u8 bus;
66
67 if (!cpu_feature_enabled(X86_FEATURE_ZEN))
68 return NULL;
69
70 /*
71 * D18F0xXXX [Config Address Control] (DF::CfgAddressCntl)
72 * Bits [7:0] (SecBusNum) holds the bus number of the root device for
73 * this Data Fabric instance. The segment, device, and function will be 0.
74 */
75 struct pci_dev *df_f0 __free(pci_dev_put) = amd_node_get_func(node, 0);
76 if (!df_f0)
77 return NULL;
78
79 cntl_off = get_cfg_addr_cntl_offset(df_f0);
80 if (!cntl_off)
81 return NULL;
82
83 if (pci_read_config_byte(df_f0, cntl_off, &bus))
84 return NULL;
85
86 /* Grab the pointer for the actual root device instance. */
87 root = pci_get_domain_bus_and_slot(0, bus, 0);
88
89 pci_dbg(root, "is root for AMD node %u\n", node);
90 return root;
91}
92
93static struct pci_dev **amd_roots;37static struct pci_dev **amd_roots;
94 38
95/* Protect the PCI config register pairs used for SMN. */39/* Protect the PCI config register pairs used for SMN. */
@@ -274,51 +218,21 @@ DEFINE_SHOW_STORE_ATTRIBUTE(smn_node); · 178 unmodified lines
274DEFINE_SHOW_STORE_ATTRIBUTE(smn_address);218DEFINE_SHOW_STORE_ATTRIBUTE(smn_address);
275DEFINE_SHOW_STORE_ATTRIBUTE(smn_value);219DEFINE_SHOW_STORE_ATTRIBUTE(smn_value);
276 220
277static int amd_cache_roots(void)221static struct pci_dev *get_next_root(struct pci_dev *root)
278{
279 u16 node, num_nodes = amd_num_nodes();
280
281 amd_roots = kcalloc(num_nodes, sizeof(*amd_roots), GFP_KERNEL);
282 if (!amd_roots)
283 return -ENOMEM;
284
285 for (node = 0; node < num_nodes; node++)
286 amd_roots[node] = amd_node_get_root(node);
287
288 return 0;
289}
290
291static int reserve_root_config_spaces(void)
292{222{
293 struct pci_dev *root = NULL;223 while ((root = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, root))) {
294 struct pci_bus *bus = NULL;224 /* Root device is Device 0 Function 0. */
295 225 if (root->devfn)
296 while ((bus = pci_find_next_bus(bus))) {
297 /* Root device is Device 0 Function 0 on each Primary Bus. */
298 root = pci_get_slot(bus, 0);
299 if (!root)
300 continue;226 continue;
301 227
302 if (root->vendor != PCI_VENDOR_ID_AMD &&228 if (root->vendor != PCI_VENDOR_ID_AMD &&
303 root->vendor != PCI_VENDOR_ID_HYGON)229 root->vendor != PCI_VENDOR_ID_HYGON)
304 continue;230 continue;
305 231
306 pci_dbg(root, "Reserving PCI config space\n");232 break;
307
308 /*
309 * There are a few SMN index/data pairs and other registers
310 * that shouldn't be accessed by user space.
311 * So reserve the entire PCI config space for simplicity rather
312 * than covering specific registers piecemeal.
313 */
314 if (!pci_request_config_region_exclusive(root, 0, PCI_CFG_SPACE_SIZE, NULL)) {
315 pci_err(root, "Failed to reserve config space\n");
316 return -EEXIST;
317 }
318 }233 }
319 234
320 smn_exclusive = true;235 return root;
321 return 0;
322}236}
323 237
324static bool enable_dfs;238static bool enable_dfs;
@@ -332,7 +246,8 @@ __setup("amd_smn_debugfs_enable", amd_smn_enable_dfs); · 7 unmodified lines
332 246
333static int __init amd_smn_init(void)247static int __init amd_smn_init(void)
334{248{
335 int err;249 u16 count, num_roots, roots_per_node, node, num_nodes;
250 struct pci_dev *root;
336 251
337 if (!cpu_feature_enabled(X86_FEATURE_ZEN))252 if (!cpu_feature_enabled(X86_FEATURE_ZEN))
338 return 0;253 return 0;
@@ -342,13 +257,48 @@ static int __init amd_smn_init(void) · 3 unmodified lines
342 if (amd_roots)257 if (amd_roots)
343 return 0;258 return 0;
344 259
345 err = amd_cache_roots();260 num_roots = 0;
346 if (err)261 root = NULL;
347 return err;262 while ((root = get_next_root(root))) {
263 pci_dbg(root, "Reserving PCI config space\n");
348 264
349 err = reserve_root_config_spaces();265 /*
350 if (err)266 * There are a few SMN index/data pairs and other registers
351 return err;267 * that shouldn't be accessed by user space. So reserve the
268 * entire PCI config space for simplicity rather than covering
269 * specific registers piecemeal.
270 */
271 if (!pci_request_config_region_exclusive(root, 0, PCI_CFG_SPACE_SIZE, NULL)) {
272 pci_err(root, "Failed to reserve config space\n");
273 return -EEXIST;
274 }
275
276 num_roots++;
277 }
278
279 pr_debug("Found %d AMD root devices\n", num_roots);
280
281 if (!num_roots)
282 return -ENODEV;
283
284 num_nodes = amd_num_nodes();
285 amd_roots = kcalloc(num_nodes, sizeof(*amd_roots), GFP_KERNEL);
286 if (!amd_roots)
287 return -ENOMEM;
288
289 roots_per_node = num_roots / num_nodes;
290
291 count = 0;
292 node = 0;
293 root = NULL;
294 while (node < num_nodes && (root = get_next_root(root))) {
295 /* Use one root for each node and skip the rest. */
296 if (count++ % roots_per_node)
297 continue;
298
299 pci_dbg(root, "is root for AMD node %u\n", node);
300 amd_roots[node++] = root;
301 }
352 302
353 if (enable_dfs) {303 if (enable_dfs) {
354 debugfs_dir = debugfs_create_dir("amd_smn", arch_debugfs_dir);304 debugfs_dir = debugfs_create_dir("amd_smn", arch_debugfs_dir);
@@ -358,6 +308,8 @@ static int __init amd_smn_init(void) · 3 unmodified lines
358 debugfs_create_file("value", 0600, debugfs_dir, NULL, &smn_value_fops);308 debugfs_create_file("value", 0600, debugfs_dir, NULL, &smn_value_fops);
359 }309 }
360 310
311 smn_exclusive = true;
312
361 return 0;313 return 0;
362}314}
363 315
arch/x86/kernel/cpu/amd.c+1−0
@@ -1038,6 +1038,7 @@ static void init_amd_zen4(struct cpuinfo_x86 *c) · 1037 unmodified lines
1038static const struct x86_cpu_id zen5_rdseed_microcode[] = {1038static const struct x86_cpu_id zen5_rdseed_microcode[] = {
1039 ZEN_MODEL_STEP_UCODE(0x1a, 0x02, 0x1, 0x0b00215a),1039 ZEN_MODEL_STEP_UCODE(0x1a, 0x02, 0x1, 0x0b00215a),
1040 ZEN_MODEL_STEP_UCODE(0x1a, 0x11, 0x0, 0x0b101054),1040 ZEN_MODEL_STEP_UCODE(0x1a, 0x11, 0x0, 0x0b101054),
1041 {},
1041};1042};
1042 1043
1043static void init_amd_zen5(struct cpuinfo_x86 *c)1044static void init_amd_zen5(struct cpuinfo_x86 *c)
arch/x86/kernel/cpu/microcode/amd.c+2−0
@@ -220,10 +220,12 @@ static bool need_sha_check(u32 cur_rev) · 219 unmodified lines
220 case 0xaa001: return cur_rev <= 0xaa00116; break;220 case 0xaa001: return cur_rev <= 0xaa00116; break;
221 case 0xaa002: return cur_rev <= 0xaa00218; break;221 case 0xaa002: return cur_rev <= 0xaa00218; break;
222 case 0xb0021: return cur_rev <= 0xb002146; break;222 case 0xb0021: return cur_rev <= 0xb002146; break;
223 case 0xb0081: return cur_rev <= 0xb008111; break;
223 case 0xb1010: return cur_rev <= 0xb101046; break;224 case 0xb1010: return cur_rev <= 0xb101046; break;
224 case 0xb2040: return cur_rev <= 0xb204031; break;225 case 0xb2040: return cur_rev <= 0xb204031; break;
225 case 0xb4040: return cur_rev <= 0xb404031; break;226 case 0xb4040: return cur_rev <= 0xb404031; break;
226 case 0xb6000: return cur_rev <= 0xb600031; break;227 case 0xb6000: return cur_rev <= 0xb600031; break;
228 case 0xb6080: return cur_rev <= 0xb608031; break;
227 case 0xb7000: return cur_rev <= 0xb700031; break;229 case 0xb7000: return cur_rev <= 0xb700031; break;
228 default: break;230 default: break;
229 }231 }