amdgpu_info/
amdgpu_info.rs

1use libdrm_amdgpu_sys::*;
2
3fn info(libdrm_amdgpu: &LibDrmAmdgpu, pci_bus: &PCI::BUS_INFO) {
4    let Ok(device_path) = pci_bus.get_drm_render_path() else { return };
5    let (amdgpu_dev, _major, _minor) = {
6        use std::fs::File;
7        use std::os::fd::IntoRawFd;
8
9        let fd = File::open(device_path).unwrap();
10
11        libdrm_amdgpu.init_device_handle(fd.into_raw_fd()).unwrap()
12    };
13
14    if let Ok(drm_ver) = amdgpu_dev.get_drm_version_struct() {
15        println!("{drm_ver:#?}");
16    }
17
18    if let Ok(ext_info) = amdgpu_dev.device_info() {
19        use AMDGPU::GPU_INFO;
20
21        println!("Marketing Name: [{}]", ext_info.find_device_name_or_default());
22        // println!("\n{ext_info:#X?}\n");
23        let gpu_type = if ext_info.is_apu() { "APU" } else { "dGPU" };
24        let asic = ext_info.get_asic_name();
25
26        println!(
27            "DeviceID.RevID: {:#0X}.{:#0X}",
28            ext_info.device_id(),
29            ext_info.pci_rev_id()
30        );
31
32        println!();
33        println!("Family:\t\t{}", ext_info.get_family_name());
34        println!("ASIC Name:\t{asic}");
35        println!("Chip class:\t{}", ext_info.get_chip_class());
36        println!("GPU Type:\t{gpu_type}");
37
38        if let Some(gfx_ver) = ext_info.get_gfx_target_version() {
39            println!("gfx_target_version: {gfx_ver}");
40        }
41
42        let max_good_cu_per_sa = ext_info.get_max_good_cu_per_sa();
43        let min_good_cu_per_sa = ext_info.get_min_good_cu_per_sa();
44
45        println!();
46        println!("Shader Engine (SE):\t\t{:3}", ext_info.max_se());
47        println!("Shader Array (SA/SH) per SE:\t{:3}", ext_info.max_sa_per_se());
48        if max_good_cu_per_sa != min_good_cu_per_sa {
49            println!("CU per SA[0]:\t\t\t{:3}", max_good_cu_per_sa);
50            println!("CU per SA[1]:\t\t\t{:3}", min_good_cu_per_sa);
51        } else {
52            println!("CU per SA:\t\t\t{:3}", max_good_cu_per_sa);
53        }
54        println!("Total Compute Unit:\t\t{:3}", ext_info.cu_active_number());
55
56        if let Some((min, max)) = amdgpu_dev.get_min_max_gpu_clock() {
57            println!("Engine Clock:\t\t{min}-{max} MHz");
58        }
59
60        println!("Peak FP32:\t\t{} GFLOPS", ext_info.peak_gflops());
61
62        println!();
63        println!("VRAM Type:\t\t{}", ext_info.get_vram_type());
64        println!("VRAM Bit Width:\t\t{}-bit", ext_info.vram_bit_width);
65
66        if let Some((min, max)) = amdgpu_dev.get_min_max_memory_clock() {
67            println!("Memory Clock:\t\t{min}-{max} MHz");
68        }
69
70        println!("Peak Memory BW:\t\t{} GB/s", ext_info.peak_memory_bw_gb());
71
72        println!();
73        println!("L1cache (per CU):\t{:4} KiB", ext_info.get_l1_cache_size() >> 10);
74        if 0 < ext_info.sqc_data_cache_size {
75            println!("SQC Data Cache:\t\t{:4} KiB", ext_info.sqc_data_cache_size);
76        }
77        if 0 < ext_info.sqc_inst_cache_size {
78            println!("SQC Inst Cache:\t\t{:4} KiB", ext_info.sqc_inst_cache_size);
79        }
80        let gl1_cache_size = ext_info.get_gl1_cache_size();
81        let l3_cache_size = ext_info.calc_l3_cache_size_mb();
82        if 0 < gl1_cache_size {
83            println!("GL1cache (per SA/SH):\t{:4} KiB", gl1_cache_size >> 10);
84        }
85        if 0 < ext_info.gl1c_cache_size {
86            println!("Total GL1cache:\t\t{gl1_cache_size:4} KiB");
87        }
88        println!(
89            "L2cache:\t\t{:4} KiB ({} Banks)",
90            ext_info.calc_l2_cache_size() >> 10,
91            ext_info.get_actual_num_tcc_blocks(),
92        );
93        if 0 < l3_cache_size {
94            println!("L3cache:\t\t{l3_cache_size:4} MiB");
95        }
96    }
97
98    if let Ok(info) = amdgpu_dev.memory_info() {
99        println!();
100        println!(
101            "VRAM Usage:\t\t\t{usage}/{total} MiB",
102            usage = info.vram.heap_usage >> 20,
103            total = info.vram.total_heap_size >> 20,
104        );
105        println!(
106            "CPU Accessible VRAM Usage:\t{usage}/{total} MiB",
107            usage = info.cpu_accessible_vram.heap_usage >> 20,
108            total = info.cpu_accessible_vram.total_heap_size >> 20,
109        );
110        println!(
111            "GTT Usage:\t\t\t{usage}/{total} MiB",
112            usage = info.gtt.heap_usage >> 20,
113            total = info.gtt.total_heap_size >> 20,
114        );
115        let re_bar = if info.check_resizable_bar() { "Enabled" } else { "Disabled" };
116        println!("ResizableBAR:\t\t\t{re_bar}");
117
118        if let Ok(moved) = amdgpu_dev.num_bytes_moved() {
119            println!("Number of bytes moved for TTM migration: {moved}");
120        }
121
122        if let Ok(fault_count) = amdgpu_dev.num_vram_cpu_page_faults() {
123            println!("Number of VRAM page faults on CPU access: {fault_count}");
124        }
125
126        if let Ok(e) = amdgpu_dev.num_evictions() {
127            println!("Number of TTM buffer evictions: {e}");
128        }
129
130        if let Ok(lost) = amdgpu_dev.vram_lost_counter() {
131            println!("VRAM lost counter: {lost}");
132        }
133
134        if let Ok(ras) = amdgpu_dev.ras_enabled_features() {
135            use AMDGPU::RasBlock;
136
137            println!("ECC Memory: {}", if ras.is_supported(RasBlock::UMC) {
138                "supported"
139            } else {
140                "not supported"
141            });
142        }
143    }
144
145    {
146        use AMDGPU::HW_IP::*;
147
148        let ip_list = [
149            HW_IP_TYPE::GFX,
150            HW_IP_TYPE::COMPUTE,
151            HW_IP_TYPE::DMA,
152            HW_IP_TYPE::UVD,
153            HW_IP_TYPE::VCE,
154            HW_IP_TYPE::UVD_ENC,
155            HW_IP_TYPE::VCN_DEC,
156            HW_IP_TYPE::VCN_ENC,
157            HW_IP_TYPE::VCN_JPEG,
158            HW_IP_TYPE::VPE,
159        ];
160
161        println!("\nHardware IP info:");
162
163        for ip_type in &ip_list {
164            if let (Ok(ip_info), Ok(ip_count)) = (
165                amdgpu_dev.query_hw_ip_info(*ip_type, 0),
166                amdgpu_dev.query_hw_ip_count(*ip_type),
167            ) {
168                let (major, minor) = ip_info.version();
169                let queues = ip_info.num_queues();
170
171                if queues == 0 {
172                    continue;
173                }
174
175                println!(
176                    "{ip_type:8} count: {ip_count}, ver: {major:2}.{minor}, queues: {queues}",
177                    ip_type = ip_type.to_string(),
178                );
179            }
180        }
181    }
182
183    {
184        use AMDGPU::FW_VERSION::*;
185
186        let fw_list = [
187            FW_TYPE::VCE,
188            FW_TYPE::UVD,
189            FW_TYPE::GMC,
190            FW_TYPE::GFX_ME,
191            FW_TYPE::GFX_PFP,
192            FW_TYPE::GFX_CE,
193            FW_TYPE::GFX_RLC,
194            FW_TYPE::GFX_MEC,
195            FW_TYPE::SMC,
196            FW_TYPE::SDMA,
197            FW_TYPE::SOS,
198            FW_TYPE::ASD,
199            FW_TYPE::VCN,
200            FW_TYPE::GFX_RLC_RESTORE_LIST_CNTL,
201            FW_TYPE::GFX_RLC_RESTORE_LIST_GPM_MEM,
202            FW_TYPE::GFX_RLC_RESTORE_LIST_SRM_MEM,
203            FW_TYPE::DMCU,
204            FW_TYPE::TA,
205            FW_TYPE::DMCUB,
206            FW_TYPE::TOC,
207            FW_TYPE::VPE,
208        ];
209
210        println!("\nFirmware info:");
211
212        for fw_type in &fw_list {
213            let fw_info = match amdgpu_dev.query_firmware_version(*fw_type, 0, 0) {
214                Ok(v) => v,
215                Err(_) => continue,
216            };
217
218            let (ver, ftr) = (fw_info.version, fw_info.feature);
219
220            if ver == 0 {
221                continue;
222            }
223
224            println!(
225                "{fw_type:<8} ver: {ver:>#10X}, feature: {ftr:>3}",
226                fw_type = fw_type.to_string(),
227            );
228        }
229    }
230
231    {
232        use AMDGPU::VIDEO_CAPS::CAP_TYPE;
233
234        println!("\nVideo caps:");
235        if let Ok(codec_info) = amdgpu_dev.get_video_caps_info(CAP_TYPE::DECODE) {
236            println!("{codec_info:#?}");
237        }
238        if let Ok(codec_info) = amdgpu_dev.get_video_caps_info(CAP_TYPE::ENCODE) {
239            println!("{codec_info:#?}");
240        }
241    }
242
243    if let Ok(bus_info) = amdgpu_dev.get_pci_bus_info() {
244        println!("\nPCI (domain:bus:dev.func): {bus_info}");
245
246        if let Ok(render) = bus_info.get_drm_render_path() {
247            println!("Render: {render:?}");
248        }
249        if let Ok(card) = bus_info.get_drm_card_path() {
250            println!("Card: {card:?}");
251        }
252    }
253
254    match amdgpu_dev.get_min_max_link_info_from_dpm() { Some([min, max]) => {
255        println!(
256            "PCIe Link Speed     (DPM)    : Gen{}x{} - Gen{}x{}",
257            min.r#gen,
258            min.width,
259            max.r#gen,
260            max.width,
261        );
262
263        if let Some(max_gpu_link) = amdgpu_dev.get_max_gpu_link() {
264            println!(
265                "PCIe Link Speed (GPU, Max)   : Gen{}x{}",
266                max_gpu_link.r#gen,
267                max_gpu_link.width,
268            );
269        }
270
271        if let Some(max_system_link) = amdgpu_dev.get_max_system_link() {
272            println!(
273                "PCIe Link Speed (System, Max): Gen{}x{}",
274                max_system_link.r#gen,
275                max_system_link.width,
276            );
277        }
278    } _ => {
279        println!("PCIe Link Speed     (DPM)    : None");
280    }}
281
282    if let Ok(vbios) = amdgpu_dev.get_vbios_info() {
283        println!("\nVBIOS info:");
284        println!("name: [{}]", vbios.name);
285        println!("pn: [{}]", vbios.pn);
286        println!("ver: [{}]", vbios.ver);
287        println!("date: [{}]", vbios.date);
288    }
289
290/*
291    if let Ok(vce_clock) = amdgpu_dev.vce_clock_info() {
292        println!("\n{vce_clock:#?}");
293    }
294*/
295
296    {
297        use AMDGPU::SENSOR_INFO::*;
298
299        let sensors = [
300            SENSOR_TYPE::GFX_SCLK,
301            SENSOR_TYPE::GFX_MCLK,
302            SENSOR_TYPE::GPU_TEMP,
303            SENSOR_TYPE::GPU_LOAD,
304            SENSOR_TYPE::GPU_AVG_POWER,
305            SENSOR_TYPE::GPU_INPUT_POWER,
306            SENSOR_TYPE::VDDNB,
307            SENSOR_TYPE::VDDGFX,
308            SENSOR_TYPE::STABLE_PSTATE_GFX_SCLK,
309            SENSOR_TYPE::STABLE_PSTATE_GFX_MCLK,
310            SENSOR_TYPE::PEAK_PSTATE_GFX_SCLK,
311            SENSOR_TYPE::PEAK_PSTATE_GFX_MCLK,
312        ];
313
314        println!("\nSensors:");
315
316        for s in &sensors {
317            match amdgpu_dev.sensor_info(*s) { Ok(val) => {
318                println!("{s:?}: {val}");
319            } _ => {
320                println!("{s:?}: not supported");
321            }}
322        }
323    }
324
325    if let Ok(sysfs) = amdgpu_dev.get_sysfs_path() {
326        // let f = AMDGPU::DpmClockRange::from_sysfs(AMDGPU::DpmClockType::FCLK, &sysfs);
327        // println!("{f:?}");
328        use AMDGPU::{DpmForcedLevel, PowerProfile};
329
330        let profiles: Vec<String> = PowerProfile::get_all_supported_profiles_from_sysfs(&sysfs)
331            .iter()
332            .map(|p| p.to_string())
333            .collect();
334
335        println!("Supported Power Profiles: {profiles:?}");
336
337        if let Some(profiles) = PowerProfile::get_current_profile_from_sysfs(&sysfs) {
338            println!("Current Power Profiles: {profiles}");
339        }
340
341        if let Ok(level) = DpmForcedLevel::get_from_sysfs(&sysfs) {
342            println!("power_dpm_force_performance_level: {level:?}");
343        }
344
345        use AMDGPU::{RasErrorCount, RasBlock};
346
347        if let Ok(cnt) = RasErrorCount::get_from_sysfs_with_ras_block(&sysfs, RasBlock::UMC) {
348            println!(
349                "Memory Error Count: uncorrected {}, corrected {}",
350                cnt.uncorrected,
351                cnt.corrected,
352            );
353        }
354    }
355
356    if let Some(hwmon) = amdgpu_dev.get_hwmon_path() {
357        println!("hwmon: {hwmon:?}");
358
359        use AMDGPU::{HwmonTemp, HwmonTempType, PowerCap};
360        if let Some(power_cap) = PowerCap::from_hwmon_path(&hwmon) {
361            let PowerCap { type_, current, default, min, max } = power_cap;
362            println!("PowerCap ({type_}): {current} W (Current), {default} W (Default), {min}-{max} W (Range)");
363        }
364        if let Some(edge_temp) = HwmonTemp::from_hwmon_path(&hwmon, HwmonTempType::Edge) {
365            println!("{edge_temp:?}");
366        }
367        if let Some(junction_temp) = HwmonTemp::from_hwmon_path(&hwmon, HwmonTempType::Junction) {
368            println!("{junction_temp:?}");
369        }
370        if let Some(mem_temp) = HwmonTemp::from_hwmon_path(&hwmon, HwmonTempType::Memory) {
371            println!("{mem_temp:?}");
372        }
373    }
374
375    println!();
376}
377
378fn main() {
379    let libdrm_amdgpu = LibDrmAmdgpu::new().unwrap();
380    let pci_devs = AMDGPU::get_all_amdgpu_pci_bus();
381
382    if pci_devs.is_empty() {
383        panic!("No AMDGPU devices.");
384    }
385
386    for pci_bus in &pci_devs {
387        info(&libdrm_amdgpu, pci_bus);
388    }
389}