xref: /DragonOS/kernel/src/exception/softirq.rs (revision 91e9d4ab55ef960f57a1b6287bc523ca4341f67a)
1 use core::{
2     fmt::Debug,
3     intrinsics::unlikely,
4     mem::{self, MaybeUninit},
5     ptr::null_mut,
6     sync::atomic::{compiler_fence, Ordering},
7 };
8 
9 use alloc::{boxed::Box, sync::Arc};
10 use num_traits::FromPrimitive;
11 use system_error::SystemError;
12 
13 use crate::{
14     arch::CurrentIrqArch, exception::InterruptArch, kdebug, kinfo, libs::rwlock::RwLock,
15     mm::percpu::PerCpu, process::ProcessManager, smp::core::smp_get_processor_id,
16     time::timer::clock,
17 };
18 
19 const MAX_SOFTIRQ_NUM: u64 = 64;
20 const MAX_SOFTIRQ_RESTART: i32 = 20;
21 
22 static mut __CPU_PENDING: Option<Box<[VecStatus; PerCpu::MAX_CPU_NUM]>> = None;
23 static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut();
24 
25 #[no_mangle]
26 pub extern "C" fn rs_softirq_init() {
27     softirq_init().expect("softirq_init failed");
28 }
29 
30 pub fn softirq_init() -> Result<(), SystemError> {
31     kinfo!("Initializing softirq...");
32     unsafe {
33         __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new()));
34         __CPU_PENDING = Some(Box::new(
35             [VecStatus::default(); PerCpu::MAX_CPU_NUM as usize],
36         ));
37         let cpu_pending = __CPU_PENDING.as_mut().unwrap();
38         for i in 0..PerCpu::MAX_CPU_NUM {
39             cpu_pending[i as usize] = VecStatus::default();
40         }
41     }
42     kinfo!("Softirq initialized.");
43     return Ok(());
44 }
45 
46 #[inline(always)]
47 pub fn softirq_vectors() -> &'static mut Softirq {
48     unsafe {
49         return __SORTIRQ_VECTORS.as_mut().unwrap();
50     }
51 }
52 
53 #[inline(always)]
54 fn cpu_pending(cpu_id: usize) -> &'static mut VecStatus {
55     unsafe {
56         return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id];
57     }
58 }
59 
60 /// 软中断向量号码
61 #[allow(dead_code)]
62 #[repr(u8)]
63 #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)]
64 pub enum SoftirqNumber {
65     /// 时钟软中断信号
66     TIMER = 0,
67     VideoRefresh = 1, //帧缓冲区刷新软中断
68 }
69 
70 impl From<u64> for SoftirqNumber {
71     fn from(value: u64) -> Self {
72         return <Self as FromPrimitive>::from_u64(value).unwrap();
73     }
74 }
75 
76 bitflags! {
77     #[derive(Default)]
78     pub struct VecStatus: u64 {
79         const TIMER = 1 << 0;
80         const VIDEO_REFRESH = 1 << 1;
81     }
82 }
83 
84 impl From<SoftirqNumber> for VecStatus {
85     fn from(value: SoftirqNumber) -> Self {
86         return Self::from_bits_truncate(1 << (value as u64));
87     }
88 }
89 
90 pub trait SoftirqVec: Send + Sync + Debug {
91     fn run(&self);
92 }
93 
94 #[derive(Debug)]
95 pub struct Softirq {
96     table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>,
97 }
98 impl Softirq {
99     fn new() -> Softirq {
100         let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] =
101             unsafe { MaybeUninit::uninit().assume_init() };
102 
103         for i in 0..MAX_SOFTIRQ_NUM {
104             data[i as usize] = MaybeUninit::new(None);
105         }
106 
107         let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe {
108             mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data)
109         };
110 
111         return Softirq {
112             table: RwLock::new(data),
113         };
114     }
115 
116     /// @brief 注册软中断向量
117     ///
118     /// @param softirq_num 中断向量号
119     ///
120     /// @param hanlder 中断函数对应的结构体
121     pub fn register_softirq(
122         &self,
123         softirq_num: SoftirqNumber,
124         handler: Arc<dyn SoftirqVec>,
125     ) -> Result<i32, SystemError> {
126         // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64);
127 
128         // let self = &mut SOFTIRQ_VECTORS.lock();
129         // 判断该软中断向量是否已经被注册
130         let mut table_guard = self.table.write();
131         if table_guard[softirq_num as usize].is_some() {
132             // kdebug!("register_softirq failed");
133 
134             return Err(SystemError::EINVAL);
135         }
136         table_guard[softirq_num as usize] = Some(handler);
137         drop(table_guard);
138 
139         // kdebug!(
140         //     "register_softirq successfully, softirq_num = {:?}",
141         //     softirq_num as u64
142         // );
143         compiler_fence(Ordering::SeqCst);
144         return Ok(0);
145     }
146 
147     /// @brief 解注册软中断向量
148     ///
149     /// @param irq_num 中断向量号码
150     pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) {
151         // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64);
152         let mut table_guard = self.table.write();
153         // 将软中断向量清空
154         table_guard[softirq_num as usize] = None;
155         drop(table_guard);
156         // 将对应位置的pending和runing都置0
157         // self.running.lock().set(VecStatus::from(softirq_num), false);
158         // 将对应CPU的pending置0
159         compiler_fence(Ordering::SeqCst);
160         cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false);
161         compiler_fence(Ordering::SeqCst);
162     }
163 
164     pub fn do_softirq(&self) {
165         // TODO pcb的flags未修改
166         // todo: 是否需要判断在当前cpu上面,该函数的嵌套层数?(防止爆栈)
167         let end = clock() + 500 * 2;
168         let cpu_id = smp_get_processor_id();
169         let mut max_restart = MAX_SOFTIRQ_RESTART;
170         loop {
171             compiler_fence(Ordering::SeqCst);
172             let pending = cpu_pending(cpu_id as usize).bits;
173             cpu_pending(cpu_id as usize).bits = 0;
174             compiler_fence(Ordering::SeqCst);
175 
176             unsafe { CurrentIrqArch::interrupt_enable() };
177             if pending != 0 {
178                 for i in 0..MAX_SOFTIRQ_NUM {
179                     if pending & (1 << i) == 0 {
180                         continue;
181                     }
182 
183                     let table_guard = self.table.read();
184                     let softirq_func = table_guard[i as usize].clone();
185                     drop(table_guard);
186                     if softirq_func.is_none() {
187                         continue;
188                     }
189 
190                     let prev_count: usize = ProcessManager::current_pcb().preempt_count();
191 
192                     softirq_func.as_ref().unwrap().run();
193                     if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) {
194                         kdebug!(
195                             "entered softirq {:?} with preempt_count {:?},exited with {:?}",
196                             i,
197                             prev_count,
198                             ProcessManager::current_pcb().preempt_count()
199                         );
200                         unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) };
201                     }
202                 }
203             }
204             unsafe { CurrentIrqArch::interrupt_disable() };
205             max_restart -= 1;
206             compiler_fence(Ordering::SeqCst);
207             if cpu_pending(cpu_id as usize).is_empty() {
208                 compiler_fence(Ordering::SeqCst);
209                 if clock() < end && max_restart > 0 {
210                     continue;
211                 } else {
212                     break;
213                 }
214             } else {
215                 // TODO:当有softirqd时 唤醒它
216                 break;
217             }
218         }
219     }
220 
221     pub fn raise_softirq(&self, softirq_num: SoftirqNumber) {
222         let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
223         let processor_id = smp_get_processor_id() as usize;
224 
225         cpu_pending(processor_id).insert(VecStatus::from(softirq_num));
226 
227         compiler_fence(Ordering::SeqCst);
228 
229         drop(guard);
230         // kdebug!("raise_softirq exited");
231     }
232     pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) {
233         compiler_fence(Ordering::SeqCst);
234         cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num));
235         compiler_fence(Ordering::SeqCst);
236     }
237 }
238 
239 // ======= 以下为给C提供的接口 =======
240 #[no_mangle]
241 pub extern "C" fn rs_raise_softirq(softirq_num: u32) {
242     softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64));
243 }
244 
245 #[no_mangle]
246 pub extern "C" fn rs_unregister_softirq(softirq_num: u32) {
247     softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64));
248 }
249 
250 #[no_mangle]
251 pub extern "C" fn rs_do_softirq() {
252     softirq_vectors().do_softirq();
253 }
254 
255 #[no_mangle]
256 pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) {
257     unsafe {
258         softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64));
259     }
260 }
261