On a Xen dom0 boot, this feature does not behave, and we end up calculating:
num_roots = 1 num_nodes = 2 roots_per_node = 0
This causes a divide-by-zero in the modulus inside the loop.
This change adds a couple of guards for invalid states where we might get a divide-by-zero.
Signed-off-by: Steven Noonan steven@uplinklabs.net Signed-off-by: Ariadne Conill ariadne@ariadne.space CC: Yazen Ghannam yazen.ghannam@amd.com CC: x86@vger.kernel.org CC: stable@vger.kernel.org --- arch/x86/kernel/amd_node.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c index 3d0a4768d603c..cdc6ba224d4ad 100644 --- a/arch/x86/kernel/amd_node.c +++ b/arch/x86/kernel/amd_node.c @@ -282,6 +282,17 @@ static int __init amd_smn_init(void) return -ENODEV;
num_nodes = amd_num_nodes(); + + if (!num_nodes) + return -ENODEV; + + /* Possibly a virtualized environment (e.g. Xen) where we wi ll get + * roots_per_node=0 if the number of roots is fewer than number of + * nodes + */ + if (num_roots < num_nodes) + return -ENODEV; + amd_roots = kcalloc(num_nodes, sizeof(*amd_roots), GFP_KERNEL); if (!amd_roots) return -ENOMEM;
We should be checking the `smn_exclusive` flag before anything else, because that indicates whether we got through `amd_smn_init` successfully.
Without this change, we dereference `amd_roots` even though it may not be allocated.
Signed-off-by: Steven Noonan steven@uplinklabs.net Signed-off-by: Ariadne Conill ariadne@ariadne.space CC: Yazen Ghannam yazen.ghannam@amd.com CC: x86@vger.kernel.org CC: stable@vger.kernel.org --- arch/x86/kernel/amd_node.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c index cdc6ba224d4ad..919932339f4a2 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_s mn_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);
linux-stable-mirror@lists.linaro.org