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