1bacd691cSlogin use core::{ 2bacd691cSlogin fmt::Debug, 3bacd691cSlogin intrinsics::unlikely, 4bacd691cSlogin mem::{self, MaybeUninit}, 5bacd691cSlogin ptr::null_mut, 6*0d6cf65aSLoGin sync::atomic::{compiler_fence, AtomicI16, Ordering}, 7bacd691cSlogin }; 862e46139SGou Ngai 9*0d6cf65aSLoGin use alloc::{boxed::Box, sync::Arc, vec::Vec}; 10bacd691cSlogin use num_traits::FromPrimitive; 1191e9d4abSLoGin use system_error::SystemError; 1262e46139SGou Ngai 1362e46139SGou Ngai use crate::{ 14*0d6cf65aSLoGin arch::CurrentIrqArch, 15*0d6cf65aSLoGin exception::InterruptArch, 16*0d6cf65aSLoGin kdebug, kinfo, 17*0d6cf65aSLoGin libs::rwlock::RwLock, 18*0d6cf65aSLoGin mm::percpu::{PerCpu, PerCpuVar}, 19*0d6cf65aSLoGin process::ProcessManager, 20*0d6cf65aSLoGin smp::core::smp_get_processor_id, 2191e9d4abSLoGin time::timer::clock, 2262e46139SGou Ngai }; 2362e46139SGou Ngai 2462e46139SGou Ngai const MAX_SOFTIRQ_NUM: u64 = 64; 25bacd691cSlogin const MAX_SOFTIRQ_RESTART: i32 = 20; 26bacd691cSlogin 2746e234aeSLoGin static mut __CPU_PENDING: Option<Box<[VecStatus; PerCpu::MAX_CPU_NUM]>> = None; 28bacd691cSlogin static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut(); 29bacd691cSlogin 30bacd691cSlogin #[no_mangle] 31bacd691cSlogin pub extern "C" fn rs_softirq_init() { 32bacd691cSlogin softirq_init().expect("softirq_init failed"); 33bacd691cSlogin } 34bacd691cSlogin 35bacd691cSlogin pub fn softirq_init() -> Result<(), SystemError> { 36bacd691cSlogin kinfo!("Initializing softirq..."); 37bacd691cSlogin unsafe { 38bacd691cSlogin __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new())); 3946e234aeSLoGin __CPU_PENDING = Some(Box::new( 4046e234aeSLoGin [VecStatus::default(); PerCpu::MAX_CPU_NUM as usize], 4146e234aeSLoGin )); 42bacd691cSlogin let cpu_pending = __CPU_PENDING.as_mut().unwrap(); 4346e234aeSLoGin for i in 0..PerCpu::MAX_CPU_NUM { 44bacd691cSlogin cpu_pending[i as usize] = VecStatus::default(); 45bacd691cSlogin } 46bacd691cSlogin } 4740fe15e0SLoGin kinfo!("Softirq initialized."); 48bacd691cSlogin return Ok(()); 49bacd691cSlogin } 50bacd691cSlogin 51bacd691cSlogin #[inline(always)] 52bacd691cSlogin pub fn softirq_vectors() -> &'static mut Softirq { 53bacd691cSlogin unsafe { 54bacd691cSlogin return __SORTIRQ_VECTORS.as_mut().unwrap(); 55bacd691cSlogin } 56bacd691cSlogin } 57bacd691cSlogin 58bacd691cSlogin #[inline(always)] 59bacd691cSlogin fn cpu_pending(cpu_id: usize) -> &'static mut VecStatus { 60bacd691cSlogin unsafe { 61bacd691cSlogin return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id]; 62bacd691cSlogin } 63bacd691cSlogin } 6462e46139SGou Ngai 6562e46139SGou Ngai /// 软中断向量号码 6662e46139SGou Ngai #[allow(dead_code)] 6762e46139SGou Ngai #[repr(u8)] 68bacd691cSlogin #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)] 6962e46139SGou Ngai pub enum SoftirqNumber { 70bacd691cSlogin /// 时钟软中断信号 71bacd691cSlogin TIMER = 0, 7262e46139SGou Ngai VideoRefresh = 1, //帧缓冲区刷新软中断 7362e46139SGou Ngai } 7462e46139SGou Ngai 75bacd691cSlogin impl From<u64> for SoftirqNumber { 76bacd691cSlogin fn from(value: u64) -> Self { 77bacd691cSlogin return <Self as FromPrimitive>::from_u64(value).unwrap(); 7862e46139SGou Ngai } 7962e46139SGou Ngai } 8062e46139SGou Ngai 81bacd691cSlogin bitflags! { 82bacd691cSlogin #[derive(Default)] 83bacd691cSlogin pub struct VecStatus: u64 { 84bacd691cSlogin const TIMER = 1 << 0; 85bacd691cSlogin const VIDEO_REFRESH = 1 << 1; 86bacd691cSlogin } 87bacd691cSlogin } 88bacd691cSlogin 89bacd691cSlogin impl From<SoftirqNumber> for VecStatus { 90bacd691cSlogin fn from(value: SoftirqNumber) -> Self { 91bacd691cSlogin return Self::from_bits_truncate(1 << (value as u64)); 92bacd691cSlogin } 93bacd691cSlogin } 94bacd691cSlogin 95bacd691cSlogin pub trait SoftirqVec: Send + Sync + Debug { 96bacd691cSlogin fn run(&self); 97bacd691cSlogin } 98bacd691cSlogin 99bacd691cSlogin #[derive(Debug)] 10062e46139SGou Ngai pub struct Softirq { 101bacd691cSlogin table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>, 102*0d6cf65aSLoGin /// 软中断嵌套层数(per cpu) 103*0d6cf65aSLoGin cpu_running_count: PerCpuVar<AtomicI16>, 10462e46139SGou Ngai } 10562e46139SGou Ngai impl Softirq { 106*0d6cf65aSLoGin /// 每个CPU最大嵌套的软中断数量 107*0d6cf65aSLoGin const MAX_RUNNING_PER_CPU: i16 = 3; 108bacd691cSlogin fn new() -> Softirq { 109bacd691cSlogin let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] = 110bacd691cSlogin unsafe { MaybeUninit::uninit().assume_init() }; 111bacd691cSlogin 112bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 113bacd691cSlogin data[i as usize] = MaybeUninit::new(None); 11462e46139SGou Ngai } 11562e46139SGou Ngai 116bacd691cSlogin let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe { 117bacd691cSlogin mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data) 118bacd691cSlogin }; 11962e46139SGou Ngai 120*0d6cf65aSLoGin let mut percpu_count = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize); 121*0d6cf65aSLoGin percpu_count.resize_with(PerCpu::MAX_CPU_NUM as usize, || AtomicI16::new(0)); 122*0d6cf65aSLoGin let cpu_running_count = PerCpuVar::new(percpu_count).unwrap(); 123*0d6cf65aSLoGin 124bacd691cSlogin return Softirq { 125bacd691cSlogin table: RwLock::new(data), 126*0d6cf65aSLoGin cpu_running_count, 127bacd691cSlogin }; 12862e46139SGou Ngai } 12962e46139SGou Ngai 130*0d6cf65aSLoGin fn cpu_running_count(&self) -> &PerCpuVar<AtomicI16> { 131*0d6cf65aSLoGin return &self.cpu_running_count; 132*0d6cf65aSLoGin } 133*0d6cf65aSLoGin 13462e46139SGou Ngai /// @brief 注册软中断向量 135bacd691cSlogin /// 136bacd691cSlogin /// @param softirq_num 中断向量号 137bacd691cSlogin /// 138bacd691cSlogin /// @param hanlder 中断函数对应的结构体 13962e46139SGou Ngai pub fn register_softirq( 140bacd691cSlogin &self, 141bacd691cSlogin softirq_num: SoftirqNumber, 142bacd691cSlogin handler: Arc<dyn SoftirqVec>, 143bacd691cSlogin ) -> Result<i32, SystemError> { 144bacd691cSlogin // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64); 14562e46139SGou Ngai 146bacd691cSlogin // let self = &mut SOFTIRQ_VECTORS.lock(); 147bacd691cSlogin // 判断该软中断向量是否已经被注册 148*0d6cf65aSLoGin let mut table_guard = self.table.write_irqsave(); 149bacd691cSlogin if table_guard[softirq_num as usize].is_some() { 150bacd691cSlogin // kdebug!("register_softirq failed"); 151bacd691cSlogin 152bacd691cSlogin return Err(SystemError::EINVAL); 15362e46139SGou Ngai } 154bacd691cSlogin table_guard[softirq_num as usize] = Some(handler); 155bacd691cSlogin drop(table_guard); 156bacd691cSlogin 157bacd691cSlogin // kdebug!( 158bacd691cSlogin // "register_softirq successfully, softirq_num = {:?}", 159bacd691cSlogin // softirq_num as u64 160bacd691cSlogin // ); 161bacd691cSlogin compiler_fence(Ordering::SeqCst); 162bacd691cSlogin return Ok(0); 16362e46139SGou Ngai } 16462e46139SGou Ngai 16562e46139SGou Ngai /// @brief 解注册软中断向量 166bacd691cSlogin /// 16762e46139SGou Ngai /// @param irq_num 中断向量号码 168bacd691cSlogin pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) { 169bacd691cSlogin // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64); 170*0d6cf65aSLoGin let mut table_guard = self.table.write_irqsave(); 171bacd691cSlogin // 将软中断向量清空 172bacd691cSlogin table_guard[softirq_num as usize] = None; 173bacd691cSlogin drop(table_guard); 174bacd691cSlogin // 将对应位置的pending和runing都置0 175bacd691cSlogin // self.running.lock().set(VecStatus::from(softirq_num), false); 176bacd691cSlogin // 将对应CPU的pending置0 177bacd691cSlogin compiler_fence(Ordering::SeqCst); 178bacd691cSlogin cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false); 179bacd691cSlogin compiler_fence(Ordering::SeqCst); 18062e46139SGou Ngai } 181bacd691cSlogin 182bacd691cSlogin pub fn do_softirq(&self) { 183*0d6cf65aSLoGin if self.cpu_running_count().get().load(Ordering::SeqCst) >= Self::MAX_RUNNING_PER_CPU { 184*0d6cf65aSLoGin // 当前CPU的软中断嵌套层数已经达到最大值,不再执行 185*0d6cf65aSLoGin return; 186*0d6cf65aSLoGin } 187*0d6cf65aSLoGin // 创建一个RunningCountGuard,当退出作用域时,会自动将cpu_running_count减1 188*0d6cf65aSLoGin let _count_guard = RunningCountGuard::new(self.cpu_running_count()); 189*0d6cf65aSLoGin 190bacd691cSlogin // TODO pcb的flags未修改 191bacd691cSlogin let end = clock() + 500 * 2; 192bacd691cSlogin let cpu_id = smp_get_processor_id(); 193bacd691cSlogin let mut max_restart = MAX_SOFTIRQ_RESTART; 194bacd691cSlogin loop { 195bacd691cSlogin compiler_fence(Ordering::SeqCst); 196bacd691cSlogin let pending = cpu_pending(cpu_id as usize).bits; 197bacd691cSlogin cpu_pending(cpu_id as usize).bits = 0; 198bacd691cSlogin compiler_fence(Ordering::SeqCst); 199bacd691cSlogin 20046e234aeSLoGin unsafe { CurrentIrqArch::interrupt_enable() }; 201bacd691cSlogin if pending != 0 { 202bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 203bacd691cSlogin if pending & (1 << i) == 0 { 20462e46139SGou Ngai continue; 20562e46139SGou Ngai } 206bacd691cSlogin 207*0d6cf65aSLoGin let table_guard = self.table.read_irqsave(); 208bacd691cSlogin let softirq_func = table_guard[i as usize].clone(); 209bacd691cSlogin drop(table_guard); 210bacd691cSlogin if softirq_func.is_none() { 211bacd691cSlogin continue; 212bacd691cSlogin } 213bacd691cSlogin 2141496ba7bSLoGin let prev_count: usize = ProcessManager::current_pcb().preempt_count(); 215bacd691cSlogin 216bacd691cSlogin softirq_func.as_ref().unwrap().run(); 2171496ba7bSLoGin if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) { 218bacd691cSlogin kdebug!( 219bacd691cSlogin "entered softirq {:?} with preempt_count {:?},exited with {:?}", 220bacd691cSlogin i, 221bacd691cSlogin prev_count, 2221496ba7bSLoGin ProcessManager::current_pcb().preempt_count() 223bacd691cSlogin ); 2241496ba7bSLoGin unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) }; 225bacd691cSlogin } 226bacd691cSlogin } 227bacd691cSlogin } 22846e234aeSLoGin unsafe { CurrentIrqArch::interrupt_disable() }; 229bacd691cSlogin max_restart -= 1; 230bacd691cSlogin compiler_fence(Ordering::SeqCst); 231bacd691cSlogin if cpu_pending(cpu_id as usize).is_empty() { 232bacd691cSlogin compiler_fence(Ordering::SeqCst); 233bacd691cSlogin if clock() < end && max_restart > 0 { 234bacd691cSlogin continue; 235bacd691cSlogin } else { 236bacd691cSlogin break; 237bacd691cSlogin } 238bacd691cSlogin } else { 239bacd691cSlogin // TODO:当有softirqd时 唤醒它 24062e46139SGou Ngai break; 24162e46139SGou Ngai } 24262e46139SGou Ngai } 24362e46139SGou Ngai } 24462e46139SGou Ngai 245bacd691cSlogin pub fn raise_softirq(&self, softirq_num: SoftirqNumber) { 2469550910aSChiichen let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 247bacd691cSlogin let processor_id = smp_get_processor_id() as usize; 248bacd691cSlogin 249bacd691cSlogin cpu_pending(processor_id).insert(VecStatus::from(softirq_num)); 250bacd691cSlogin 251bacd691cSlogin compiler_fence(Ordering::SeqCst); 252bacd691cSlogin 2539550910aSChiichen drop(guard); 254bacd691cSlogin // kdebug!("raise_softirq exited"); 25562e46139SGou Ngai } 2568fd71f27Shoumkh pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) { 257bacd691cSlogin compiler_fence(Ordering::SeqCst); 258bacd691cSlogin cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num)); 259bacd691cSlogin compiler_fence(Ordering::SeqCst); 26062e46139SGou Ngai } 26162e46139SGou Ngai } 262bacd691cSlogin 263*0d6cf65aSLoGin /// 当前CPU的软中断嵌套层数的计数器守卫 264*0d6cf65aSLoGin /// 265*0d6cf65aSLoGin /// 当进入作用域时,会自动将cpu_running_count加1, 266*0d6cf65aSLoGin /// 当退出作用域时,会自动将cpu_running_count减1 267*0d6cf65aSLoGin struct RunningCountGuard<'a> { 268*0d6cf65aSLoGin cpu_running_count: &'a PerCpuVar<AtomicI16>, 269*0d6cf65aSLoGin } 270*0d6cf65aSLoGin 271*0d6cf65aSLoGin impl<'a> RunningCountGuard<'a> { 272*0d6cf65aSLoGin fn new(cpu_running_count: &'a PerCpuVar<AtomicI16>) -> RunningCountGuard { 273*0d6cf65aSLoGin cpu_running_count.get().fetch_add(1, Ordering::SeqCst); 274*0d6cf65aSLoGin return RunningCountGuard { cpu_running_count }; 275*0d6cf65aSLoGin } 276*0d6cf65aSLoGin } 277*0d6cf65aSLoGin 278*0d6cf65aSLoGin impl<'a> Drop for RunningCountGuard<'a> { 279*0d6cf65aSLoGin fn drop(&mut self) { 280*0d6cf65aSLoGin self.cpu_running_count.get().fetch_sub(1, Ordering::SeqCst); 281*0d6cf65aSLoGin } 282*0d6cf65aSLoGin } 283*0d6cf65aSLoGin 284bacd691cSlogin // ======= 以下为给C提供的接口 ======= 285bacd691cSlogin #[no_mangle] 286bacd691cSlogin pub extern "C" fn rs_raise_softirq(softirq_num: u32) { 287bacd691cSlogin softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64)); 28862e46139SGou Ngai } 289bacd691cSlogin 290bacd691cSlogin #[no_mangle] 291bacd691cSlogin pub extern "C" fn rs_unregister_softirq(softirq_num: u32) { 292bacd691cSlogin softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64)); 29362e46139SGou Ngai } 294bacd691cSlogin 295bacd691cSlogin #[no_mangle] 296bacd691cSlogin pub extern "C" fn rs_do_softirq() { 297bacd691cSlogin softirq_vectors().do_softirq(); 298bacd691cSlogin } 299bacd691cSlogin 300bacd691cSlogin #[no_mangle] 301bacd691cSlogin pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) { 3028fd71f27Shoumkh unsafe { 303bacd691cSlogin softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64)); 30462e46139SGou Ngai } 3058fd71f27Shoumkh } 306