xref: /DragonOS/kernel/src/exception/sysfs.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1 use alloc::{string::ToString, sync::Arc};
2 use log::warn;
3 use system_error::SystemError;
4 use unified_init::macros::unified_init;
5 
6 use crate::{
7     driver::base::{
8         kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps},
9         kset::KSet,
10     },
11     filesystem::{
12         sysfs::{
13             file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport,
14             SYSFS_ATTR_MODE_RO,
15         },
16         vfs::syscall::ModeType,
17     },
18     init::initcall::INITCALL_POSTCORE,
19     misc::ksysfs::sys_kernel_kset,
20 };
21 
22 use super::{
23     irqdesc::{irq_desc_manager, IrqDesc},
24     IrqNumber,
25 };
26 
27 /// `/sys/kernel/irq`的kset
28 static mut SYS_KERNEL_IRQ_KSET_INSTANCE: Option<Arc<KSet>> = None;
29 
30 #[inline(always)]
31 #[allow(dead_code)]
sys_kernel_irq_kset() -> Arc<KSet>32 pub fn sys_kernel_irq_kset() -> Arc<KSet> {
33     unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.clone().unwrap() }
34 }
35 
36 /// 中断描述符的kobjtype
37 ///
38 /// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#280
39 #[derive(Debug)]
40 pub(super) struct IrqKObjType;
41 
42 impl KObjType for IrqKObjType {
sysfs_ops(&self) -> Option<&dyn SysFSOps>43     fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
44         Some(&KObjectSysFSOps)
45     }
46 
attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>47     fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
48         Some(&[&IrqAttrGroup])
49     }
50 
release(&self, _kobj: Arc<dyn KObject>)51     fn release(&self, _kobj: Arc<dyn KObject>) {
52 
53         // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#428
54     }
55 }
56 
57 #[derive(Debug)]
58 struct IrqAttrGroup;
59 
60 impl AttributeGroup for IrqAttrGroup {
name(&self) -> Option<&str>61     fn name(&self) -> Option<&str> {
62         None
63     }
64 
65     /// 所有的属性
66     ///
67     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#268
attrs(&self) -> &[&'static dyn Attribute]68     fn attrs(&self) -> &[&'static dyn Attribute] {
69         // 每个irq的属性
70         // todo: 添加per_cpu_count属性
71         &[
72             &AttrChipName,
73             &AttrHardwareIrq,
74             &AttrType,
75             &AttrWakeup,
76             &AttrName,
77             &AttrActions,
78         ]
79     }
80 
is_visible( &self, _kobj: Arc<dyn KObject>, attr: &'static dyn Attribute, ) -> Option<ModeType>81     fn is_visible(
82         &self,
83         _kobj: Arc<dyn KObject>,
84         attr: &'static dyn Attribute,
85     ) -> Option<ModeType> {
86         Some(attr.mode())
87     }
88 }
89 
90 /// 初始化irq模块在sysfs中的目录
91 ///
92 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#313
93 #[unified_init(INITCALL_POSTCORE)]
irq_sysfs_init() -> Result<(), SystemError>94 fn irq_sysfs_init() -> Result<(), SystemError> {
95     // todo!("irq_sysfs_init");
96 
97     let irq_kset = KSet::new("irq".to_string());
98     irq_kset
99         .register(Some(sys_kernel_kset()))
100         .expect("register irq kset failed");
101     unsafe {
102         SYS_KERNEL_IRQ_KSET_INSTANCE = Some(irq_kset);
103     }
104 
105     // 把所有的irq都注册到/sys/kernel/irq
106     for (irq, desc) in irq_desc_manager().iter_descs() {
107         irq_sysfs_add(irq, desc);
108     }
109 
110     return Ok(());
111 }
112 
113 /// 把irqdesc添加到sysfs
irq_sysfs_add(irq: &IrqNumber, desc: &Arc<IrqDesc>)114 fn irq_sysfs_add(irq: &IrqNumber, desc: &Arc<IrqDesc>) {
115     if unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.is_none() } {
116         return;
117     }
118 
119     let kset = sys_kernel_irq_kset();
120     KObjectManager::add_kobj(desc.clone() as Arc<dyn KObject>, Some(kset)).unwrap_or_else(|e| {
121         warn!("Failed to add irq({irq:?}) kobject to sysfs: {:?}", e);
122     });
123 
124     desc.mark_in_sysfs();
125 }
126 
127 /// 从sysfs中删除irqdesc
128 #[allow(dead_code)]
irq_sysfs_del(desc: &Arc<IrqDesc>)129 pub(super) fn irq_sysfs_del(desc: &Arc<IrqDesc>) {
130     if desc.in_sysfs() {
131         KObjectManager::remove_kobj(desc.clone() as Arc<dyn KObject>);
132         desc.mark_not_in_sysfs();
133     }
134 }
135 #[derive(Debug)]
136 struct AttrChipName;
137 
138 impl Attribute for AttrChipName {
name(&self) -> &str139     fn name(&self) -> &str {
140         "chip_name"
141     }
142 
mode(&self) -> ModeType143     fn mode(&self) -> ModeType {
144         SYSFS_ATTR_MODE_RO
145     }
146 
support(&self) -> SysFSOpsSupport147     fn support(&self) -> SysFSOpsSupport {
148         SysFSOpsSupport::ATTR_SHOW
149     }
150 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>151     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
152         let irq_desc = kobj
153             .arc_any()
154             .downcast::<IrqDesc>()
155             .map_err(|_| SystemError::EINVAL)?;
156 
157         let chip = irq_desc.irq_data().chip_info_read_irqsave().chip();
158         let name = chip.name();
159         let len = core::cmp::min(name.len() + 1, buf.len());
160         let name = format!("{}\n", name);
161         buf[..len].copy_from_slice(name.as_bytes());
162         return Ok(len);
163     }
164 }
165 
166 #[derive(Debug)]
167 struct AttrHardwareIrq;
168 
169 impl Attribute for AttrHardwareIrq {
name(&self) -> &str170     fn name(&self) -> &str {
171         "hwirq"
172     }
173 
mode(&self) -> ModeType174     fn mode(&self) -> ModeType {
175         SYSFS_ATTR_MODE_RO
176     }
177 
support(&self) -> SysFSOpsSupport178     fn support(&self) -> SysFSOpsSupport {
179         SysFSOpsSupport::ATTR_SHOW
180     }
181 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>182     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
183         let irq_desc = kobj
184             .arc_any()
185             .downcast::<IrqDesc>()
186             .map_err(|_| SystemError::EINVAL)?;
187         let hwirq = irq_desc.hardware_irq();
188         return sysfs_emit_str(buf, &format!("{}\n", hwirq.data()));
189     }
190 }
191 
192 #[derive(Debug)]
193 struct AttrType;
194 
195 impl Attribute for AttrType {
name(&self) -> &str196     fn name(&self) -> &str {
197         "type"
198     }
199 
mode(&self) -> ModeType200     fn mode(&self) -> ModeType {
201         SYSFS_ATTR_MODE_RO
202     }
203 
support(&self) -> SysFSOpsSupport204     fn support(&self) -> SysFSOpsSupport {
205         SysFSOpsSupport::ATTR_SHOW
206     }
207 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>208     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
209         let irq_desc = kobj
210             .arc_any()
211             .downcast::<IrqDesc>()
212             .map_err(|_| SystemError::EINVAL)?;
213         let irq_type = if irq_desc.irq_data().is_level_type() {
214             "level"
215         } else {
216             "edge"
217         };
218 
219         return sysfs_emit_str(buf, &format!("{}\n", irq_type));
220     }
221 }
222 
223 #[derive(Debug)]
224 struct AttrWakeup;
225 
226 impl Attribute for AttrWakeup {
name(&self) -> &str227     fn name(&self) -> &str {
228         "wakeup"
229     }
230 
mode(&self) -> ModeType231     fn mode(&self) -> ModeType {
232         SYSFS_ATTR_MODE_RO
233     }
234 
support(&self) -> SysFSOpsSupport235     fn support(&self) -> SysFSOpsSupport {
236         SysFSOpsSupport::ATTR_SHOW
237     }
238 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>239     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
240         let irq_desc = kobj
241             .arc_any()
242             .downcast::<IrqDesc>()
243             .map_err(|_| SystemError::EINVAL)?;
244         let wakeup = irq_desc.irq_data().is_wakeup_set();
245         return sysfs_emit_str(buf, &format!("{}\n", wakeup));
246     }
247 }
248 
249 #[derive(Debug)]
250 struct AttrName;
251 
252 impl Attribute for AttrName {
name(&self) -> &str253     fn name(&self) -> &str {
254         "name"
255     }
256 
mode(&self) -> ModeType257     fn mode(&self) -> ModeType {
258         SYSFS_ATTR_MODE_RO
259     }
260 
support(&self) -> SysFSOpsSupport261     fn support(&self) -> SysFSOpsSupport {
262         SysFSOpsSupport::ATTR_SHOW
263     }
264 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>265     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
266         let irq_desc = kobj
267             .arc_any()
268             .downcast::<IrqDesc>()
269             .map_err(|_| SystemError::EINVAL)?;
270 
271         if let Some(name) = irq_desc.name() {
272             return sysfs_emit_str(buf, &format!("{}\n", name));
273         }
274 
275         return Ok(0);
276     }
277 }
278 
279 #[derive(Debug)]
280 struct AttrActions;
281 
282 impl Attribute for AttrActions {
name(&self) -> &str283     fn name(&self) -> &str {
284         "actions"
285     }
286 
mode(&self) -> ModeType287     fn mode(&self) -> ModeType {
288         SYSFS_ATTR_MODE_RO
289     }
290 
support(&self) -> SysFSOpsSupport291     fn support(&self) -> SysFSOpsSupport {
292         SysFSOpsSupport::ATTR_SHOW
293     }
294 
show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError>295     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
296         let irq_desc = kobj
297             .arc_any()
298             .downcast::<IrqDesc>()
299             .map_err(|_| SystemError::EINVAL)?;
300 
301         let actions = irq_desc.actions();
302         let mut len = 0;
303 
304         for action in actions {
305             if len != 0 {
306                 len += sysfs_emit_str(&mut buf[len..], &format!(",{}", action.inner().name()))
307                     .unwrap();
308             } else {
309                 len += sysfs_emit_str(&mut buf[len..], &action.inner().name().to_string()).unwrap();
310             }
311 
312             if len >= buf.len() {
313                 break;
314             }
315         }
316 
317         if len != 0 && len < buf.len() {
318             len += sysfs_emit_str(&mut buf[len..], "\n").unwrap();
319         }
320 
321         return Ok(len);
322     }
323 }
324