[PATCH] x86/pm: Save AMD CPUID leaf 7 across S3

Sean Rhodes <[email protected]>
Newsgroups org.kernel.vger.linux-pm,org.kernel.vger.linux-kernel
Message-ID <4430d02d34617dd2d3cb506202fe44d5e45c053b.1785838418.git.sean@starlabs.systems>
Some AMD systems return from S3 with the boot CPU CPUID leaf 7
override MSR reset. On Byte/Cezanne, CPUID leaf 7 EBX becomes
0x219c9fb9 on CPU0 after S3 even though XTEST still raises #UD.
Userspace can then select RTM-optimised glibc paths and fault after
resume.

The x86 suspend code already has a small MSR save/restore list for
firmware-modified MSRs and restores it after resume microcode has been
loaded. Add MSR_AMD64_CPUID_FN_7 for the AMD families that can modify
this MSR during CPU init so the pre-suspend CPUID mask is restored
before tasks are thawed.

This covers family 17h, 19h, and 1Ah: family 17h has the Cyan Skillfish
RDSEED leaf-7 quirk, family 19h covers the observed Cezanne issue, and
family 1Ah has the Zen5 RDSEED leaf-7 quirk.

Tested on StarBook Mk V (Byte/Cezanne, 26.07 firmware):
- without this restore, dmesg showed "ACPI: PM: Low-level resume complete"
  and "PM: suspend exit"; the post-S3 CPUID probe showed CPU0 leaf 7 EBX
  0x219c9fb9 with hle=1 rtm=1 while XTEST still raised #UD.
- a temporary PM resume hook clearing the same MSR logged
  "CPU0 MSR_AMD64_CPUID_FN_7 0x219c9fb9 -> 0x219c97a9"; the post-S3 probe
  showed hle=0 rtm=0 on all CPUs.
- this patch booted on Byte and registered the MSR save path; dmesg showed
  "x86/pm: AMD family 0x19 CPU detected"; pm_test freezer/devices/platform/
  processors/core passed with the same boot ID.

Tested-by: Sean Rhodes <[email protected]>
Signed-off-by: Sean Rhodes <[email protected]>
---
 arch/x86/power/cpu.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 702f30eaf9c4..b85061f4cee4 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -467,9 +467,24 @@ static int msr_save_cpuid_features(const struct x86_cpu_id *c)
 	return msr_build_context(cpuid_msr_id, ARRAY_SIZE(cpuid_msr_id));
 }
 
+static int msr_save_amd_leaf7_cpuid_features(const struct x86_cpu_id *c)
+{
+	u32 cpuid_msr_id[] = {
+		MSR_AMD64_CPUID_FN_7,
+	};
+
+	pr_info("x86/pm: AMD family %#x CPU detected, saving CPUID leaf 7 MSR across suspend.\n",
+		c->family);
+
+	return msr_build_context(cpuid_msr_id, ARRAY_SIZE(cpuid_msr_id));
+}
+
 static const struct x86_cpu_id msr_save_cpu_table[] = {
 	X86_MATCH_VENDOR_FAM(AMD, 0x15, &msr_save_cpuid_features),
 	X86_MATCH_VENDOR_FAM(AMD, 0x16, &msr_save_cpuid_features),
+	X86_MATCH_VENDOR_FAM(AMD, 0x17, &msr_save_amd_leaf7_cpuid_features),
+	X86_MATCH_VENDOR_FAM(AMD, 0x19, &msr_save_amd_leaf7_cpuid_features),
+	X86_MATCH_VENDOR_FAM(AMD, 0x1a, &msr_save_amd_leaf7_cpuid_features),
 	{}
 };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.