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