]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/CPU/AMD: Prevent reset reasons from being retained across reboot
authorRong Zhang <i@rong.moe>
Fri, 10 Oct 2025 16:59:58 +0000 (00:59 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Oct 2025 14:24:21 +0000 (16:24 +0200)
commit e6416c2dfe23c9a6fec881fda22ebb9ae486cfc5 upstream.

The S5_RESET_STATUS register is parsed on boot and printed to kmsg.
However, this could sometimes be misleading and lead to users wasting a
lot of time on meaningless debugging for two reasons:

* Some bits are never cleared by hardware. It's the software's
responsibility to clear them as per the Processor Programming Reference
(see [1]).

* Some rare hardware-initiated platform resets do not update the
register at all.

In both cases, a previous reboot could leave its trace in the register,
resulting in users seeing unrelated reboot reasons while debugging random
reboots afterward.

Write the read value back to the register in order to clear all reason bits
since they are write-1-to-clear while the others must be preserved.

  [1]: https://bugzilla.kernel.org/show_bug.cgi?id=206537#attach_303991

  [ bp: Massage commit message. ]

Fixes: ab8131028710 ("x86/CPU/AMD: Print the reason for the last reset")
Signed-off-by: Rong Zhang <i@rong.moe>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Yazen Ghannam <yazen.ghannam@amd.com>
Cc: <stable@kernel.org>
Link: https://lore.kernel.org/all/20250913144245.23237-1-i@rong.moe/
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/kernel/cpu/amd.c

index a6f88ca1a6b495282e9284727bf043cbb8741d59..a11e17f3b4b1b697d2ad93ea2567caaf541153b3 100644 (file)
@@ -1338,11 +1338,23 @@ static __init int print_s5_reset_status_mmio(void)
                return 0;
 
        value = ioread32(addr);
-       iounmap(addr);
 
        /* Value with "all bits set" is an error response and should be ignored. */
-       if (value == U32_MAX)
+       if (value == U32_MAX) {
+               iounmap(addr);
                return 0;
+       }
+
+       /*
+        * Clear all reason bits so they won't be retained if the next reset
+        * does not update the register. Besides, some bits are never cleared by
+        * hardware so it's software's responsibility to clear them.
+        *
+        * Writing the value back effectively clears all reason bits as they are
+        * write-1-to-clear.
+        */
+       iowrite32(value, addr);
+       iounmap(addr);
 
        for (i = 0; i < ARRAY_SIZE(s5_reset_reason_txt); i++) {
                if (!(value & BIT(i)))