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