libdrm_amdgpu_sys/amdgpu/
ip_discovery.rs

1use std::path::{Path, PathBuf};
2use std::collections::HashMap;
3
4/* ref: drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c */
5#[derive(Debug, Clone)]
6pub struct IpHwInstance {
7    pub hw_id: HwId,
8    pub num_instance: u8,
9    pub major: u8,
10    pub minor: u8,
11    pub revision: u8,
12    pub harvest: u8,
13    pub num_base_addresses: isize,
14    pub base_address: Vec<u32>,
15}
16
17impl IpHwInstance {
18    /// `ip_discovery/die/#die/#hw_id/#instance/`
19    pub fn get_from_instance_sysfs<P: Into<PathBuf>>(sysfs_path: P) -> Option<Self> {
20        let path = sysfs_path.into();
21        let hw_id = {
22            let tmp = Self::parse_file::<isize>(path.join("hw_id"))?;
23            HwId::from(tmp)
24        };
25        let num_instance = Self::parse_file::<u8>(path.join("num_instance"))?;
26        let major = Self::parse_file::<u8>(path.join("major"))?;
27        let minor = Self::parse_file::<u8>(path.join("minor"))?;
28        let revision = Self::parse_file::<u8>(path.join("revision"))?;
29        let harvest = Self::parse_harvest_file(&path)?;
30        let num_base_addresses = Self::parse_file::<isize>(path.join("num_base_addresses"))?;
31        let base_address = Self::parse_base_address_file(&path);
32
33        Some(Self {
34            hw_id,
35            num_instance,
36            major,
37            minor,
38            revision,
39            harvest,
40            num_base_addresses,
41            base_address,
42        })
43    }
44
45    pub fn parse_harvest_file<P: AsRef<Path>>(sysfs_path: P) -> Option<u8> {
46        let s = std::fs::read_to_string(sysfs_path.as_ref().join("harvest")).ok()?;
47        let len = s.len();
48
49        u8::from_str_radix(s.get(2..len-1)?, 16).ok() // "0x0\n"
50    }
51
52    pub fn parse_base_address_file<P: AsRef<Path>>(sysfs_path: P) -> Vec<u32> {
53        let mut base_addr = Vec::with_capacity(8);
54        let Ok(s) = std::fs::read_to_string(sysfs_path.as_ref().join("base_addr")) else { return base_addr };
55        let lines = s.lines();
56
57        for l in lines {
58            /* "0x0000" */
59            let Some(addr) = l.get(2..).and_then(|s| u32::from_str_radix(s, 16).ok()) else {
60                continue
61            };
62
63            base_addr.push(addr);
64        }
65
66        base_addr
67    }
68
69    pub fn parse_file<T: std::str::FromStr>(path: PathBuf) -> Option<T> {
70        let s = std::fs::read_to_string(path).ok()?;
71
72        if s.is_empty() { return None }
73
74        let len = s.len();
75
76        s.get(..len-1)?.parse::<T>().ok()
77    }
78
79    pub fn version(&self) -> (u8, u8, u8) {
80        (self.major, self.minor, self.revision)
81    }
82}
83
84#[derive(Debug, Clone)]
85pub struct IpHwId {
86    pub hw_id: HwId,
87    pub instances: Vec<IpHwInstance>,
88}
89
90impl IpHwId {
91    /// die_id_path: `ip_discovery/die/#die/`
92    pub fn get_from_die_id_sysfs<P: AsRef<Path>>(hw_id: HwId, die_id_path: P) -> Result<Self, std::io::Error> {
93        Self::get_from_ip_hw_sysfs(hw_id, die_id_path.as_ref().join(hw_id.to_string()))
94    }
95
96    /// ip_hw_path: `ip_discovery/die/#die/#hw_id/`
97    pub fn get_from_ip_hw_sysfs<P: AsRef<Path>>(hw_id: HwId, ip_hw_path: P) -> Result<Self, std::io::Error> {
98        let path = ip_hw_path.as_ref();
99        let inst_count = std::fs::read_dir(path)?.count(); // use count for the order
100
101        Ok(IpHwId {
102            hw_id,
103            instances: (0..inst_count).filter_map(|i| {
104                let path = path.join(i.to_string());
105                IpHwInstance::get_from_instance_sysfs(path)
106            }).collect(),
107        })
108    }
109}
110
111#[derive(Debug, Clone)]
112pub struct IpDieEntry {
113    pub die_id: usize,
114    pub ip_hw_ids: Vec<IpHwId>,
115}
116
117impl IpDieEntry {
118    pub fn get_all_entries_from_sysfs<P: Into<PathBuf>>(sysfs_path: P) -> Vec<Self> {
119        let path = sysfs_path.into().join("ip_discovery/die/");
120        let Ok(dies) = std::fs::read_dir(&path) else { return Vec::new() };
121        let die_count = dies.count(); // use count for the order
122
123        (0..die_count).filter_map(|die_id| {
124            Self::get_from_sysfs_with_die_id(die_id, &path)
125        }).collect()
126    }
127
128    /// `ip_discovery/die/#die/`
129    pub fn get_from_die_sysfs<P: AsRef<Path>>(sysfs_path: P) -> Option<Self> {
130        let path = sysfs_path.as_ref();
131        let die_id: usize = path.file_name()?.to_str()?.parse().ok()?;
132        Self::get_from_sysfs_with_die_id(die_id, path.join("../"))
133    }
134
135    pub fn get_from_sysfs_with_die_id<P: AsRef<Path>>(die_id: usize, sysfs_path: P) -> Option<Self> {
136        let die_path = sysfs_path.as_ref().join(die_id.to_string());
137        let die = std::fs::read_dir(&die_path).ok()?;
138        let mut ip_hw: Vec<isize> = die.filter_map(|ip_hw| {
139            ip_hw.ok()?.file_name().to_str()?.parse().ok()
140        }).collect();
141
142        ip_hw.sort();
143
144        let ip_hw_ids = ip_hw.iter().filter_map(|hw_id| {
145            let ip_hw_path = die_path.join(hw_id.to_string());
146            IpHwId::get_from_ip_hw_sysfs(HwId::from(*hw_id), &ip_hw_path).ok()
147        }).collect();
148
149        Some(Self{ die_id, ip_hw_ids })
150    }
151
152    pub fn vec_ip_hw_id_to_hashmap(&self) -> HashMap<HwId, IpHwId> {
153        self.ip_hw_ids.iter().map(|ip_hw_id| (ip_hw_id.hw_id, ip_hw_id.clone())).collect()
154    }
155}
156
157/* ref: drivers/gpu/drm/amd/include/soc15_hw_ip.h */
158const MP1_HWID: isize = 1;
159const MP2_HWID: isize = 2;
160const THM_HWID: isize = 3;
161const SMUIO_HWID: isize = 4;
162const FUSE_HWID: isize = 5;
163const CLKA_HWID: isize = 6;
164const PWR_HWID: isize = 10;
165const GC_HWID: isize = 11;
166const UVD_HWID: isize = 12;
167// const VCN_HWID: isize = UVD_HWID;
168const AUDIO_AZ_HWID: isize = 13;
169const ACP_HWID: isize = 14;
170const DCI_HWID: isize = 15;
171const DMU_HWID: isize = 271;
172const DCO_HWID: isize = 16;
173const DIO_HWID: isize = 272;
174const XDMA_HWID: isize = 17;
175const DCEAZ_HWID: isize = 18;
176const DAZ_HWID: isize = 274;
177const SDPMUX_HWID: isize = 19;
178const NTB_HWID: isize = 20;
179const VPE_HWID: isize = 21;
180const IOHC_HWID: isize = 24;
181const L2IMU_HWID: isize = 28;
182const VCE_HWID: isize = 32;
183const MMHUB_HWID: isize = 34;
184const ATHUB_HWID: isize = 35;
185const DBGU_NBIO_HWID: isize = 36;
186const DFX_HWID: isize = 37;
187const DBGU0_HWID: isize = 38;
188const DBGU1_HWID: isize = 39;
189const OSSSYS_HWID: isize = 40;
190const HDP_HWID: isize = 41;
191const SDMA0_HWID: isize = 42;
192const SDMA1_HWID: isize = 43;
193const ISP_HWID: isize = 44;
194const DBGU_IO_HWID: isize = 45;
195const DF_HWID: isize = 46;
196const CLKB_HWID: isize = 47;
197const FCH_HWID: isize = 48;
198const DFX_DAP_HWID: isize = 49;
199const L1IMU_PCIE_HWID: isize = 50;
200const L1IMU_NBIF_HWID: isize = 51;
201const L1IMU_IOAGR_HWID: isize = 52;
202const L1IMU3_HWID: isize = 53;
203const L1IMU4_HWID: isize = 54;
204const L1IMU5_HWID: isize = 55;
205const L1IMU6_HWID: isize = 56;
206const L1IMU7_HWID: isize = 57;
207const L1IMU8_HWID: isize = 58;
208const L1IMU9_HWID: isize = 59;
209const L1IMU10_HWID: isize = 60;
210const L1IMU11_HWID: isize = 61;
211const L1IMU12_HWID: isize = 62;
212const L1IMU13_HWID: isize = 63;
213const L1IMU14_HWID: isize = 64;
214const L1IMU15_HWID: isize = 65;
215const WAFLC_HWID: isize = 66;
216const FCH_USB_PD_HWID: isize = 67;
217const SDMA2_HWID: isize = 68;
218const SDMA3_HWID: isize = 69;
219const PCIE_HWID: isize = 70;
220const PCS_HWID: isize = 80;
221const DDCL_HWID: isize = 89;
222const SST_HWID: isize = 90;
223const LSDMA_HWID: isize = 91;
224const IOAGR_HWID: isize = 100;
225const NBIF_HWID: isize = 108;
226const IOAPIC_HWID: isize = 124;
227const SYSTEMHUB_HWID: isize = 128;
228const NTBCCP_HWID: isize = 144;
229const UMC_HWID: isize = 150;
230const SATA_HWID: isize = 168;
231const USB_HWID: isize = 170;
232const CCXSEC_HWID: isize = 176;
233const XGMI_HWID: isize = 200;
234const XGBE_HWID: isize = 216;
235const MP0_HWID: isize = 255;
236
237#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
238#[repr(isize)]
239pub enum HwId {
240    MP1 = self::MP1_HWID,
241    MP2 = self::MP2_HWID,
242    THM = self::THM_HWID,
243    SMUIO = self::SMUIO_HWID,
244    FUSE = self::FUSE_HWID,
245    CLKA = self::CLKA_HWID,
246    PWR = self::PWR_HWID,
247    GC = self::GC_HWID,
248    UVD = self::UVD_HWID,
249    // VCN = self::VCN_HWID,
250    AUDIO_AZ = self::AUDIO_AZ_HWID,
251    ACP = self::ACP_HWID,
252    DCI = self::DCI_HWID,
253    DMU = self::DMU_HWID,
254    DCO = self::DCO_HWID,
255    DIO = self::DIO_HWID,
256    XDMA = self::XDMA_HWID,
257    DCEAZ = self::DCEAZ_HWID,
258    DAZ = self::DAZ_HWID,
259    SDPMUX = self::SDPMUX_HWID,
260    NTB = self::NTB_HWID,
261    IOHC = self::IOHC_HWID,
262    VPE = self::VPE_HWID,
263    L2IMU = self::L2IMU_HWID,
264    VCE = self::VCE_HWID,
265    MMHUB = self::MMHUB_HWID,
266    ATHUB = self::ATHUB_HWID,
267    DBGU_NBIO = self::DBGU_NBIO_HWID,
268    DFX = self::DFX_HWID,
269    DBGU0 = self::DBGU0_HWID,
270    DBGU1 = self::DBGU1_HWID,
271    OSSSYS = self::OSSSYS_HWID,
272    HDP = self::HDP_HWID,
273    SDMA0 = self::SDMA0_HWID,
274    SDMA1 = self::SDMA1_HWID,
275    ISP = self::ISP_HWID,
276    DBGU_IO = self::DBGU_IO_HWID,
277    DF = self::DF_HWID,
278    CLKB = self::CLKB_HWID,
279    FCH = self::FCH_HWID,
280    DFX_DAP = self::DFX_DAP_HWID,
281    L1IMU_PCIE = self::L1IMU_PCIE_HWID,
282    L1IMU_NBIF = self::L1IMU_NBIF_HWID,
283    L1IMU_IOAGR = self::L1IMU_IOAGR_HWID,
284    L1IMU3 = self::L1IMU3_HWID,
285    L1IMU4 = self::L1IMU4_HWID,
286    L1IMU5 = self::L1IMU5_HWID,
287    L1IMU6 = self::L1IMU6_HWID,
288    L1IMU7 = self::L1IMU7_HWID,
289    L1IMU8 = self::L1IMU8_HWID,
290    L1IMU9 = self::L1IMU9_HWID,
291    L1IMU10 = self::L1IMU10_HWID,
292    L1IMU11 = self::L1IMU11_HWID,
293    L1IMU12 = self::L1IMU12_HWID,
294    L1IMU13 = self::L1IMU13_HWID,
295    L1IMU14 = self::L1IMU14_HWID,
296    L1IMU15 = self::L1IMU15_HWID,
297    WAFLC = self::WAFLC_HWID,
298    FCH_USB_PD = self::FCH_USB_PD_HWID,
299    SDMA2 = self::SDMA2_HWID,
300    SDMA3 = self::SDMA3_HWID,
301    PCIE = self::PCIE_HWID,
302    PCS = self::PCS_HWID,
303    DDCL = self::DDCL_HWID,
304    SST = self::SST_HWID,
305    LSDMA = self::LSDMA_HWID,
306    IOAGR = self::IOAGR_HWID,
307    NBIF = self::NBIF_HWID,
308    IOAPIC = self::IOAPIC_HWID,
309    SYSTEMHUB = self::SYSTEMHUB_HWID,
310    NTBCCP = self::NTBCCP_HWID,
311    UMC = self::UMC_HWID,
312    SATA = self::SATA_HWID,
313    USB = self::USB_HWID,
314    CCXSEC = self::CCXSEC_HWID,
315    XGMI = self::XGMI_HWID,
316    XGBE = self::XGBE_HWID,
317    MP0 = self::MP0_HWID,
318    Unknown(isize),
319}
320
321impl From<isize> for HwId {
322    fn from(hw_id: isize) -> Self {
323        match hw_id {
324            self::MP1_HWID => Self::MP1,
325            self::MP2_HWID => Self::MP2,
326            self::THM_HWID => Self::THM,
327            self::SMUIO_HWID => Self::SMUIO,
328            self::FUSE_HWID => Self::FUSE,
329            self::CLKA_HWID => Self::CLKA,
330            self::PWR_HWID => Self::PWR,
331            self::GC_HWID => Self::GC,
332            self::UVD_HWID => Self::UVD,
333            self::AUDIO_AZ_HWID => Self::AUDIO_AZ,
334            self::ACP_HWID => Self::ACP,
335            self::DCI_HWID => Self::DCI,
336            self::DMU_HWID => Self::DMU,
337            self::DCO_HWID => Self::DCO,
338            self::DIO_HWID => Self::DIO,
339            self::XDMA_HWID => Self::XDMA,
340            self::DCEAZ_HWID => Self::DCEAZ,
341            self::DAZ_HWID => Self::DAZ,
342            self::SDPMUX_HWID => Self::SDPMUX,
343            self::NTB_HWID => Self::NTB,
344            self::IOHC_HWID => Self::IOHC,
345            self::VPE_HWID => Self::VPE,
346            self::L2IMU_HWID => Self::L2IMU,
347            self::VCE_HWID => Self::VCE,
348            self::MMHUB_HWID => Self::MMHUB,
349            self::ATHUB_HWID => Self::ATHUB,
350            self::DBGU_NBIO_HWID => Self::DBGU_NBIO,
351            self::DFX_HWID => Self::DFX,
352            self::DBGU0_HWID => Self::DBGU0,
353            self::DBGU1_HWID => Self::DBGU1,
354            self::OSSSYS_HWID => Self::OSSSYS,
355            self::HDP_HWID => Self::HDP,
356            self::SDMA0_HWID => Self::SDMA0,
357            self::SDMA1_HWID => Self::SDMA1,
358            self::ISP_HWID => Self::ISP,
359            self::DBGU_IO_HWID => Self::DBGU_IO,
360            self::DF_HWID => Self::DF,
361            self::CLKB_HWID => Self::CLKB,
362            self::FCH_HWID => Self::FCH,
363            self::DFX_DAP_HWID => Self::DFX_DAP,
364            self::L1IMU_PCIE_HWID => Self::L1IMU_PCIE,
365            self::L1IMU_NBIF_HWID => Self::L1IMU_NBIF,
366            self::L1IMU_IOAGR_HWID => Self::L1IMU_IOAGR,
367            self::L1IMU3_HWID => Self::L1IMU3,
368            self::L1IMU4_HWID => Self::L1IMU4,
369            self::L1IMU5_HWID => Self::L1IMU5,
370            self::L1IMU6_HWID => Self::L1IMU6,
371            self::L1IMU7_HWID => Self::L1IMU7,
372            self::L1IMU8_HWID => Self::L1IMU8,
373            self::L1IMU9_HWID => Self::L1IMU9,
374            self::L1IMU10_HWID => Self::L1IMU10,
375            self::L1IMU11_HWID => Self::L1IMU11,
376            self::L1IMU12_HWID => Self::L1IMU12,
377            self::L1IMU13_HWID => Self::L1IMU13,
378            self::L1IMU14_HWID => Self::L1IMU14,
379            self::L1IMU15_HWID => Self::L1IMU15,
380            self::WAFLC_HWID => Self::WAFLC,
381            self::FCH_USB_PD_HWID => Self::FCH_USB_PD,
382            self::SDMA2_HWID => Self::SDMA2,
383            self::SDMA3_HWID => Self::SDMA3,
384            self::PCIE_HWID => Self::PCIE,
385            self::PCS_HWID => Self::PCS,
386            self::DDCL_HWID => Self::DDCL,
387            self::SST_HWID => Self::SST,
388            self::LSDMA_HWID => Self::LSDMA,
389            self::IOAGR_HWID => Self::IOAGR,
390            self::NBIF_HWID => Self::NBIF,
391            self::IOAPIC_HWID => Self::IOAPIC,
392            self::SYSTEMHUB_HWID => Self::SYSTEMHUB,
393            self::NTBCCP_HWID => Self::NTBCCP,
394            self::UMC_HWID => Self::UMC,
395            self::SATA_HWID => Self::SATA,
396            self::USB_HWID => Self::USB,
397            self::CCXSEC_HWID => Self::CCXSEC,
398            self::XGMI_HWID => Self::XGMI,
399            self::XGBE_HWID => Self::XGBE,
400            self::MP0_HWID => Self::MP0,
401            _ => Self::Unknown(hw_id),
402        }
403    }
404}
405
406use std::fmt;
407impl fmt::Display for HwId {
408    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
409        write!(f, "{:?}", self)
410    }
411}