use core::sync::atomic::{fence, Ordering}; use alloc::{string::ToString, sync::Arc}; use bitmap::{traits::BitMapOps, StaticBitmap}; use system_error::SystemError; use crate::{ arch::{interrupt::TrapFrame, time::riscv_time_base_freq, CurrentIrqArch, CurrentTimeArch}, driver::base::device::DeviceId, exception::{ irqdata::{IrqHandlerData, IrqLineStatus}, irqdesc::{ irq_desc_manager, IrqDesc, IrqFlowHandler, IrqHandleFlags, IrqHandler, IrqReturn, }, manage::irq_manager, InterruptArch, IrqNumber, }, libs::spinlock::SpinLock, mm::percpu::PerCpu, process::ProcessManager, smp::core::smp_get_processor_id, time::{clocksource::HZ, TimeArch}, }; pub struct RiscVSbiTimer; static SBI_TIMER_INIT_BMP: SpinLock> = SpinLock::new(StaticBitmap::new()); static mut INTERVAL_CNT: usize = 0; impl RiscVSbiTimer { pub const TIMER_IRQ: IrqNumber = IrqNumber::from(5); fn handle_irq(trap_frame: &mut TrapFrame) -> Result<(), SystemError> { // 更新下一次中断时间 // kdebug!( // "riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}", // smp_get_processor_id().data(), // CurrentTimeArch::get_cycles() as u64 // ); sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64); ProcessManager::update_process_times(trap_frame.is_from_user()); Ok(()) } fn enable() { unsafe { riscv::register::sie::set_stimer() }; } #[allow(dead_code)] fn disable() { unsafe { riscv::register::sie::clear_stimer() }; } } /// riscv 初始化本地调度时钟源 #[inline(never)] pub fn riscv_sbi_timer_init_local() { assert_eq!(CurrentIrqArch::is_irq_enabled(), false); if unsafe { INTERVAL_CNT } == 0 { let new = riscv_time_base_freq() / HZ as usize; if new == 0 { panic!("riscv_sbi_timer_init: failed to get timebase-frequency"); } unsafe { INTERVAL_CNT = new; } } let mut guard = SBI_TIMER_INIT_BMP.lock(); // 如果已经初始化过了,直接返回。或者cpu id不存在 if guard .get(smp_get_processor_id().data() as usize) .unwrap_or(true) { return; } irq_manager() .request_irq( RiscVSbiTimer::TIMER_IRQ, "riscv_clocksource".to_string(), &RiscvSbiTimerHandler, IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_PERCPU, Some(DeviceId::new(Some("riscv sbi timer"), None).unwrap()), ) .expect("Apic timer init failed"); // 设置第一次中断 sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64); RiscVSbiTimer::enable(); guard .set(smp_get_processor_id().data() as usize, true) .unwrap(); } #[inline(never)] pub fn riscv_sbi_timer_irq_desc_init() { let desc = irq_desc_manager().lookup(RiscVSbiTimer::TIMER_IRQ).unwrap(); desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); desc.set_handler(&RiscvSbiTimerIrqFlowHandler); } #[derive(Debug)] struct RiscvSbiTimerHandler; impl IrqHandler for RiscvSbiTimerHandler { fn handle( &self, _irq: IrqNumber, _static_data: Option<&dyn IrqHandlerData>, _dynamic_data: Option>, ) -> Result { // empty (只是为了让编译通过,不会被调用到。真正的处理函数在 RiscvSbiTimerIrqFlowHandler 中) Ok(IrqReturn::NotHandled) } } #[derive(Debug)] struct RiscvSbiTimerIrqFlowHandler; impl IrqFlowHandler for RiscvSbiTimerIrqFlowHandler { fn handle(&self, _irq_desc: &Arc, trap_frame: &mut TrapFrame) { RiscVSbiTimer::handle_irq(trap_frame).unwrap(); fence(Ordering::SeqCst) } }