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 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{
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 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}