Enable RV32 IPI.

master
WangRunji 6 years ago
parent ff18852c56
commit 5bc392f388

@ -36,20 +36,20 @@ pub fn clear_ipi() {
sbi_call(SBI_CLEAR_IPI, 0, 0, 0); sbi_call(SBI_CLEAR_IPI, 0, 0, 0);
} }
pub fn send_ipi(hart_mask: *const usize) { pub fn send_ipi(hart_mask: usize) {
sbi_call(SBI_SEND_IPI, hart_mask as usize, 0, 0); sbi_call(SBI_SEND_IPI, &hart_mask as *const _ as usize, 0, 0);
} }
pub fn remote_fence_i(hart_mask: *const usize) { pub fn remote_fence_i(hart_mask: usize) {
sbi_call(SBI_REMOTE_FENCE_I, hart_mask as usize, 0, 0); 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) { pub fn remote_sfence_vma(hart_mask: usize, _start: usize, _size: usize) {
sbi_call(SBI_REMOTE_SFENCE_VMA, hart_mask as usize, 0, 0); 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) { 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 usize, 0, 0); sbi_call(SBI_REMOTE_SFENCE_VMA_ASID, &hart_mask as *const _ as usize, 0, 0);
} }
const SBI_SET_TIMER: usize = 0; const SBI_SET_TIMER: usize = 0;

@ -33,12 +33,16 @@ ifeq ($(arch), x86_64)
qemu_opts := \ qemu_opts := \
-drive format=raw,file=$(bootimage) \ -drive format=raw,file=$(bootimage) \
-drive format=raw,file=$(SFSIMG),media=disk,cache=writeback \ -drive format=raw,file=$(SFSIMG),media=disk,cache=writeback \
-smp $(smp) \ -smp cores=$(smp) \
-serial mon:stdio \ -serial mon:stdio \
-device isa-debug-exit -device isa-debug-exit
endif endif
ifeq ($(arch), riscv32) ifeq ($(arch), riscv32)
qemu_opts := -machine virt -kernel $(bin) -nographic -smp cpus=$(smp) qemu_opts := \
-machine virt \
-kernel $(bin) \
-nographic \
-smp cores=$(smp)
endif endif
ifdef board ifdef board

@ -5,19 +5,19 @@ use memory::*;
static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM]; static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM];
pub unsafe fn set_cpu_id(cpu_id: usize) { 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 { pub fn id() -> usize {
let mut cpu_id = 0; let cpu_id;
unsafe { unsafe { asm!("mv $0, tp" : "=r"(cpu_id)); }
asm!("mv $0, tp" : : "r" (cpu_id));
}
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 { pub unsafe fn has_started(cpu_id: usize) -> bool {
read_volatile(&STARTED[cpu_id]) read_volatile(&STARTED[cpu_id])
} }

@ -14,6 +14,8 @@ pub fn init() {
sscratch::write(0); sscratch::write(0);
// Set the exception vector address // Set the exception vector address
stvec::write(__alltraps as usize, stvec::TrapMode::Direct); stvec::write(__alltraps as usize, stvec::TrapMode::Direct);
// Enable IPI
sie::set_ssoft();
} }
info!("interrupt: init end"); 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}; use super::riscv::register::scause::{Trap, Interrupt as I, Exception as E};
trace!("Interrupt: {:?}", tf.scause.cause()); trace!("Interrupt: {:?}", tf.scause.cause());
match tf.scause.cause() { match tf.scause.cause() {
Trap::Interrupt(I::SupervisorSoft) => ipi(),
Trap::Interrupt(I::SupervisorTimer) => timer(), Trap::Interrupt(I::SupervisorTimer) => timer(),
Trap::Exception(E::IllegalInstruction) => illegal_inst(tf), Trap::Exception(E::IllegalInstruction) => illegal_inst(tf),
Trap::Exception(E::UserEnvCall) => syscall(tf), Trap::Exception(E::UserEnvCall) => syscall(tf),
@ -51,6 +54,11 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
trace!("Interrupt end"); trace!("Interrupt end");
} }
fn ipi() {
debug!("IPI");
super::bbl::sbi::clear_ipi();
}
fn timer() { fn timer() {
::trap::timer(); ::trap::timer();
super::timer::set_next(); super::timer::set_next();

@ -8,36 +8,35 @@ pub mod paging;
pub mod memory; pub mod memory;
pub mod compiler_rt; pub mod compiler_rt;
pub mod consts; pub mod consts;
pub mod smp; pub mod cpu;
use self::smp::*;
fn others_main(hartid: usize) -> ! {
println!("hart {} is booting", hartid);
loop { }
}
#[no_mangle] #[no_mangle]
pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! { 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 { if hartid != 0 {
while unsafe { !has_started(hartid) } { } while unsafe { !cpu::has_started(hartid) } { }
others_main(hartid); others_main();
// others_main should not return unreachable!();
} }
println!("Hello RISCV! in hart {}, {}, {}", hartid, dtb, hart_mask);
::logging::init(); ::logging::init();
interrupt::init(); interrupt::init();
memory::init(); memory::init();
timer::init(); timer::init();
unsafe { start_others(hart_mask); } unsafe { cpu::start_others(hart_mask); }
::kmain(); ::kmain();
} }
fn others_main() -> ! {
interrupt::init();
timer::init();
cpu::send_ipi(0);
loop { }
}
#[cfg(feature = "no_bbl")] #[cfg(feature = "no_bbl")]
global_asm!(include_str!("boot/boot.asm")); global_asm!(include_str!("boot/boot.asm"));
global_asm!(include_str!("boot/entry.asm")); global_asm!(include_str!("boot/entry.asm"));

@ -16,9 +16,9 @@ pub fn id() -> usize {
CpuId::new().get_feature_info().unwrap().initial_local_apic_id() as 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) }; 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() { pub fn init() {

Loading…
Cancel
Save