18. 除錯 AMD Zen 系統¶
18.1. 簡介¶
本文件介紹了可用於除錯 AMD Zen 系統問題的技術。它旨在供開發人員和技術使用者使用,以幫助識別和解決問題。
18.2. S3 vs s2idle¶
在 AMD 系統上,無法同時支援掛起到 RAM (S3) 和掛起到空閒 (s2idle)。要確認您的系統支援哪種模式,您可以檢視 cat /sys/power/mem_sleep。如果顯示 s2idle [deep],則支援 *S3*。如果顯示 [s2idle],則支援 *s2idle*。
在支援 *S3* 的系統上,將利用韌體將所有硬體置於適當的低功耗狀態。
在支援 *s2idle* 的系統上,核心將負責將裝置轉換為適當的低功耗狀態。當所有裝置都處於適當的低功耗狀態時,硬體將轉換為硬體睡眠狀態。
在掛起週期之後,您可以透過檢視 cat /sys/power/suspend_stats/last_hw_sleep 來了解在硬體睡眠狀態下花費了多少時間。
此流程圖解釋了 AMD s2idle 掛起流程的工作方式。
此流程圖解釋了 amd s2idle 恢復流程的工作方式。
18.3. s2idle 除錯工具¶
由於可能發生問題的地點很多,因此在 amd-debug-tools 上建立了一個除錯工具,可以幫助測試常見問題並提供建議。
如果您遇到 s2idle 問題,最好從此開始,並按照其發現結果中的說明進行操作。如果您繼續遇到問題,請使用此指令碼生成的報告向 drm/amd gitlab 提交錯誤報告。
18.4. 來自 IRQ 的虛假 s2idle 喚醒¶
虛假喚醒通常會將 IRQ 設定為 /sys/power/pm_wakeup_irq。這可以與 /proc/interrupts 匹配,以確定哪個裝置喚醒了系統。
如果這不足以除錯問題,則可以設定以下 sysfs 檔案,以增加喚醒過程的詳細程度
# echo 1 | sudo tee /sys/power/pm_debug_messages
# echo 1 | sudo tee /sys/power/pm_print_times
進行這些更改後,核心將顯示可以追溯到核心 s2idle 迴圈程式碼的訊息,並顯示喚醒時任何活動的 GPIO 源。
如果喚醒是由 ACPI SCI 引起的,則可能需要額外的 ACPI 除錯。以下命令可以啟用額外的跟蹤資料
# echo enable | sudo tee /sys/module/acpi/parameters/trace_state
# echo 1 | sudo tee /sys/module/acpi/parameters/aml_debug_output
# echo 0x0800000f | sudo tee /sys/module/acpi/parameters/debug_level
# echo 0xffff0000 | sudo tee /sys/module/acpi/parameters/debug_layer
18.5. 來自 GPIO 的虛假 s2idle 喚醒¶
如果在喚醒系統時 GPIO 處於活動狀態,理想情況下您應該檢視原理圖以確定它與哪個裝置相關聯。如果原理圖不可用,另一種策略是檢視 ACPI _EVT() 條目,以確定當該 GPIO 處於活動狀態時通知哪個裝置。
對於一個假設的例子,假設 GPIO 59 喚醒了系統。您可以檢視 SSDT 以確定當 GPIO 59 處於活動狀態時通知哪個裝置。
首先將 GPIO 編號轉換為十六進位制。
$ python3 -c "print(hex(59))"
0x3b
接下來確定哪個 ACPI 表具有 _EVT 條目。例如
$ sudo grep EVT /sys/firmware/acpi/tables/SSDT*
grep: /sys/firmware/acpi/tables/SSDT27: binary file matches
解碼此表
$ sudo cp /sys/firmware/acpi/tables/SSDT27 .
$ sudo iasl -d SSDT27
然後檢視該表,並找到 GPIO 0x3b 的匹配條目。
Case (0x3B)
{
M000 (0x393B)
M460 (" Notify (\\_SB.PCI0.GP17.XHC1, 0x02)\n", Zero, Zero, Zero, Zero, Zero, Zero)
Notify (\_SB.PCI0.GP17.XHC1, 0x02) // Device Wake
}
您可以在這種情況下看到,當 GPIO 59 處於活動狀態時,裝置 \_SB.PCI0.GP17.XHC1 收到通知。很明顯這是一個 XHCI 控制器,但要更進一步,您可以透過將其與 ACPI 匹配來確定它是哪個 XHCI 控制器。
$ grep "PCI0.GP17.XHC1" /sys/bus/acpi/devices/*/path
/sys/bus/acpi/devices/device:2d/path:\_SB_.PCI0.GP17.XHC1
/sys/bus/acpi/devices/device:2e/path:\_SB_.PCI0.GP17.XHC1.RHUB
/sys/bus/acpi/devices/device:2f/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT1
/sys/bus/acpi/devices/device:30/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT1.CAM0
/sys/bus/acpi/devices/device:31/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT1.CAM1
/sys/bus/acpi/devices/device:32/path:\_SB_.PCI0.GP17.XHC1.RHUB.PRT2
/sys/bus/acpi/devices/LNXPOWER:0d/path:\_SB_.PCI0.GP17.XHC1.PWRS
在這裡您可以看到它與 device:2d 匹配。檢視 physical_node 以確定實際的 PCI 裝置是什麼。
$ ls -l /sys/bus/acpi/devices/device:2d/physical_node
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
所以這就是它:與此 GPIO 喚醒相關的 PCI 裝置是 0000:c2:00.4。
amd_s2idle.py 指令碼將為您捕獲大多數這些工件。
18.6. s2idle PM 除錯訊息¶
在 AMD 系統上的 s2idle 流程中,ACPI LPS0 驅動程式負責檢查所有 uPEP 約束。未透過的 uPEP 約束不會阻止 s0i3 進入。這意味著如果某些約束未得到滿足,即使存在一些已知問題,核心也可能會嘗試進入 s2idle。
要啟用 PM 除錯,可以在啟動時指定 pm_debug_messagess 核心命令列選項,或寫入 /sys/power/pm_debug_messages。未滿足的約束將顯示在核心日誌中,並且可以透過處理核心環形緩衝區的日誌記錄工具(如 dmesg 或 journalctl)檢視。”
如果在這些訊息重新整理之前系統在進入/退出時凍結,一個有用的除錯策略是取消繫結 amd_pmc 驅動程式,以防止通知平臺啟動 s0i3 進入。這將阻止系統在進入或退出時凍結,並讓您檢視所有失敗的約束。
cd /sys/bus/platform/drivers/amd_pmc
ls | grep AMD | sudo tee unbind
執行此操作後,執行掛起週期並特別注意以下方面的錯誤
ACPI: LPI: Constraint not met; min power state:%s current power state:%s
18.7. s2idle 問題的歷史示例¶
為了幫助瞭解可能發生的問題型別以及如何除錯它們,以下是一些已解決的 s2idle 問題的歷史示例。
18.7.1. 核心離線¶
一位終端使用者報告說,使核心離線會阻止系統正確進入 s0i3。這是使用內部 AMD 工具進行除錯的,以捕獲和顯示來自硬體的指標流,顯示當核心離線時發生的變化。確定硬體沒有收到離線核心處於最深狀態的通知,因此它阻止了 CPU 進入最深狀態。該問題被除錯為將核心置於 C3 狀態的缺失命令。
commit d6b88ce2eb9d2 (“ACPI: processor idle: Allow playing dead in C3 state”)
18.7.2. 恢復後損壞¶
Rembrandt 出現的一個大問題是恢復後出現圖形損壞。發生這種情況的原因是 PSP 和驅動程式職責的錯位。PSP 將儲存和恢復 DMCUB,但驅動程式假定它需要在恢復時重置 DMCUB。實際上,這也是早期晶片組的錯位,但未觀察到。
commit 79d6b9351f086 (“drm/amd/display: Don’t reinitialize DMCUB on s0ix resume”)
18.7.3. 背靠背掛起失敗¶
當使用觸發 IRQ 以喚醒的喚醒源時,pinctrl-amd 驅動程式中的一個錯誤可能會捕獲 IRQ 的錯誤狀態,並阻止系統正確地返回睡眠狀態。
commit b8c824a869f22 (“pinctrl: amd: Don’t save/restore interrupt status and wake status bits”)
18.7.4. 5 分鐘後基於定時器的虛假喚醒¶
HPET 用於為系統程式設計喚醒源,但是這導致 5 分鐘後出現虛假喚醒。要使用的正確警報是 ACPI 警報。
commit 3d762e21d5637 (“rtc: cmos: Use ACPI alarm for non-Intel x86 systems too”)
18.7.5. 恢復後磁碟消失¶
從 s2idle 恢復後,NVME 磁碟將消失。這是由於 BIOS 未指定 _DSD StorageD3Enable 屬性。這導致 NVME 驅動程式無法在掛起時將磁碟置於預期狀態,並且在恢復時失敗。
commit e79a10652bbd3 (“ACPI: x86: Force StorageD3Enable on more products”)
18.7.6. 虛假 IRQ1¶
許多 Renoir、Lucienne、Cezanne 和 Barcelo 平臺都存在平臺韌體錯誤,其中 IRQ1 在 s0i3 恢復期間被觸發。
這已在平臺韌體中修復,但許多系統未收到任何更多平臺韌體更新。
commit 8e60615e89321 (“platform/x86/amd: pmc: Disable IRQ1 wakeup for RN/CZN”)
18.7.7. 硬體超時¶
除了接受來自 amd-pmc 驅動程式的值外,硬體還執行許多操作。由於與硬體的通訊路徑是一個郵箱,因此它可能無法足夠快地響應。此問題表現為掛起失敗
PM: dpm_run_callback(): acpi_subsys_suspend_noirq+0x0/0x50 returns -110
amd_pmc AMDI0005:00: PM: failed to suspend noirq: error -110
透過比較空閒掩碼的值來識別計時問題。
commit 3c3c8e88c8712 (“platform/x86: amd-pmc: Increase the response register timeout”)
18.7.8. 無法在面板開啟的情況下達到硬體睡眠狀態¶
在某些 Strix 系統上,觀察到某些面板會阻止系統進入硬體睡眠狀態,如果在該序列期間內部面板已開啟。
即使面板在掛起期間已關閉,它也暴露了一個計時問題,即中斷導致顯示硬體喚醒並阻止低功耗狀態進入。
commit 40b8c14936bd2 (“drm/amd/display: Disable unneeded hpd interrupts during dm_init”)
18.8. 執行時功耗問題¶
執行時功耗受許多因素影響,包括但不限於 PCIe 主動狀態電源管理 (ASPM) 的配置、顯示亮度、CPU 的 EPP 策略以及裝置的電源管理。
18.8.1. ASPM¶
為了獲得最佳的執行時功耗,ASPM 應按照硬體供應商 BIOS 的預期進行程式設計。要實現此目的,應使用設定為 y 的 CONFIG_PCIEASPM_DEFAULT 編譯 Linux 核心,並且不應修改 sysfs 檔案 /sys/module/pcie_aspm/parameters/policy。
最值得注意的是,如果任何裝置的 L1.2 配置不正確,SoC 將無法進入最深度的空閒狀態。
18.8.2. EPP 策略¶
energy_performance_preference sysfs 檔案可用於設定 CPU 的效率或效能偏差。當更偏向效能時,這與電池壽命有直接關係。
18.9. BIOS 除錯訊息¶
大多數 OEM 機器沒有用於輸出核心或 BIOS 除錯訊息的序列 UART。但是,BIOS 除錯訊息對於理解 BIOS 錯誤和呼叫 BIOS AML 的 Linux 核心驅動程式的錯誤都很有用。
由於大多數 OEM AMD 系統上的 BIOS 都基於 AMD 參考 BIOS,因此用於匯出除錯訊息的基礎架構通常與 AMD 參考 BIOS 相同。
18.9.1. 手動解析¶
通常有一個 ACPI 方法 \M460,AML 的不同路徑將呼叫該方法以將訊息傳送到 BIOS 序列日誌。此方法採用 7 個引數,第一個引數是一個字串,其餘引數是可選整數
Method (M460, 7, Serialized)
這是一個 BIOS AML 可能使用 \M460 呼叫的字串示例
M460 (" OEM-ASL-PCIe Address (0x%X)._REG (%d %d) PCSA = %d\n", DADR, Arg0, Arg1, PCSA, Zero, Zero)
通常在執行時,\M460 方法會將其他引數填充到字串中。為了從 Linux 核心獲取這些訊息,ACPICA 中添加了一個鉤子,可以捕獲傳送到 \M460 的*引數*,並將它們列印到核心環形緩衝區。例如,以下訊息可以傳送到核心環形緩衝區
extrace-0174 ex_trace_args : " OEM-ASL-PCIe Address (0x%X)._REG (%d %d) PCSA = %d\n", ec106000, 2, 1, 1, 0, 0
為了獲取這些訊息,您需要使用 CONFIG_ACPI_DEBUG 進行編譯,然後開啟以下 ACPICA 跟蹤引數。這可以在核心命令列上或在執行時完成
acpi.trace_method_name=\M460acpi.trace_state=method
注意:這些在啟動時可能非常嘈雜。如果您在核心命令上開啟這些引數,請同時考慮將 CONFIG_LOG_BUF_SHIFT 調大到更大的尺寸,例如 17,以避免丟失早期啟動訊息。
18.9.2. 工具輔助解析¶
如上所述,手動解析可能很乏味,尤其是在有很多訊息的情況下。為了幫助解決這個問題,已經在 amd-debug-tools 上建立了一個工具來幫助解析訊息。
18.10. 隨機重啟問題¶
當發生隨機重啟時,重啟的高階原因儲存在一個暫存器中,該暫存器將持續到下一次啟動。
- 重啟原因分為 6 類
軟體引起的
電源狀態轉換
引腳引起的
硬體引起的
遠端重置
內部 CPU 事件
位 |
型別 |
原因 |
|---|---|---|
0 |
引腳 |
熱敏引腳 BP_THERMTRIP_L 被觸發 |
1 |
引腳 |
電源按鈕被按下 4 秒鐘 |
2 |
引腳 |
關機引腳被觸發 |
4 |
遠端 |
收到遠端 ASF 關機命令 |
9 |
內部 |
內部 CPU 熱限制被觸發 |
16 |
引腳 |
系統重置引腳 BP_SYS_RST_L 被觸發 |
17 |
軟體 |
軟體發出 PCI 重置 |
18 |
軟體 |
軟體將 0x4 寫入重置控制暫存器 0xCF9 |
19 |
軟體 |
軟體將 0x6 寫入重置控制暫存器 0xCF9 |
20 |
軟體 |
軟體將 0xE 寫入重置控制暫存器 0xCF9 |
21 |
ACPI-狀態 |
發生 ACPI 電源狀態轉換 |
22 |
引腳 |
鍵盤重置引腳 KB_RST_L 被觸發 |
23 |
內部 |
發生內部 CPU 關機事件 |
24 |
硬體 |
系統在失敗啟動計時器到期之前未能啟動 |
25 |
硬體 |
硬體看門狗計時器到期 |
26 |
遠端 |
收到遠端 ASF 重置命令 |
27 |
內部 |
未更正的錯誤導致資料結構同步泛洪事件 |
29 |
內部 |
FCH 和 MP1 未能進行溫重置握手 |
30 |
內部 |
發生奇偶校驗錯誤 |
31 |
內部 |
發生軟體同步泛洪事件 |
此資訊在啟動時由核心讀取並列印到系統日誌中。當發生隨機重啟時,此訊息有助於確定要除錯的下一個元件。