1*bacd691cSlogin use core::{ 2*bacd691cSlogin fmt::Debug, 3*bacd691cSlogin intrinsics::unlikely, 4*bacd691cSlogin mem::{self, MaybeUninit}, 5*bacd691cSlogin ptr::null_mut, 6*bacd691cSlogin sync::atomic::{compiler_fence, Ordering}, 7*bacd691cSlogin }; 862e46139SGou Ngai 9*bacd691cSlogin use alloc::{boxed::Box, sync::Arc}; 10*bacd691cSlogin use num_traits::FromPrimitive; 1162e46139SGou Ngai 1262e46139SGou Ngai use crate::{ 13*bacd691cSlogin arch::{ 14*bacd691cSlogin asm::{ 15*bacd691cSlogin current::current_pcb, 16*bacd691cSlogin irqflags::{local_irq_restore, local_irq_save}, 17*bacd691cSlogin }, 18*bacd691cSlogin interrupt::{cli, sti}, 19*bacd691cSlogin }, 20*bacd691cSlogin include::bindings::bindings::MAX_CPU_NUM, 21*bacd691cSlogin kdebug, kinfo, 22*bacd691cSlogin libs::rwlock::RwLock, 23*bacd691cSlogin smp::core::smp_get_processor_id, 24*bacd691cSlogin syscall::SystemError, 25*bacd691cSlogin time::timer::clock, 2662e46139SGou Ngai }; 2762e46139SGou Ngai 2862e46139SGou Ngai const MAX_SOFTIRQ_NUM: u64 = 64; 29*bacd691cSlogin const MAX_SOFTIRQ_RESTART: i32 = 20; 30*bacd691cSlogin 31*bacd691cSlogin static mut __CPU_PENDING: Option<Box<[VecStatus; MAX_CPU_NUM as usize]>> = None; 32*bacd691cSlogin static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut(); 33*bacd691cSlogin 34*bacd691cSlogin #[no_mangle] 35*bacd691cSlogin pub extern "C" fn rs_softirq_init() { 36*bacd691cSlogin softirq_init().expect("softirq_init failed"); 37*bacd691cSlogin } 38*bacd691cSlogin 39*bacd691cSlogin pub fn softirq_init() -> Result<(), SystemError> { 40*bacd691cSlogin kinfo!("Initializing softirq..."); 41*bacd691cSlogin unsafe { 42*bacd691cSlogin __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new())); 43*bacd691cSlogin __CPU_PENDING = Some(Box::new([VecStatus::default(); MAX_CPU_NUM as usize])); 44*bacd691cSlogin let cpu_pending = __CPU_PENDING.as_mut().unwrap(); 45*bacd691cSlogin for i in 0..MAX_CPU_NUM { 46*bacd691cSlogin cpu_pending[i as usize] = VecStatus::default(); 47*bacd691cSlogin } 48*bacd691cSlogin } 49*bacd691cSlogin return Ok(()); 50*bacd691cSlogin } 51*bacd691cSlogin 52*bacd691cSlogin #[inline(always)] 53*bacd691cSlogin pub fn softirq_vectors() -> &'static mut Softirq { 54*bacd691cSlogin unsafe { 55*bacd691cSlogin return __SORTIRQ_VECTORS.as_mut().unwrap(); 56*bacd691cSlogin } 57*bacd691cSlogin } 58*bacd691cSlogin 59*bacd691cSlogin #[inline(always)] 60*bacd691cSlogin fn cpu_pending(cpu_id: usize) -> &'static mut VecStatus { 61*bacd691cSlogin unsafe { 62*bacd691cSlogin return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id]; 63*bacd691cSlogin } 64*bacd691cSlogin } 6562e46139SGou Ngai 6662e46139SGou Ngai /// 软中断向量号码 6762e46139SGou Ngai #[allow(dead_code)] 6862e46139SGou Ngai #[repr(u8)] 69*bacd691cSlogin #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)] 7062e46139SGou Ngai pub enum SoftirqNumber { 71*bacd691cSlogin /// 时钟软中断信号 72*bacd691cSlogin TIMER = 0, 7362e46139SGou Ngai VideoRefresh = 1, //帧缓冲区刷新软中断 7462e46139SGou Ngai } 7562e46139SGou Ngai 76*bacd691cSlogin impl From<u64> for SoftirqNumber { 77*bacd691cSlogin fn from(value: u64) -> Self { 78*bacd691cSlogin return <Self as FromPrimitive>::from_u64(value).unwrap(); 7962e46139SGou Ngai } 8062e46139SGou Ngai } 8162e46139SGou Ngai 82*bacd691cSlogin bitflags! { 83*bacd691cSlogin #[derive(Default)] 84*bacd691cSlogin pub struct VecStatus: u64 { 85*bacd691cSlogin const TIMER = 1 << 0; 86*bacd691cSlogin const VIDEO_REFRESH = 1 << 1; 87*bacd691cSlogin } 88*bacd691cSlogin } 89*bacd691cSlogin 90*bacd691cSlogin impl From<SoftirqNumber> for VecStatus { 91*bacd691cSlogin fn from(value: SoftirqNumber) -> Self { 92*bacd691cSlogin return Self::from_bits_truncate(1 << (value as u64)); 93*bacd691cSlogin } 94*bacd691cSlogin } 95*bacd691cSlogin 96*bacd691cSlogin pub trait SoftirqVec: Send + Sync + Debug { 97*bacd691cSlogin fn run(&self); 98*bacd691cSlogin } 99*bacd691cSlogin 100*bacd691cSlogin #[derive(Debug)] 10162e46139SGou Ngai pub struct Softirq { 102*bacd691cSlogin table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>, 10362e46139SGou Ngai } 10462e46139SGou Ngai impl Softirq { 105*bacd691cSlogin fn new() -> Softirq { 106*bacd691cSlogin let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] = 107*bacd691cSlogin unsafe { MaybeUninit::uninit().assume_init() }; 108*bacd691cSlogin 109*bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 110*bacd691cSlogin data[i as usize] = MaybeUninit::new(None); 11162e46139SGou Ngai } 11262e46139SGou Ngai 113*bacd691cSlogin let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe { 114*bacd691cSlogin mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data) 115*bacd691cSlogin }; 11662e46139SGou Ngai 117*bacd691cSlogin return Softirq { 118*bacd691cSlogin table: RwLock::new(data), 119*bacd691cSlogin }; 12062e46139SGou Ngai } 12162e46139SGou Ngai 12262e46139SGou Ngai /// @brief 注册软中断向量 123*bacd691cSlogin /// 124*bacd691cSlogin /// @param softirq_num 中断向量号 125*bacd691cSlogin /// 126*bacd691cSlogin /// @param hanlder 中断函数对应的结构体 12762e46139SGou Ngai pub fn register_softirq( 128*bacd691cSlogin &self, 129*bacd691cSlogin softirq_num: SoftirqNumber, 130*bacd691cSlogin handler: Arc<dyn SoftirqVec>, 131*bacd691cSlogin ) -> Result<i32, SystemError> { 132*bacd691cSlogin // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64); 13362e46139SGou Ngai 134*bacd691cSlogin // let self = &mut SOFTIRQ_VECTORS.lock(); 135*bacd691cSlogin // 判断该软中断向量是否已经被注册 136*bacd691cSlogin let mut table_guard = self.table.write(); 137*bacd691cSlogin if table_guard[softirq_num as usize].is_some() { 138*bacd691cSlogin // kdebug!("register_softirq failed"); 139*bacd691cSlogin 140*bacd691cSlogin return Err(SystemError::EINVAL); 14162e46139SGou Ngai } 142*bacd691cSlogin table_guard[softirq_num as usize] = Some(handler); 143*bacd691cSlogin drop(table_guard); 144*bacd691cSlogin 145*bacd691cSlogin // kdebug!( 146*bacd691cSlogin // "register_softirq successfully, softirq_num = {:?}", 147*bacd691cSlogin // softirq_num as u64 148*bacd691cSlogin // ); 149*bacd691cSlogin compiler_fence(Ordering::SeqCst); 150*bacd691cSlogin return Ok(0); 15162e46139SGou Ngai } 15262e46139SGou Ngai 15362e46139SGou Ngai /// @brief 解注册软中断向量 154*bacd691cSlogin /// 15562e46139SGou Ngai /// @param irq_num 中断向量号码 156*bacd691cSlogin pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) { 157*bacd691cSlogin // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64); 158*bacd691cSlogin let table_guard = &mut self.table.write(); 159*bacd691cSlogin // 将软中断向量清空 160*bacd691cSlogin table_guard[softirq_num as usize] = None; 161*bacd691cSlogin drop(table_guard); 162*bacd691cSlogin // 将对应位置的pending和runing都置0 163*bacd691cSlogin // self.running.lock().set(VecStatus::from(softirq_num), false); 164*bacd691cSlogin // 将对应CPU的pending置0 165*bacd691cSlogin compiler_fence(Ordering::SeqCst); 166*bacd691cSlogin cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false); 167*bacd691cSlogin compiler_fence(Ordering::SeqCst); 16862e46139SGou Ngai } 169*bacd691cSlogin 170*bacd691cSlogin pub fn do_softirq(&self) { 171*bacd691cSlogin // TODO pcb的flags未修改 172*bacd691cSlogin // todo: 是否需要判断在当前cpu上面,该函数的嵌套层数?(防止爆栈) 173*bacd691cSlogin let end = clock() + 500 * 2; 174*bacd691cSlogin let cpu_id = smp_get_processor_id(); 175*bacd691cSlogin let mut max_restart = MAX_SOFTIRQ_RESTART; 176*bacd691cSlogin loop { 177*bacd691cSlogin compiler_fence(Ordering::SeqCst); 178*bacd691cSlogin let pending = cpu_pending(cpu_id as usize).bits; 179*bacd691cSlogin cpu_pending(cpu_id as usize).bits = 0; 180*bacd691cSlogin compiler_fence(Ordering::SeqCst); 181*bacd691cSlogin 182*bacd691cSlogin sti(); 183*bacd691cSlogin if pending != 0 { 184*bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 185*bacd691cSlogin if pending & (1 << i) == 0 { 18662e46139SGou Ngai continue; 18762e46139SGou Ngai } 188*bacd691cSlogin 189*bacd691cSlogin let table_guard = self.table.read(); 190*bacd691cSlogin let softirq_func = table_guard[i as usize].clone(); 191*bacd691cSlogin drop(table_guard); 192*bacd691cSlogin if softirq_func.is_none() { 193*bacd691cSlogin continue; 194*bacd691cSlogin } 195*bacd691cSlogin 196*bacd691cSlogin let prev_count = current_pcb().preempt_count; 197*bacd691cSlogin 198*bacd691cSlogin softirq_func.as_ref().unwrap().run(); 199*bacd691cSlogin if unlikely(prev_count != current_pcb().preempt_count) { 200*bacd691cSlogin kdebug!( 201*bacd691cSlogin "entered softirq {:?} with preempt_count {:?},exited with {:?}", 202*bacd691cSlogin i, 203*bacd691cSlogin prev_count, 204*bacd691cSlogin current_pcb().preempt_count 205*bacd691cSlogin ); 206*bacd691cSlogin current_pcb().preempt_count = prev_count; 207*bacd691cSlogin } 208*bacd691cSlogin } 209*bacd691cSlogin } 210*bacd691cSlogin cli(); 211*bacd691cSlogin max_restart -= 1; 212*bacd691cSlogin compiler_fence(Ordering::SeqCst); 213*bacd691cSlogin if cpu_pending(cpu_id as usize).is_empty() { 214*bacd691cSlogin compiler_fence(Ordering::SeqCst); 215*bacd691cSlogin if clock() < end && max_restart > 0 { 216*bacd691cSlogin continue; 217*bacd691cSlogin } else { 218*bacd691cSlogin break; 219*bacd691cSlogin } 220*bacd691cSlogin } else { 221*bacd691cSlogin // TODO:当有softirqd时 唤醒它 22262e46139SGou Ngai break; 22362e46139SGou Ngai } 22462e46139SGou Ngai } 22562e46139SGou Ngai } 22662e46139SGou Ngai 227*bacd691cSlogin pub fn raise_softirq(&self, softirq_num: SoftirqNumber) { 228*bacd691cSlogin let mut flags = 0; 229*bacd691cSlogin local_irq_save(&mut flags); 230*bacd691cSlogin let processor_id = smp_get_processor_id() as usize; 231*bacd691cSlogin 232*bacd691cSlogin cpu_pending(processor_id).insert(VecStatus::from(softirq_num)); 233*bacd691cSlogin 234*bacd691cSlogin compiler_fence(Ordering::SeqCst); 235*bacd691cSlogin 236*bacd691cSlogin local_irq_restore(&flags); 237*bacd691cSlogin // kdebug!("raise_softirq exited"); 23862e46139SGou Ngai } 239*bacd691cSlogin pub fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) { 240*bacd691cSlogin compiler_fence(Ordering::SeqCst); 241*bacd691cSlogin cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num)); 242*bacd691cSlogin compiler_fence(Ordering::SeqCst); 24362e46139SGou Ngai } 24462e46139SGou Ngai } 245*bacd691cSlogin 246*bacd691cSlogin // ======= 以下为给C提供的接口 ======= 247*bacd691cSlogin #[no_mangle] 248*bacd691cSlogin pub extern "C" fn rs_raise_softirq(softirq_num: u32) { 249*bacd691cSlogin softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64)); 25062e46139SGou Ngai } 251*bacd691cSlogin 252*bacd691cSlogin #[no_mangle] 253*bacd691cSlogin pub extern "C" fn rs_unregister_softirq(softirq_num: u32) { 254*bacd691cSlogin softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64)); 25562e46139SGou Ngai } 256*bacd691cSlogin 257*bacd691cSlogin #[no_mangle] 258*bacd691cSlogin pub extern "C" fn rs_do_softirq() { 259*bacd691cSlogin softirq_vectors().do_softirq(); 260*bacd691cSlogin } 261*bacd691cSlogin 262*bacd691cSlogin #[no_mangle] 263*bacd691cSlogin pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) { 264*bacd691cSlogin softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64)); 26562e46139SGou Ngai } 266