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
}
}

View File

@ -3,26 +3,33 @@ use system_error::SystemError;
use crate::{
arch::{driver::sbi::SbiDriver, mm::init::mm_early_init},
driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
driver::{
firmware::efi::init::efi_init, irqchip::riscv_intc::riscv_intc_init,
open_firmware::fdt::open_firmware_fdt_driver,
},
init::{boot_params, init::start_kernel},
kdebug, kinfo,
mm::{memblock::mem_block_manager, PhysAddr, VirtAddr},
print, println,
smp::cpu::ProcessorId,
};
use super::driver::sbi::console_putstr;
use super::{cpu::init_local_context, driver::sbi::console_putstr};
#[derive(Debug)]
pub struct ArchBootParams {
/// 启动时的fdt物理地址
pub fdt_paddr: PhysAddr,
pub fdt_vaddr: Option<VirtAddr>,
pub boot_hartid: ProcessorId,
}
impl ArchBootParams {
pub const DEFAULT: Self = ArchBootParams {
fdt_paddr: PhysAddr::new(0),
fdt_vaddr: None,
boot_hartid: ProcessorId::new(0),
};
pub fn arch_fdt(&self) -> VirtAddr {
@ -34,7 +41,7 @@ impl ArchBootParams {
}
}
static mut BOOT_HARTID: usize = 0;
static mut BOOT_HARTID: u32 = 0;
static mut BOOT_FDT_PADDR: PhysAddr = PhysAddr::new(0);
#[no_mangle]
@ -42,7 +49,7 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
let fdt_paddr = PhysAddr::new(fdt_paddr);
unsafe {
BOOT_HARTID = hartid;
BOOT_HARTID = hartid as u32;
BOOT_FDT_PADDR = fdt_paddr;
}
@ -79,9 +86,14 @@ unsafe fn parse_dtb() {
#[inline(never)]
pub fn early_setup_arch() -> Result<(), SystemError> {
SbiDriver::early_init();
let hartid: usize = unsafe { BOOT_HARTID };
let hartid = unsafe { BOOT_HARTID };
let fdt_paddr = unsafe { BOOT_FDT_PADDR };
boot_params().write().arch.fdt_paddr = fdt_paddr;
let mut arch_boot_params_guard = boot_params().write();
arch_boot_params_guard.arch.fdt_paddr = fdt_paddr;
arch_boot_params_guard.arch.boot_hartid = ProcessorId::new(hartid);
drop(arch_boot_params_guard);
kinfo!(
"DragonOS kernel is running on hart {}, fdt address:{:?}",
@ -109,7 +121,7 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
#[inline(never)]
pub fn setup_arch() -> Result<(), SystemError> {
// todo
init_local_context();
return Ok(());
}

View File

@ -1,6 +1,9 @@
use system_error::SystemError;
use crate::exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber};
use crate::{
driver::irqchip::riscv_intc::riscv_intc_init,
exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
};
pub mod ipi;
@ -8,7 +11,9 @@ pub struct RiscV64InterruptArch;
impl InterruptArch for RiscV64InterruptArch {
unsafe fn arch_irq_init() -> Result<(), SystemError> {
todo!("RiscV64InterruptArch::arch_irq_init")
riscv_intc_init()?;
Ok(())
}
unsafe fn interrupt_enable() {
riscv::interrupt::enable();

View File

@ -1,6 +1,6 @@
use x86::cpuid::{cpuid, CpuIdResult};
use crate::smp::cpu::ProcessorId;
use crate::smp::cpu::{ProcessorId, SmpCpuManager};
/// 获取当前cpu的apic id
#[inline]
@ -16,3 +16,7 @@ pub unsafe fn cpu_reset() -> ! {
unsafe { x86::io::outb(0x64, 0xfe) };
loop {}
}
impl SmpCpuManager {
pub fn arch_init(_boot_cpu: ProcessorId) {}
}