From 5bc392f3880bb8adfe4badfebb6af9300d9636a0 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sun, 21 Oct 2018 21:35:28 +0800 Subject: [PATCH] Enable RV32 IPI. --- crate/bbl/src/sbi.rs | 16 ++++++------ kernel/Makefile | 8 ++++-- kernel/src/arch/riscv32/{smp.rs => cpu.rs} | 16 ++++++------ kernel/src/arch/riscv32/interrupt.rs | 8 ++++++ kernel/src/arch/riscv32/mod.rs | 29 +++++++++++----------- kernel/src/arch/x86_64/cpu.rs | 4 +-- 6 files changed, 46 insertions(+), 35 deletions(-) rename kernel/src/arch/riscv32/{smp.rs => cpu.rs} (70%) diff --git a/crate/bbl/src/sbi.rs b/crate/bbl/src/sbi.rs index b8782b7..3942fc2 100644 --- a/crate/bbl/src/sbi.rs +++ b/crate/bbl/src/sbi.rs @@ -36,20 +36,20 @@ pub fn clear_ipi() { sbi_call(SBI_CLEAR_IPI, 0, 0, 0); } -pub fn send_ipi(hart_mask: *const usize) { - sbi_call(SBI_SEND_IPI, hart_mask as usize, 0, 0); +pub fn send_ipi(hart_mask: usize) { + sbi_call(SBI_SEND_IPI, &hart_mask as *const _ as usize, 0, 0); } -pub fn remote_fence_i(hart_mask: *const usize) { - sbi_call(SBI_REMOTE_FENCE_I, hart_mask as usize, 0, 0); +pub fn remote_fence_i(hart_mask: usize) { + sbi_call(SBI_REMOTE_FENCE_I, &hart_mask as *const _ as usize, 0, 0); } -pub fn remote_sfence_vma(hart_mask: *const usize, _start: usize, _size: usize) { - sbi_call(SBI_REMOTE_SFENCE_VMA, hart_mask as usize, 0, 0); +pub fn remote_sfence_vma(hart_mask: usize, _start: usize, _size: usize) { + sbi_call(SBI_REMOTE_SFENCE_VMA, &hart_mask as *const _ as usize, 0, 0); } -pub fn remote_sfence_vma_asid(hart_mask: *const usize, _start: usize, _size: usize, _asid: usize) { - sbi_call(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask as usize, 0, 0); +pub fn remote_sfence_vma_asid(hart_mask: usize, _start: usize, _size: usize, _asid: usize) { + sbi_call(SBI_REMOTE_SFENCE_VMA_ASID, &hart_mask as *const _ as usize, 0, 0); } const SBI_SET_TIMER: usize = 0; diff --git a/kernel/Makefile b/kernel/Makefile index a32456b..0b49f67 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -33,12 +33,16 @@ ifeq ($(arch), x86_64) qemu_opts := \ -drive format=raw,file=$(bootimage) \ -drive format=raw,file=$(SFSIMG),media=disk,cache=writeback \ - -smp $(smp) \ + -smp cores=$(smp) \ -serial mon:stdio \ -device isa-debug-exit endif ifeq ($(arch), riscv32) -qemu_opts := -machine virt -kernel $(bin) -nographic -smp cpus=$(smp) +qemu_opts := \ + -machine virt \ + -kernel $(bin) \ + -nographic \ + -smp cores=$(smp) endif ifdef board diff --git a/kernel/src/arch/riscv32/smp.rs b/kernel/src/arch/riscv32/cpu.rs similarity index 70% rename from kernel/src/arch/riscv32/smp.rs rename to kernel/src/arch/riscv32/cpu.rs index aab6e4e..0b95107 100644 --- a/kernel/src/arch/riscv32/smp.rs +++ b/kernel/src/arch/riscv32/cpu.rs @@ -5,19 +5,19 @@ use memory::*; static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM]; pub unsafe fn set_cpu_id(cpu_id: usize) { - unsafe { - asm!("mv tp, $0" : : "r"(cpu_id)); - } + asm!("mv tp, $0" : : "r"(cpu_id)); } -pub unsafe fn get_cpu_id() -> usize { - let mut cpu_id = 0; - unsafe { - asm!("mv $0, tp" : : "r" (cpu_id)); - } +pub fn id() -> usize { + let cpu_id; + unsafe { asm!("mv $0, tp" : "=r"(cpu_id)); } cpu_id } +pub fn send_ipi(cpu_id: usize) { + super::bbl::sbi::send_ipi(1 << cpu_id); +} + pub unsafe fn has_started(cpu_id: usize) -> bool { read_volatile(&STARTED[cpu_id]) } diff --git a/kernel/src/arch/riscv32/interrupt.rs b/kernel/src/arch/riscv32/interrupt.rs index 58ed672..cee4bc1 100644 --- a/kernel/src/arch/riscv32/interrupt.rs +++ b/kernel/src/arch/riscv32/interrupt.rs @@ -14,6 +14,8 @@ pub fn init() { sscratch::write(0); // Set the exception vector address stvec::write(__alltraps as usize, stvec::TrapMode::Direct); + // Enable IPI + sie::set_ssoft(); } info!("interrupt: init end"); } @@ -42,6 +44,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { use super::riscv::register::scause::{Trap, Interrupt as I, Exception as E}; trace!("Interrupt: {:?}", tf.scause.cause()); match tf.scause.cause() { + Trap::Interrupt(I::SupervisorSoft) => ipi(), Trap::Interrupt(I::SupervisorTimer) => timer(), Trap::Exception(E::IllegalInstruction) => illegal_inst(tf), Trap::Exception(E::UserEnvCall) => syscall(tf), @@ -51,6 +54,11 @@ pub extern fn rust_trap(tf: &mut TrapFrame) { trace!("Interrupt end"); } +fn ipi() { + debug!("IPI"); + super::bbl::sbi::clear_ipi(); +} + fn timer() { ::trap::timer(); super::timer::set_next(); diff --git a/kernel/src/arch/riscv32/mod.rs b/kernel/src/arch/riscv32/mod.rs index aadbdaf..c6ccc1c 100644 --- a/kernel/src/arch/riscv32/mod.rs +++ b/kernel/src/arch/riscv32/mod.rs @@ -8,36 +8,35 @@ pub mod paging; pub mod memory; pub mod compiler_rt; pub mod consts; -pub mod smp; - -use self::smp::*; - -fn others_main(hartid: usize) -> ! { - println!("hart {} is booting", hartid); - loop { } -} +pub mod cpu; #[no_mangle] pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! { - unsafe { set_cpu_id(hartid); } + unsafe { cpu::set_cpu_id(hartid); } + println!("Hello RISCV! in hart {}, {}, {}", hartid, dtb, hart_mask); if hartid != 0 { - while unsafe { !has_started(hartid) } { } - others_main(hartid); - // others_main should not return + while unsafe { !cpu::has_started(hartid) } { } + others_main(); + unreachable!(); } - println!("Hello RISCV! in hart {}, {}, {}", hartid, dtb, hart_mask); - ::logging::init(); interrupt::init(); memory::init(); timer::init(); - unsafe { start_others(hart_mask); } + unsafe { cpu::start_others(hart_mask); } ::kmain(); } +fn others_main() -> ! { + interrupt::init(); + timer::init(); + cpu::send_ipi(0); + loop { } +} + #[cfg(feature = "no_bbl")] global_asm!(include_str!("boot/boot.asm")); global_asm!(include_str!("boot/entry.asm")); diff --git a/kernel/src/arch/x86_64/cpu.rs b/kernel/src/arch/x86_64/cpu.rs index 18a63d2..b8957dc 100644 --- a/kernel/src/arch/x86_64/cpu.rs +++ b/kernel/src/arch/x86_64/cpu.rs @@ -16,9 +16,9 @@ pub fn id() -> usize { CpuId::new().get_feature_info().unwrap().initial_local_apic_id() as usize } -pub fn send_ipi(cpu_id: u8) { +pub fn send_ipi(cpu_id: usize) { let mut lapic = unsafe { XApic::new(0xffffff00_fee00000) }; - unsafe { lapic.send_ipi(cpu_id, 0x30); } // TODO: Find a IPI trap num + unsafe { lapic.send_ipi(cpu_id as u8, 0x30); } // TODO: Find a IPI trap num } pub fn init() {