[PATCH v1 2/2] x86/amd_node: reject SMN access when amd_smn_init() did not complete

From: Penny Zheng

Date: Wed May 06 2026 - 01:57:29 EST


amd_smn_init() can fail early (e.g. -ENODEV when num_roots < num_nodes,
-ENOMEM from kcalloc) without setting smn_exclusive. In that case
amd_roots stays NULL, but the existing __amd_smn_rw() ordering dereferenced
amd_roots[node] before the smn_exclusive guard. The first SMN consumer (e.g.
amd_pmc_probe -> amd_smn_read) then hit a NULL pointer dereference
instead of getting -ENODEV.

Move the smn_exclusive check to the very beginning of __amd_smn_rw()
so a failed init is rejected before any deref. Also zero *value in
amd_smn_read() on the error path so callers never read uninitialized
data via the subsequent PCI_POSSIBLE_ERROR() check.

Signed-off-by: Penny Zheng <penny.zheng@xxxxxxx>
---
arch/x86/kernel/amd_node.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c
index c896060fe0df..cb9ed022c53c 100644
--- a/arch/x86/kernel/amd_node.c
+++ b/arch/x86/kernel/amd_node.c
@@ -88,6 +88,9 @@ static int __amd_smn_rw(u8 i_off, u8 d_off, u16 node, u32 address, u32 *value, b
struct pci_dev *root;
int err = -ENODEV;

+ if (!smn_exclusive)
+ return err;
+
if (node >= amd_num_nodes())
return err;

@@ -95,9 +98,6 @@ static int __amd_smn_rw(u8 i_off, u8 d_off, u16 node, u32 address, u32 *value, b
if (!root)
return err;

- if (!smn_exclusive)
- return err;
-
guard(mutex)(&smn_mutex);

err = pci_write_config_dword(root, i_off, address);
@@ -116,6 +116,11 @@ int __must_check amd_smn_read(u16 node, u32 address, u32 *value)
{
int err = __amd_smn_rw(SMN_INDEX_OFFSET, SMN_DATA_OFFSET, node, address, value, false);

+ if (err) {
+ *value = 0;
+ return err;
+ }
+
if (PCI_POSSIBLE_ERROR(*value)) {
err = -ENODEV;
*value = 0;
--
2.43.0