amd-debugging.rst 16 KB

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