xref: /linux/Documentation/arch/x86/amd-debugging.rst (revision 785cdec46e9227f9433884ed3b436471e944007c)
1.. SPDX-License-Identifier: GPL-2.0
2
3Debugging AMD Zen systems
4+++++++++++++++++++++++++
5
6Introduction
7============
8
9This document describes techniques that are useful for debugging issues with
10AMD Zen systems.  It is intended for use by developers and technical users
11to help identify and resolve issues.
12
13S3 vs s2idle
14============
15
16On AMD systems, it's not possible to simultaneously support suspend-to-RAM (S3)
17and suspend-to-idle (s2idle).  To confirm which mode your system supports you
18can look at ``cat /sys/power/mem_sleep``.  If it shows ``s2idle [deep]`` then
19*S3* is supported.  If it shows ``[s2idle]`` then *s2idle* is
20supported.
21
22On systems that support *S3*, the firmware will be utilized to put all hardware into
23the appropriate low power state.
24
25On systems that support *s2idle*, the kernel will be responsible for transitioning devices
26into the appropriate low power state. When all devices are in the appropriate low
27power state, the hardware will transition into a hardware sleep state.
28
29After a suspend cycle you can tell how much time was spent in a hardware sleep
30state by looking at ``cat /sys/power/suspend_stats/last_hw_sleep``.
31
32This flowchart explains how the AMD s2idle suspend flow works.
33
34.. kernel-figure:: suspend.svg
35
36This flowchart explains how the amd s2idle resume flow works.
37
38.. kernel-figure:: resume.svg
39
40s2idle debugging tool
41=====================
42
43As there are a lot of places that problems can occur, a debugging tool has been
44created at
45`amd-debug-tools <https://git.kernel.org/pub/scm/linux/kernel/git/superm1/amd-debug-tools.git/about/>`_
46that can help test for common problems and offer suggestions.
47
48If you have an s2idle issue, it's best to start with this and follow instructions
49from its findings.  If you continue to have an issue, raise a bug with the
50report generated from this script to
51`drm/amd gitlab <https://gitlab.freedesktop.org/drm/amd/-/issues/new?issuable_template=s2idle_BUG_TEMPLATE>`_.
52
53Spurious s2idle wakeups from an IRQ
54===================================
55
56Spurious wakeups will generally have an IRQ set to ``/sys/power/pm_wakeup_irq``.
57This can be matched to ``/proc/interrupts`` to determine what device woke the system.
58
59If this isn't enough to debug the problem, then the following sysfs files
60can be set to add more verbosity to the wakeup process: ::
61
62  # echo 1 | sudo tee /sys/power/pm_debug_messages
63  # echo 1 | sudo tee /sys/power/pm_print_times
64
65After making those changes, the kernel will display messages that can
66be traced back to kernel s2idle loop code as well as display any active
67GPIO sources while waking up.
68
69If the wakeup is caused by the ACPI SCI, additional ACPI debugging may be
70needed.  These commands can enable additional trace data: ::
71
72  # echo enable | sudo tee /sys/module/acpi/parameters/trace_state
73  # echo 1 | sudo tee /sys/module/acpi/parameters/aml_debug_output
74  # echo 0x0800000f | sudo tee /sys/module/acpi/parameters/debug_level
75  # echo 0xffff0000 | sudo tee /sys/module/acpi/parameters/debug_layer
76
77Spurious s2idle wakeups from a GPIO
78===================================
79
80If a GPIO is active when waking up the system ideally you would look at the
81schematic to determine what device it is associated with. If the schematic
82is not available, another tactic is to look at the ACPI _EVT() entry
83to determine what device is notified when that GPIO is active.
84
85For a hypothetical example, say that GPIO 59 woke up the system.  You can
86look at the SSDT to determine what device is notified when GPIO 59 is active.
87
88First convert the GPIO number into hex. ::
89
90  $ python3 -c "print(hex(59))"
91  0x3b
92
93Next determine which ACPI table has the ``_EVT`` entry. For example: ::
94
95  $ sudo grep EVT /sys/firmware/acpi/tables/SSDT*
96  grep: /sys/firmware/acpi/tables/SSDT27: binary file matches
97
98Decode this table::
99
100  $ sudo cp /sys/firmware/acpi/tables/SSDT27 .
101  $ sudo iasl -d SSDT27
102
103Then look at the table and find the matching entry for GPIO 0x3b. ::
104
105  Case (0x3B)
106  {
107      M000 (0x393B)
108      M460 ("    Notify (\\_SB.PCI0.GP17.XHC1, 0x02)\n", Zero, Zero, Zero, Zero, Zero, Zero)
109      Notify (\_SB.PCI0.GP17.XHC1, 0x02) // Device Wake
110  }
111
112You can see in this case that the device ``\_SB.PCI0.GP17.XHC1`` is notified
113when GPIO 59 is active. It's obvious this is an XHCI controller, but to go a
114step further you can figure out which XHCI controller it is by matching it to
115ACPI.::
116
117  $ grep "PCI0.GP17.XHC1" /sys/bus/acpi/devices/*/path
118  /sys/bus/acpi/devices/device:2d/path:\_SB_.PCI0.GP17.XHC1
119  /sys/bus/acpi/devices/device:2e/path:\_SB_.PCI0.GP17.XHC1.RHUB
120  /sys/bus/acpi/devices/device:2f/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT1
121  /sys/bus/acpi/devices/device:30/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT1.CAM0
122  /sys/bus/acpi/devices/device:31/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT1.CAM1
123  /sys/bus/acpi/devices/device:32/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT2
124  /sys/bus/acpi/devices/LNXPOWER:0d/path:\_SB_.PCI0.GP17.XHC1.PWRS
125
126Here you can see it matches to ``device:2d``. Look at the ``physical_node``
127to determine what PCI device that actually is. ::
128
129  $ ls -l /sys/bus/acpi/devices/device:2d/physical_node
130  lrwxrwxrwx 1 root root 0 Feb 12 13:22 /sys/bus/acpi/devices/device:2d/physical_node -> ../../../../../pci0000:00/0000:00:08.1/0000:c2:00.4
131
132So there you have it: the PCI device associated with this GPIO wakeup was ``0000:c2:00.4``.
133
134The ``amd_s2idle.py`` script will capture most of these artifacts for you.
135
136s2idle PM debug messages
137========================
138
139During the s2idle flow on AMD systems, the ACPI LPS0 driver is responsible
140to check all uPEP constraints.  Failing uPEP constraints does not prevent
141s0i3 entry.  This means that if some constraints are not met, it is possible
142the kernel may attempt to enter s2idle even if there are some known issues.
143
144To activate PM debugging, either specify ``pm_debug_messagess`` kernel
145command-line option at boot or write to ``/sys/power/pm_debug_messages``.
146Unmet constraints will be displayed in the kernel log and can be
147viewed by logging tools that process kernel ring buffer like ``dmesg`` or
148``journalctl``."
149
150If the system freezes on entry/exit before these messages are flushed, a
151useful debugging tactic is to unbind the ``amd_pmc`` driver to prevent
152notification to the platform to start s0i3 entry.  This will stop the
153system from freezing on entry or exit and let you view all the failed
154constraints. ::
155
156  cd /sys/bus/platform/drivers/amd_pmc
157  ls | grep AMD | sudo tee unbind
158
159After doing this, run the suspend cycle and look specifically for errors around: ::
160
161  ACPI: LPI: Constraint not met; min power state:%s current power state:%s
162
163Historical examples of s2idle issues
164====================================
165
166To help understand the types of issues that can occur and how to debug them,
167here are some historical examples of s2idle issues that have been resolved.
168
169Core offlining
170--------------
171An end user had reported that taking a core offline would prevent the system
172from properly entering s0i3.  This was debugged using internal AMD tools
173to capture and display a stream of metrics from the hardware showing what changed
174when a core was offlined.  It was determined that the hardware didn't get
175notification the offline cores were in the deepest state, and so it prevented
176CPU from going into the deepest state. The issue was debugged to a missing
177command to put cores into C3 upon offline.
178
179`commit d6b88ce2eb9d2 ("ACPI: processor idle: Allow playing dead in C3 state") <https://git.kernel.org/torvalds/c/d6b88ce2eb9d2>`_
180
181Corruption after resume
182-----------------------
183A big problem that occurred with Rembrandt was that there was graphical
184corruption after resume.  This happened because of a misalignment of PSP
185and driver responsibility.  The PSP will save and restore DMCUB, but the
186driver assumed it needed to reset DMCUB on resume.
187This actually was a misalignment for earlier silicon as well, but was not
188observed.
189
190`commit 79d6b9351f086 ("drm/amd/display: Don't reinitialize DMCUB on s0ix resume") <https://git.kernel.org/torvalds/c/79d6b9351f086>`_
191
192Back to Back suspends fail
193--------------------------
194When using a wakeup source that triggers the IRQ to wakeup, a bug in the
195pinctrl-amd driver may capture the wrong state of the IRQ and prevent the
196system going back to sleep properly.
197
198`commit b8c824a869f22 ("pinctrl: amd: Don't save/restore interrupt status and wake status bits") <https://git.kernel.org/torvalds/c/b8c824a869f22>`_
199
200Spurious timer based wakeup after 5 minutes
201-------------------------------------------
202The HPET was being used to program the wakeup source for the system, however
203this was causing a spurious wakeup after 5 minutes.  The correct alarm to use
204was the ACPI alarm.
205
206`commit 3d762e21d5637 ("rtc: cmos: Use ACPI alarm for non-Intel x86 systems too") <https://git.kernel.org/torvalds/c/3d762e21d5637>`_
207
208Disk disappears after resume
209----------------------------
210After resuming from s2idle, the NVME disk would disappear.  This was due to the
211BIOS not specifying the _DSD StorageD3Enable property.  This caused the NVME
212driver not to put the disk into the expected state at suspend and to fail
213on resume.
214
215`commit e79a10652bbd3 ("ACPI: x86: Force StorageD3Enable on more products") <https://git.kernel.org/torvalds/c/e79a10652bbd3>`_
216
217Spurious IRQ1
218-------------
219A number of Renoir, Lucienne, Cezanne, & Barcelo platforms have a
220platform firmware bug where IRQ1 is triggered during s0i3 resume.
221
222This was fixed in the platform firmware, but a number of systems didn't
223receive any more platform firmware updates.
224
225`commit 8e60615e89321 ("platform/x86/amd: pmc: Disable IRQ1 wakeup for RN/CZN") <https://git.kernel.org/torvalds/c/8e60615e89321>`_
226
227Hardware timeout
228----------------
229The hardware performs many actions besides accepting the values from
230amd-pmc driver.  As the communication path with the hardware is a mailbox,
231it's possible that it might not respond quickly enough.
232This issue manifested as a failure to suspend: ::
233
234  PM: dpm_run_callback(): acpi_subsys_suspend_noirq+0x0/0x50 returns -110
235  amd_pmc AMDI0005:00: PM: failed to suspend noirq: error -110
236
237The timing problem was identified by comparing the values of the idle mask.
238
239`commit 3c3c8e88c8712 ("platform/x86: amd-pmc: Increase the response register timeout") <https://git.kernel.org/torvalds/c/3c3c8e88c8712>`_
240
241Failed to reach hardware sleep state with panel on
242--------------------------------------------------
243On some Strix systems certain panels were observed to block the system from
244entering a hardware sleep state if the internal panel was on during the sequence.
245
246Even though the panel got turned off during suspend it exposed a timing problem
247where an interrupt caused the display hardware to wake up and block low power
248state entry.
249
250`commit 40b8c14936bd2 ("drm/amd/display: Disable unneeded hpd interrupts during dm_init") <https://git.kernel.org/torvalds/c/40b8c14936bd2>`_
251
252Runtime power consumption issues
253================================
254
255Runtime power consumption is influenced by many factors, including but not
256limited to the configuration of the PCIe Active State Power Management (ASPM),
257the display brightness, the EPP policy of the CPU, and the power management
258of the devices.
259
260ASPM
261----
262For the best runtime power consumption, ASPM should be programmed as intended
263by the BIOS from the hardware vendor.  To accomplish this the Linux kernel
264should be compiled with ``CONFIG_PCIEASPM_DEFAULT`` set to ``y`` and the
265sysfs file ``/sys/module/pcie_aspm/parameters/policy`` should not be modified.
266
267Most notably, if L1.2 is not configured properly for any devices, the SoC
268will not be able to enter the deepest idle state.
269
270EPP Policy
271----------
272The ``energy_performance_preference`` sysfs file can be used to set a bias
273of efficiency or performance for a CPU.  This has a direct relationship on
274the battery life when more heavily biased towards performance.
275
276
277BIOS debug messages
278===================
279
280Most OEM machines don't have a serial UART for outputting kernel or BIOS
281debug messages. However BIOS debug messages are useful for understanding
282both BIOS bugs and bugs with the Linux kernel drivers that call BIOS AML.
283
284As the BIOS on most OEM AMD systems are based off an AMD reference BIOS,
285the infrastructure used for exporting debugging messages is often the same
286as AMD reference BIOS.
287
288Manually Parsing
289----------------
290There is generally an ACPI method ``\M460`` that different paths of the AML
291will call to emit a message to the BIOS serial log. This method takes
2927 arguments, with the first being a string and the rest being optional
293integers::
294
295  Method (M460, 7, Serialized)
296
297Here is an example of a string that BIOS AML may call out using ``\M460``::
298
299  M460 ("  OEM-ASL-PCIe Address (0x%X)._REG (%d %d)  PCSA = %d\n", DADR, Arg0, Arg1, PCSA, Zero, Zero)
300
301Normally when executed, the ``\M460`` method would populate the additional
302arguments into the string.  In order to get these messages from the Linux
303kernel a hook has been added into ACPICA that can capture the *arguments*
304sent to ``\M460`` and print them to the kernel ring buffer.
305For example the following message could be emitted into kernel ring buffer::
306
307  extrace-0174 ex_trace_args         :  "  OEM-ASL-PCIe Address (0x%X)._REG (%d %d)  PCSA = %d\n", ec106000, 2, 1, 1, 0, 0
308
309In order to get these messages, you need to compile with ``CONFIG_ACPI_DEBUG``
310and then turn on the following ACPICA tracing parameters.
311This can be done either on the kernel command line or at runtime:
312
313* ``acpi.trace_method_name=\M460``
314* ``acpi.trace_state=method``
315
316NOTE: These can be very noisy at bootup. If you turn these parameters on
317the kernel command, please also consider turning up ``CONFIG_LOG_BUF_SHIFT``
318to a larger size such as 17 to avoid losing early boot messages.
319
320Tool assisted Parsing
321---------------------
322As mentioned above, parsing by hand can be tedious, especially with a lot of
323messages.  To help with this, a tool has been created at
324`amd-debug-tools <https://git.kernel.org/pub/scm/linux/kernel/git/superm1/amd-debug-tools.git/about/>`_
325to help parse the messages.
326
327Random reboot issues
328====================
329
330When a random reboot occurs, the high-level reason for the reboot is stored
331in a register that will persist onto the next boot.
332
333There are 6 classes of reasons for the reboot:
334 * Software induced
335 * Power state transition
336 * Pin induced
337 * Hardware induced
338 * Remote reset
339 * Internal CPU event
340
341.. csv-table::
342   :header: "Bit", "Type", "Reason"
343   :align: left
344
345   "0",  "Pin",      "thermal pin BP_THERMTRIP_L was tripped"
346   "1",  "Pin",      "power button was pressed for 4 seconds"
347   "2",  "Pin",      "shutdown pin was tripped"
348   "4",  "Remote",   "remote ASF power off command was received"
349   "9",  "Internal", "internal CPU thermal limit was tripped"
350   "16", "Pin",      "system reset pin BP_SYS_RST_L was tripped"
351   "17", "Software", "software issued PCI reset"
352   "18", "Software", "software wrote 0x4 to reset control register 0xCF9"
353   "19", "Software", "software wrote 0x6 to reset control register 0xCF9"
354   "20", "Software", "software wrote 0xE to reset control register 0xCF9"
355   "21", "ACPI-state", "ACPI power state transition occurred"
356   "22", "Pin",      "keyboard reset pin KB_RST_L was tripped"
357   "23", "Internal", "internal CPU shutdown event occurred"
358   "24", "Hardware", "system failed to boot before failed boot timer expired"
359   "25", "Hardware", "hardware watchdog timer expired"
360   "26", "Remote",   "remote ASF reset command was received"
361   "27", "Internal", "an uncorrected error caused a data fabric sync flood event"
362   "29", "Internal", "FCH and MP1 failed warm reset handshake"
363   "30", "Internal", "a parity error occurred"
364   "31", "Internal", "a software sync flood event occurred"
365
366This information is read by the kernel at bootup and printed into
367the syslog. When a random reboot occurs this message can be helpful
368to determine the next component to debug.
369