riscv: 初始化irq (#560)

完成riscv的irqchip初始化的代码。

这是该功能的第一个PR。由于还需要实现timer驱动才能测试,因此该功能将会通过2~3个PR来完成。
This commit is contained in:
LoGin
2024-03-05 17:22:04 +08:00
committed by GitHub
parent bc6f0a967c
commit 338f690326
21 changed files with 995 additions and 67 deletions

View File

@ -1,9 +1,22 @@
use crate::smp::cpu::ProcessorId;
use alloc::vec::Vec;
use crate::{
init::boot_params,
kdebug,
mm::percpu::{PerCpu, PerCpuVar},
smp::cpu::{ProcessorId, SmpCpuManager},
};
/// 获取当前cpu的id
#[inline]
pub fn current_cpu_id() -> ProcessorId {
unimplemented!("RiscV64 current_cpu_id")
let ptr: *const LocalContext = riscv::register::sscratch::read() as *const LocalContext;
if core::intrinsics::unlikely(ptr.is_null()) {
return boot_params().read_irqsave().arch.boot_hartid;
}
unsafe { (*ptr).current_cpu() }
}
/// 重置cpu
@ -11,3 +24,64 @@ pub unsafe fn cpu_reset() -> ! {
sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason);
unimplemented!("RiscV64 reset failed, manual override expected ...")
}
static mut LOCAL_CONTEXT: Option<PerCpuVar<LocalContext>> = None;
#[inline(always)]
pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
unsafe { LOCAL_CONTEXT.as_ref().unwrap() }
}
/// Per cpu的上下文数据
///
/// 每个CPU的sscratch寄存器指向这个结构体
#[derive(Debug)]
pub(super) struct LocalContext {
/// 当前cpu的id
current_cpu: ProcessorId,
}
impl LocalContext {
fn new(cpu: ProcessorId) -> Self {
Self { current_cpu: cpu }
}
pub fn current_cpu(&self) -> ProcessorId {
self.current_cpu
}
pub fn set_current_cpu(&mut self, cpu: ProcessorId) {
self.current_cpu = cpu;
}
fn sync_to_cpu(&self) {
let ptr = self as *const Self as usize;
riscv::register::sscratch::write(ptr);
}
}
/// 初始化本地上下文
#[inline(never)]
pub(super) fn init_local_context() {
kdebug!("init_local_context");
let mut data = Vec::new();
for i in 0..PerCpu::MAX_CPU_NUM {
data.push(LocalContext::new(ProcessorId::new(i)));
}
let ctx = PerCpuVar::new(data).unwrap();
unsafe {
LOCAL_CONTEXT = Some(ctx);
}
let hartid = boot_params().read().arch.boot_hartid;
let ctx = unsafe { local_context().force_get(hartid) };
ctx.sync_to_cpu();
}
impl SmpCpuManager {
pub fn arch_init(boot_cpu: ProcessorId) {
// todo: 读取所有可用的CPU
}
}