- Berangkat dari ketiadaan debugger yang dapat menghentikan eksekusi GPU dan memeriksa statusnya, artikel ini menjelaskan proses implementasinya secara langsung pada GPU AMD
- Berkomunikasi langsung dengan GPU melalui antarmuka DRM dan libdrm, lalu menyusun proses pembuatan konteks, alokasi buffer, dan pengiriman perintah secara bertahap
- Membangun struktur untuk menghentikan eksekusi GPU dengan memanfaatkan register TBA/TMA dan trap handler, lalu membaca dan memulihkan status melalui sinkronisasi dengan CPU
- Memperluas lingkungan debugging shader nyata melalui kompilasi kode SPIR-V dan integrasi RADV, sehingga fitur breakpoint, stepping, dan watchpoint dapat diimplementasikan
- Pendekatan yang mengendalikan langsung struktur internal GPU ini membuktikan kemungkinan implementasi debugger lengkap untuk GPU AMD, dan masih memiliki ruang untuk berkembang ke integrasi Vulkan
Kebutuhan dan pendekatan untuk debugging GPU
- Berangkat dari ketiadaan alat untuk menghentikan sementara eksekusi GPU dan memeriksa statusnya seperti pada CPU
- Model eksekusi paralel pada GPU membuat debugging jauh lebih kompleks
rocgdb di lingkungan AMD ROCm memang ada, tetapi hanya mendukung cakupan yang terbatas pada ROCm
- Dengan merujuk pada seri blog Marcell Kiss, penulis mencoba mengimplementasikan debugger yang berkomunikasi langsung dengan GPU
Berkomunikasi langsung dengan GPU
- Mempelajari cara berkomunikasi langsung dengan GPU dengan menelusuri cara kerja driver RADV
- Membuka
/dev/dri/cardX untuk terhubung ke KMD (kernel mode driver), lalu memanggil amdgpu_device_initialize
- Melalui
libdrm, melakukan pembuatan konteks (amdgpu_cs_ctx_create) dan alokasi buffer
- Membuat dua buffer: buffer kode dan buffer perintah
- Memetakan buffer ke ruang alamat virtual GPU/CPU
- Alih-alih
amdgpu_bo_va_op, pemetaan dilakukan dengan memanggil IOCTL secara langsung
- Menggunakan
clang dan objdump untuk mengompilasi kode assembly shader dan mengekstrak binarinya
- Menyusun perintah GPU dalam format
PM4 Packet untuk mengirim perintah eksekusi shader
Trap GPU dan pemanfaatan Debugfs
- Menyetel trap handler menggunakan register TBA/TMA pada ISA RDNA3
TBA: alamat trap handler
TMA: alamat memori sementara untuk trap handler
- Karena tidak bisa diakses langsung dari user space, digunakan antarmuka debugfs
- Mengakses register melalui file
/sys/kernel/debug/dri/{PCI address}/regs2
- Penulisan register dilakukan dengan
amdgpu_debugfs_regs2_write
- Mengaktifkan trap handler dengan mengatur TBA/TMA per VMID
- Tiap VMID membedakan konteks proses GPU
Implementasi trap handler
- Trap handler adalah program shader istimewa yang dijalankan saat GPU menemui pengecualian
- Menggunakan register TTMP untuk menyimpan status GPU (STATUS, EXEC, VCC, dll.)
- Menyimpan nilai register tiap thread ke memori dengan instruksi
global_store_addtid_b32
- Saat GPU selesai menulis data, CPU mendeteksinya lalu menghentikan sementara GPU dengan register SQ_CMD
- Setelah CPU menganalisis data, eksekusi GPU dilanjutkan kembali melalui SQ_CMD
- Saat kembali, trap handler memulihkan program counter dan status register
Eksekusi kode SPIR-V dan integrasi RADV
- Mendukung kompilasi kode SPIR-V alih-alih assembly manual
- Menggunakan kompiler
ACO milik RADV untuk mengubah SPIR-V menjadi biner GPU
- Membuat perangkat virtual dengan variabel lingkungan
RADV_FORCE_FAMILY
- Dalam mode
null_winsys RADV, hanya kompilasi yang dilakukan tanpa akses ke perangkat keras nyata
- Mengekstrak kode shader, pengaturan resource, dan informasi debug dari hasil kompilasi
Perluasan fitur debugger
- Stepping: mengendalikan eksekusi per instruksi dengan bit
RSRC1.DEBUG_MODE dan RSRC3.TRAP_ON_START
- Breakpoints: menangani trap setelah menghitung posisi program counter berdasarkan alamat buffer kode
- Source Mapping: memetakan baris kode sumber dengan informasi debug dari kompiler ACO
- Watchpoints: fitur pemantauan alamat dapat diimplementasikan dengan proteksi halaman GPU atau register
SQ_WATCH
- Pelacakan nama dan tipe variabel: perlu peningkatan pada penyampaian informasi debug di tahap optimisasi NIR milik Mesa
- Integrasi Vulkan: memungkinkan debugging per frame berbasis RADV serta pemanfaatan informasi buffer, tekstur, dan konstanta
Bonus: kode page walking mode pengguna
- Menyediakan contoh kode penelusuran page table untuk GPU RDNA3 (gfx11)
- Termasuk definisi struct PDE/PTE dan fungsi decoding
- Mengimplementasikan proses konversi dari alamat virtual ke alamat fisik
- Dengan membaca register page table per VMID, dimungkinkan untuk menganalisis struktur pemetaan memori GPU
Kesimpulan
- Membuktikan kemungkinan implementasi debugger lengkap melalui akses tingkat kernel dan perangkat keras pada GPU AMD
- Mewujudkan penghentian eksekusi, analisis status, dan pelanjutan kembali dengan membangun loop komunikasi dua arah antara CPU dan GPU
- Ke depan, ada peluang berkembang menjadi lingkungan debugging GPU yang ramah pengembang melalui integrasi RADV dan Vulkan
Belum ada komentar.