mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 02:46:47 +00:00
初始化riscv-sbi-timer (#716)
This commit is contained in:
parent
3959e94df3
commit
f049d1af01
@ -5,7 +5,10 @@ use core::hint::spin_loop;
|
|||||||
|
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{arch::syscall::syscall_handler, kdebug, kerror};
|
use crate::{
|
||||||
|
arch::syscall::syscall_handler, driver::irqchip::riscv_intc::riscv_intc_irq,
|
||||||
|
exception::HardwareIrqNumber, kdebug, kerror,
|
||||||
|
};
|
||||||
|
|
||||||
use super::TrapFrame;
|
use super::TrapFrame;
|
||||||
|
|
||||||
@ -40,11 +43,8 @@ unsafe extern "C" fn riscv64_do_irq(trap_frame: &mut TrapFrame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 处理中断
|
/// 处理中断
|
||||||
fn riscv64_do_interrupt(_trap_frame: &mut TrapFrame) {
|
fn riscv64_do_interrupt(trap_frame: &mut TrapFrame) {
|
||||||
kdebug!("todo: riscv64_do_irq: interrupt");
|
riscv_intc_irq(trap_frame);
|
||||||
loop {
|
|
||||||
spin_loop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 处理异常
|
/// 处理异常
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use core::hint::spin_loop;
|
use core::hint::spin_loop;
|
||||||
|
|
||||||
use crate::{arch::CurrentIrqArch, exception::InterruptArch, kBUG, process::ProcessManager};
|
use crate::{
|
||||||
|
arch::CurrentIrqArch, exception::InterruptArch, kBUG, kdebug, process::ProcessManager,
|
||||||
|
};
|
||||||
|
|
||||||
impl ProcessManager {
|
impl ProcessManager {
|
||||||
/// 每个核的idle进程
|
/// 每个核的idle进程
|
||||||
@ -14,6 +16,8 @@ impl ProcessManager {
|
|||||||
kBUG!("Idle process should not be scheduled with IRQs disabled.");
|
kBUG!("Idle process should not be scheduled with IRQs disabled.");
|
||||||
spin_loop();
|
spin_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kdebug!("idle loop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ use crate::{
|
|||||||
CurrentIrqArch,
|
CurrentIrqArch,
|
||||||
},
|
},
|
||||||
exception::InterruptArch,
|
exception::InterruptArch,
|
||||||
kerror,
|
kdebug, kerror,
|
||||||
libs::spinlock::SpinLockGuard,
|
libs::spinlock::SpinLockGuard,
|
||||||
mm::VirtAddr,
|
mm::VirtAddr,
|
||||||
process::{
|
process::{
|
||||||
@ -127,14 +127,22 @@ impl ProcessManager {
|
|||||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
|
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
|
||||||
pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
|
pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
|
||||||
assert!(!CurrentIrqArch::is_irq_enabled());
|
assert!(!CurrentIrqArch::is_irq_enabled());
|
||||||
|
kdebug!(
|
||||||
|
"riscv switch process: prev: {:?}, next: {:?}",
|
||||||
|
prev.pid(),
|
||||||
|
next.pid()
|
||||||
|
);
|
||||||
Self::switch_process_fpu(&prev, &next);
|
Self::switch_process_fpu(&prev, &next);
|
||||||
|
kdebug!("riscv switch process: after switch_process_fpu");
|
||||||
Self::switch_local_context(&prev, &next);
|
Self::switch_local_context(&prev, &next);
|
||||||
|
kdebug!("riscv switch process: after switch_local_context");
|
||||||
|
|
||||||
// 切换地址空间
|
// 切换地址空间
|
||||||
let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone();
|
let next_addr_space = next.basic().user_vm().as_ref().unwrap().clone();
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
next_addr_space.read().user_mapper.utable.make_current();
|
next_addr_space.read().user_mapper.utable.make_current();
|
||||||
|
kdebug!("riscv switch process: after switch addr space");
|
||||||
drop(next_addr_space);
|
drop(next_addr_space);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
@ -147,7 +155,7 @@ impl ProcessManager {
|
|||||||
ProcessManager::current_pcb().preempt_enable();
|
ProcessManager::current_pcb().preempt_enable();
|
||||||
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
|
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
|
||||||
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
|
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
|
||||||
// kdebug!("switch tss ok");
|
kdebug!("riscv switch process: before to inner");
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
// 正式切换上下文
|
// 正式切换上下文
|
||||||
switch_to_inner(prev_arch, next_arch);
|
switch_to_inner(prev_arch, next_arch);
|
||||||
@ -244,7 +252,14 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI
|
|||||||
|
|
||||||
/// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误)
|
/// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误)
|
||||||
unsafe extern "C" fn before_switch_finish_hook() {
|
unsafe extern "C" fn before_switch_finish_hook() {
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
kdebug!(
|
||||||
|
"before_switch_finish_hook, pid: {:?}, name: {:?}",
|
||||||
|
pcb.pid(),
|
||||||
|
pcb.basic().name()
|
||||||
|
);
|
||||||
switch_finish_hook();
|
switch_finish_hook();
|
||||||
|
kdebug!("after switch_finish_hook");
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessControlBlock {
|
impl ProcessControlBlock {
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
use crate::sched::SchedArch;
|
use crate::{
|
||||||
|
driver::clocksource::timer_riscv::riscv_sbi_timer_init_local, exception::InterruptArch,
|
||||||
|
sched::SchedArch,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::CurrentIrqArch;
|
||||||
|
|
||||||
/// 发起调度
|
/// 发起调度
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -10,14 +15,13 @@ pub struct RiscV64SchedArch;
|
|||||||
|
|
||||||
impl SchedArch for RiscV64SchedArch {
|
impl SchedArch for RiscV64SchedArch {
|
||||||
fn enable_sched_local() {
|
fn enable_sched_local() {
|
||||||
todo!()
|
riscv_sbi_timer_init_local();
|
||||||
|
unsafe { CurrentIrqArch::interrupt_enable() };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable_sched_local() {
|
fn disable_sched_local() {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initial_setup_sched_local() {
|
fn initial_setup_sched_local() {}
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -64,3 +64,7 @@ impl TimeArch for RiscV64TimeArch {
|
|||||||
cycles * 1000000000 / unsafe { TIME_FREQ }
|
cycles * 1000000000 / unsafe { TIME_FREQ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn riscv_time_base_freq() -> usize {
|
||||||
|
unsafe { TIME_FREQ }
|
||||||
|
}
|
||||||
|
2
kernel/src/driver/clocksource/mod.rs
Normal file
2
kernel/src/driver/clocksource/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
pub mod timer_riscv;
|
131
kernel/src/driver/clocksource/timer_riscv.rs
Normal file
131
kernel/src/driver/clocksource/timer_riscv.rs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
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::TimeArch,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct RiscVSbiTimer;
|
||||||
|
|
||||||
|
static SBI_TIMER_INIT_BMP: SpinLock<StaticBitmap<{ PerCpu::MAX_CPU_NUM as usize }>> =
|
||||||
|
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() };
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
// todo: 将来正式实现时,需要除以HZ
|
||||||
|
let new = riscv_time_base_freq();
|
||||||
|
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<Arc<dyn IrqHandlerData>>,
|
||||||
|
) -> Result<IrqReturn, SystemError> {
|
||||||
|
// empty (只是为了让编译通过,不会被调用到。真正的处理函数在 RiscvSbiTimerIrqFlowHandler 中)
|
||||||
|
Ok(IrqReturn::NotHandled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RiscvSbiTimerIrqFlowHandler;
|
||||||
|
|
||||||
|
impl IrqFlowHandler for RiscvSbiTimerIrqFlowHandler {
|
||||||
|
fn handle(&self, _irq_desc: &Arc<IrqDesc>, trap_frame: &mut TrapFrame) {
|
||||||
|
RiscVSbiTimer::handle_irq(trap_frame).unwrap();
|
||||||
|
fence(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,19 @@
|
|||||||
use alloc::{string::ToString, sync::Arc};
|
use alloc::{string::ToString, sync::Arc};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::exception::{
|
use crate::{
|
||||||
handle::PerCpuDevIdIrqHandler,
|
arch::interrupt::TrapFrame,
|
||||||
irqchip::{IrqChip, IrqChipFlags},
|
driver::clocksource::timer_riscv::{riscv_sbi_timer_irq_desc_init, RiscVSbiTimer},
|
||||||
irqdata::IrqData,
|
exception::{
|
||||||
irqdesc::irq_desc_manager,
|
handle::PerCpuDevIdIrqHandler,
|
||||||
irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
|
irqchip::{IrqChip, IrqChipFlags},
|
||||||
HardwareIrqNumber, IrqNumber,
|
irqdata::IrqData,
|
||||||
|
irqdesc::{irq_desc_manager, GenericIrqHandler},
|
||||||
|
irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
|
||||||
|
HardwareIrqNumber, IrqNumber,
|
||||||
|
},
|
||||||
|
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||||
|
sched::{SchedMode, __schedule},
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut RISCV_INTC_DOMAIN: Option<Arc<IrqDomain>> = None;
|
static mut RISCV_INTC_DOMAIN: Option<Arc<IrqDomain>> = None;
|
||||||
@ -24,7 +30,9 @@ fn riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RiscvIntcChip;
|
struct RiscvIntcChip {
|
||||||
|
inner: SpinLock<InnerIrqChip>,
|
||||||
|
}
|
||||||
|
|
||||||
impl IrqChip for RiscvIntcChip {
|
impl IrqChip for RiscvIntcChip {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
@ -43,9 +51,7 @@ impl IrqChip for RiscvIntcChip {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn irq_ack(&self, irq: &Arc<IrqData>) {
|
fn irq_ack(&self, _irq: &Arc<IrqData>) {}
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_mask_ack(&self) -> bool {
|
fn can_mask_ack(&self) -> bool {
|
||||||
false
|
false
|
||||||
@ -75,10 +81,28 @@ impl IrqChip for RiscvIntcChip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> IrqChipFlags {
|
fn flags(&self) -> IrqChipFlags {
|
||||||
todo!()
|
self.inner().flags
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RiscvIntcChip {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: SpinLock::new(InnerIrqChip {
|
||||||
|
flags: IrqChipFlags::empty(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn inner(&self) -> SpinLockGuard<InnerIrqChip> {
|
||||||
|
self.inner.lock_irqsave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct InnerIrqChip {
|
||||||
|
flags: IrqChipFlags,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct RiscvIntcDomainOps;
|
struct RiscvIntcDomainOps;
|
||||||
|
|
||||||
@ -104,14 +128,14 @@ impl IrqDomainOps for RiscvIntcDomainOps {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber) {
|
fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) {
|
||||||
todo!("riscv_intc_domain_ops::unmap");
|
todo!("riscv_intc_domain_ops::unmap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
|
pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
|
||||||
let intc_chip = Arc::new(RiscvIntcChip);
|
let intc_chip = Arc::new(RiscvIntcChip::new());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
RISCV_INTC_CHIP = Some(intc_chip);
|
RISCV_INTC_CHIP = Some(intc_chip);
|
||||||
@ -130,5 +154,18 @@ pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
|
|||||||
RISCV_INTC_DOMAIN = Some(intc_domain);
|
RISCV_INTC_DOMAIN = Some(intc_domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
riscv_sbi_timer_irq_desc_init();
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23
|
||||||
|
pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
|
||||||
|
let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32);
|
||||||
|
kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
|
||||||
|
GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame)
|
||||||
|
.ok();
|
||||||
|
if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
|
||||||
|
__schedule(SchedMode::SM_PREEMPT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
pub mod acpi;
|
pub mod acpi;
|
||||||
pub mod base;
|
pub mod base;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
|
pub mod clocksource;
|
||||||
pub mod disk;
|
pub mod disk;
|
||||||
pub mod firmware;
|
pub mod firmware;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
@ -11,6 +11,7 @@ use crate::libs::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
irqchip::{IrqChip, IrqChipData},
|
irqchip::{IrqChip, IrqChipData},
|
||||||
|
irqdesc::IrqDesc,
|
||||||
irqdomain::IrqDomain,
|
irqdomain::IrqDomain,
|
||||||
msi::MsiDesc,
|
msi::MsiDesc,
|
||||||
HardwareIrqNumber, IrqNumber,
|
HardwareIrqNumber, IrqNumber,
|
||||||
@ -43,7 +44,7 @@ impl IrqData {
|
|||||||
inner: SpinLock::new(InnerIrqData {
|
inner: SpinLock::new(InnerIrqData {
|
||||||
hwirq,
|
hwirq,
|
||||||
common_data,
|
common_data,
|
||||||
|
desc: Weak::new(),
|
||||||
domain: None,
|
domain: None,
|
||||||
parent_data: None,
|
parent_data: None,
|
||||||
}),
|
}),
|
||||||
@ -71,6 +72,18 @@ impl IrqData {
|
|||||||
self.irq
|
self.irq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn irq_desc(&self) -> Option<Arc<IrqDesc>> {
|
||||||
|
self.inner.lock_irqsave().desc.upgrade()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_irq_desc(&self, desc: Weak<IrqDesc>) {
|
||||||
|
self.inner.lock_irqsave().desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_irq_desc(&self) {
|
||||||
|
self.inner.lock_irqsave().desc = Weak::new();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hardware_irq(&self) -> HardwareIrqNumber {
|
pub fn hardware_irq(&self) -> HardwareIrqNumber {
|
||||||
self.inner.lock_irqsave().hwirq
|
self.inner.lock_irqsave().hwirq
|
||||||
}
|
}
|
||||||
@ -133,6 +146,8 @@ pub struct InnerIrqData {
|
|||||||
/// 涉及的所有irqchip之间共享的数据
|
/// 涉及的所有irqchip之间共享的数据
|
||||||
common_data: Arc<IrqCommonData>,
|
common_data: Arc<IrqCommonData>,
|
||||||
|
|
||||||
|
desc: Weak<IrqDesc>,
|
||||||
|
|
||||||
/// 中断域
|
/// 中断域
|
||||||
domain: Option<Arc<IrqDomain>>,
|
domain: Option<Arc<IrqDomain>>,
|
||||||
/// 中断的父中断(如果具有中断域继承的话)
|
/// 中断的父中断(如果具有中断域继承的话)
|
||||||
@ -409,6 +424,7 @@ impl IrqLineStatus {
|
|||||||
///
|
///
|
||||||
/// - 如果不是电平触发类型,则返回None
|
/// - 如果不是电平触发类型,则返回None
|
||||||
/// - 如果是电平触发类型,则返回Some(bool),当为true时表示高电平触发
|
/// - 如果是电平触发类型,则返回Some(bool),当为true时表示高电平触发
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn is_level_high(&self) -> Option<bool> {
|
pub fn is_level_high(&self) -> Option<bool> {
|
||||||
if !self.is_level_type() {
|
if !self.is_level_type() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -37,6 +37,7 @@ use super::{
|
|||||||
handle::bad_irq_handler,
|
handle::bad_irq_handler,
|
||||||
irqchip::IrqChip,
|
irqchip::IrqChip,
|
||||||
irqdata::{IrqCommonData, IrqData, IrqHandlerData, IrqLineStatus, IrqStatus},
|
irqdata::{IrqCommonData, IrqData, IrqHandlerData, IrqLineStatus, IrqStatus},
|
||||||
|
irqdomain::{irq_domain_manager, IrqDomain},
|
||||||
sysfs::{irq_sysfs_del, IrqKObjType},
|
sysfs::{irq_sysfs_del, IrqKObjType},
|
||||||
HardwareIrqNumber, InterruptArch, IrqNumber,
|
HardwareIrqNumber, InterruptArch, IrqNumber,
|
||||||
};
|
};
|
||||||
@ -119,11 +120,12 @@ impl IrqDesc {
|
|||||||
kobj_state: LockedKObjectState::new(Some(KObjectState::INITIALIZED)),
|
kobj_state: LockedKObjectState::new(Some(KObjectState::INITIALIZED)),
|
||||||
threads_active: AtomicI64::new(0),
|
threads_active: AtomicI64::new(0),
|
||||||
};
|
};
|
||||||
|
let irq_desc = Arc::new(irq_desc);
|
||||||
|
irq_desc.irq_data().set_irq_desc(Arc::downgrade(&irq_desc));
|
||||||
irq_desc.set_handler(bad_irq_handler());
|
irq_desc.set_handler(bad_irq_handler());
|
||||||
irq_desc.inner().irq_data.irqd_set(irqd_flags);
|
irq_desc.inner().irq_data.irqd_set(irqd_flags);
|
||||||
|
|
||||||
return Arc::new(irq_desc);
|
return irq_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 返回当前活跃的中断线程数量
|
/// 返回当前活跃的中断线程数量
|
||||||
@ -988,3 +990,35 @@ impl IrqDescManager {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GenericIrqHandler;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl GenericIrqHandler {
|
||||||
|
/// `handle_domain_irq` - 调用属于某个中断域的硬件中断的处理程序
|
||||||
|
///
|
||||||
|
/// # 参数
|
||||||
|
///
|
||||||
|
/// * `domain`: 执行查找的域
|
||||||
|
/// * `hwirq`: 要转换为逻辑中断的硬件中断号
|
||||||
|
///
|
||||||
|
/// # 返回
|
||||||
|
///
|
||||||
|
/// 成功时返回 `Ok(())`,如果转换失败则返回 `Err(SystemError)`
|
||||||
|
///
|
||||||
|
/// 此函数必须在初始化了中断寄存器的中断上下文中调用
|
||||||
|
///
|
||||||
|
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/irq/irqdesc.c?fi=generic_handle_domain_irq#726
|
||||||
|
pub fn handle_domain_irq(
|
||||||
|
domain: Arc<IrqDomain>,
|
||||||
|
hwirq: HardwareIrqNumber,
|
||||||
|
trap_frame: &mut TrapFrame,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
let (irq_desc, _) =
|
||||||
|
irq_domain_manager().resolve_irq_mapping(Some(domain.clone()), hwirq)?;
|
||||||
|
|
||||||
|
irq_desc.handler().unwrap().handle(&irq_desc, trap_frame);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,14 +11,17 @@ use system_error::SystemError;
|
|||||||
use crate::{
|
use crate::{
|
||||||
driver::{base::device::Device, open_firmware::device_node::DeviceNode},
|
driver::{base::device::Device, open_firmware::device_node::DeviceNode},
|
||||||
exception::{irqdata::IrqLineStatus, irqdesc::irq_desc_manager, manage::irq_manager},
|
exception::{irqdata::IrqLineStatus, irqdesc::irq_desc_manager, manage::irq_manager},
|
||||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
libs::{
|
||||||
|
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
|
spinlock::SpinLock,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
dummychip::no_irq_chip,
|
dummychip::no_irq_chip,
|
||||||
irqchip::{IrqChip, IrqChipData, IrqChipGeneric, IrqGcFlags},
|
irqchip::{IrqChip, IrqChipData, IrqChipGeneric, IrqGcFlags},
|
||||||
irqdata::{IrqData, IrqHandlerData},
|
irqdata::{IrqData, IrqHandlerData},
|
||||||
irqdesc::IrqFlowHandler,
|
irqdesc::{IrqDesc, IrqFlowHandler},
|
||||||
HardwareIrqNumber, IrqNumber,
|
HardwareIrqNumber, IrqNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -389,6 +392,48 @@ impl IrqDomainManager {
|
|||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `resolve_irq_mapping` - 从硬件中断号找到中断号。
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `domain`: 拥有此硬件中断的域
|
||||||
|
/// - `hwirq`: 该域空间中的硬件中断号
|
||||||
|
/// - `irq`: 如果需要,可选的指针以返回Linux中断
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// 返回一个元组,包含中断描述符和中断号
|
||||||
|
pub fn resolve_irq_mapping(
|
||||||
|
&self,
|
||||||
|
mut domain: Option<Arc<IrqDomain>>,
|
||||||
|
hwirq: HardwareIrqNumber,
|
||||||
|
) -> Result<(Arc<IrqDesc>, IrqNumber), SystemError> {
|
||||||
|
if domain.is_none() {
|
||||||
|
domain = Some(self.default_domain().ok_or(SystemError::EINVAL)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
let domain = domain.unwrap();
|
||||||
|
|
||||||
|
if domain.no_map() {
|
||||||
|
if hwirq < domain.revmap_read_irqsave().hwirq_max {
|
||||||
|
let irq_desc = irq_desc_manager()
|
||||||
|
.lookup(IrqNumber::new(hwirq.data()))
|
||||||
|
.ok_or(SystemError::EINVAL)?;
|
||||||
|
if irq_desc.irq_data().hardware_irq() == hwirq {
|
||||||
|
let irq = irq_desc.irq_data().irq();
|
||||||
|
return Ok((irq_desc, irq));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
let revmap = domain.revmap_read_irqsave();
|
||||||
|
let irq_data = revmap.lookup(hwirq).ok_or(SystemError::EINVAL)?;
|
||||||
|
let irq_desc = irq_data.irq_desc().unwrap();
|
||||||
|
return Ok((irq_desc, irq_data.irq()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InnerIrqDomainManager {
|
struct InnerIrqDomainManager {
|
||||||
@ -480,9 +525,19 @@ impl IrqDomain {
|
|||||||
.contains(IrqDomainFlags::NO_MAP)
|
.contains(IrqDomainFlags::NO_MAP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn revmap_read_irqsave(&self) -> RwLockReadGuard<IrqDomainRevMap> {
|
||||||
|
self.revmap.read_irqsave()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn revmap_write_irqsave(&self) -> RwLockWriteGuard<IrqDomainRevMap> {
|
||||||
|
self.revmap.write_irqsave()
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) {
|
fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) {
|
||||||
self.revmap.write_irqsave().hwirq_max = hwirq_max;
|
self.revmap_write_irqsave().hwirq_max = hwirq_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> Option<String> {
|
pub fn name(&self) -> Option<String> {
|
||||||
@ -498,7 +553,7 @@ impl IrqDomain {
|
|||||||
|
|
||||||
/// The number of mapped interrupts
|
/// The number of mapped interrupts
|
||||||
pub fn map_count(&self) -> u32 {
|
pub fn map_count(&self) -> u32 {
|
||||||
self.revmap.read().map.len() as u32
|
self.revmap_read_irqsave().map.len() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn host_data(&self) -> Option<Arc<dyn IrqChipData>> {
|
pub fn host_data(&self) -> Option<Arc<dyn IrqChipData>> {
|
||||||
|
@ -911,12 +911,8 @@ pub fn __schedule(sched_mod: SchedMode) {
|
|||||||
|
|
||||||
// CurrentApic.send_eoi();
|
// CurrentApic.send_eoi();
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
unsafe {
|
unsafe { ProcessManager::switch_process(prev, next) };
|
||||||
ProcessManager::switch_process(prev, next)
|
|
||||||
};
|
|
||||||
#[cfg(target_arch = "riscv64")]
|
|
||||||
todo!()
|
|
||||||
} else {
|
} else {
|
||||||
kwarn!(
|
kwarn!(
|
||||||
"!!!switch_process {} {:?} to self ",
|
"!!!switch_process {} {:?} to self ",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user