diff --git a/kernel/Makefile b/kernel/Makefile index 38213696..5f1cebd4 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -128,7 +128,7 @@ else qemu_opts += \ -machine virt \ -serial mon:stdio \ - -bios default \ + -bios ../tools/opensbi/fw_jump.elf \ -device loader,addr=0x80200000,file=$(kernel_img) \ -drive file=$(USER_QCOW2),format=qcow2,id=sfs \ -device virtio-blk-device,drive=sfs \ diff --git a/kernel/src/arch/riscv/mod.rs b/kernel/src/arch/riscv/mod.rs index f5b14fd7..81caa258 100644 --- a/kernel/src/arch/riscv/mod.rs +++ b/kernel/src/arch/riscv/mod.rs @@ -22,9 +22,18 @@ pub mod syscall; pub mod timer; use crate::memory::phys_to_virt; -use core::sync::atomic::{AtomicBool, Ordering}; +use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use riscv::register::sie; +fn start_all_harts() { + // simply wake up the first 64 harts. + use sbi::sbi_hart_start; + for i in 0..64 { + let ret = sbi_hart_start(i, 0x80200000usize, i); + info!("Start {}: {:?}", i, ret); + } +} + #[no_mangle] pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { let device_tree_vaddr = phys_to_virt(device_tree_paddr); @@ -33,7 +42,15 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { cpu::set_cpu_id(hartid); } - if hartid != BOOT_HART_ID { + if FIRST_HART + .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) + .is_ok() + { + LOTTERY_HART_ID.store(hartid, Ordering::SeqCst); + start_all_harts(); + } + let main_hart = LOTTERY_HART_ID.load(Ordering::SeqCst); + if hartid != main_hart { while !AP_CAN_INIT.load(Ordering::Relaxed) {} others_main(hartid); } @@ -41,13 +58,8 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { unsafe { memory::clear_bss(); } - - info!( - "Hello RISCV! in hart {}, device tree @ {:#x}", - hartid, device_tree_vaddr - ); - crate::logging::init(); + unsafe { trapframe::init(); } @@ -60,8 +72,12 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { board::init_external_interrupt(); } crate::process::init(); - + info!( + "Hello RISCV! in hart {}, device tree @ {:#x}", + hartid, device_tree_vaddr + ); AP_CAN_INIT.store(true, Ordering::Relaxed); + crate::kmain(); } @@ -76,6 +92,8 @@ fn others_main(hartid: usize) -> ! { } static AP_CAN_INIT: AtomicBool = AtomicBool::new(false); +static FIRST_HART: AtomicBool = AtomicBool::new(false); +static LOTTERY_HART_ID: AtomicUsize = AtomicUsize::new(0); #[cfg(not(feature = "board_u540"))] const BOOT_HART_ID: usize = 0; diff --git a/kernel/src/arch/riscv/sbi.rs b/kernel/src/arch/riscv/sbi.rs index 98b78798..31d37df2 100644 --- a/kernel/src/arch/riscv/sbi.rs +++ b/kernel/src/arch/riscv/sbi.rs @@ -1,8 +1,85 @@ //! Port from sbi.h #![allow(dead_code)] +#[derive(Clone, Copy, Debug)] +pub struct SBIRet { + error: isize, + value: usize, +} +#[derive(Clone, Copy, Debug)] +pub struct SBICall { + eid: usize, + fid: usize, +} #[inline(always)] -fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { +fn sbi_call(which: SBICall, arg0: usize, arg1: usize, arg2: usize) -> SBIRet { + let ret1; + let ret2; + unsafe { + llvm_asm!("ecall" + : "={x10}" (ret1), "={x11}"(ret2) + : "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x17}" (which.eid), "{x16}" (which.fid) + : "memory" + : "volatile"); + } + SBIRet { + error: ret1, + value: ret2, + } +} + +pub fn sbi_hart_start(hartid: usize, start_addr: usize, opaque: usize) -> SBIRet { + sbi_call( + SBICall { + eid: SBI_EID_HSM, + fid: SBI_FID_HSM_START, + }, + hartid, + start_addr as usize, + opaque, + ) +} +pub fn sbi_hart_stop() -> ! { + sbi_call( + SBICall { + eid: SBI_EID_HSM, + fid: SBI_FID_HSM_STOP, + }, + 0, + 0, + 0, + ); + unreachable!(); +} +pub fn sbi_hart_get_status(hartid: usize) -> SBIRet { + sbi_call( + SBICall { + eid: SBI_EID_HSM, + fid: SBI_FID_HSM_START, + }, + hartid, + 0, + 0, + ) +} + +const SBI_SUCCESS: isize = 0; +const SBI_ERR_FAILED: isize = -1; +const SBI_ERR_NOT_SUPPORTED: isize = -2; +const SBI_ERR_INVALID_PARAM: isize = -3; +const SBI_ERR_DENIED: isize = -4; +const SBI_ERR_INVALID_ADDRESS: isize = -5; +const SBI_ERR_ALREADY_AVAILABLE: isize = -6; + +const SBI_EID_HSM: usize = 0x48534D; +const SBI_FID_HSM_START: usize = 0; +const SBI_FID_HSM_STOP: usize = 1; +const SBI_FID_HSM_STATUS: usize = 2; + +/// Legacy calls. + +#[inline(always)] +fn sbi_call_legacy(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { let ret; unsafe { llvm_asm!("ecall" @@ -15,48 +92,48 @@ fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize { } pub fn console_putchar(ch: usize) { - sbi_call(SBI_CONSOLE_PUTCHAR, ch, 0, 0); + sbi_call_legacy(SBI_CONSOLE_PUTCHAR, ch, 0, 0); } pub fn console_getchar() -> usize { - sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0) + sbi_call_legacy(SBI_CONSOLE_GETCHAR, 0, 0, 0) } pub fn shutdown() -> ! { - sbi_call(SBI_SHUTDOWN, 0, 0, 0); + sbi_call_legacy(SBI_SHUTDOWN, 0, 0, 0); unreachable!() } pub fn set_timer(stime_value: u64) { #[cfg(target_pointer_width = "32")] - sbi_call( + sbi_call_legacy( SBI_SET_TIMER, stime_value as usize, (stime_value >> 32) as usize, 0, ); #[cfg(target_pointer_width = "64")] - sbi_call(SBI_SET_TIMER, stime_value as usize, 0, 0); + sbi_call_legacy(SBI_SET_TIMER, stime_value as usize, 0, 0); } pub fn clear_ipi() { - sbi_call(SBI_CLEAR_IPI, 0, 0, 0); + sbi_call_legacy(SBI_CLEAR_IPI, 0, 0, 0); } pub fn send_ipi(hart_mask: usize) { - sbi_call(SBI_SEND_IPI, &hart_mask as *const _ as usize, 0, 0); + sbi_call_legacy(SBI_SEND_IPI, &hart_mask as *const _ 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); + sbi_call_legacy(SBI_REMOTE_FENCE_I, &hart_mask as *const _ 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); + sbi_call_legacy(SBI_REMOTE_SFENCE_VMA, &hart_mask as *const _ as usize, 0, 0); } pub fn remote_sfence_vma_asid(hart_mask: usize, _start: usize, _size: usize, _asid: usize) { - sbi_call( + sbi_call_legacy( SBI_REMOTE_SFENCE_VMA_ASID, &hart_mask as *const _ as usize, 0, @@ -73,3 +150,4 @@ const SBI_REMOTE_FENCE_I: usize = 5; const SBI_REMOTE_SFENCE_VMA: usize = 6; const SBI_REMOTE_SFENCE_VMA_ASID: usize = 7; const SBI_SHUTDOWN: usize = 8; +// Legacy calls end. diff --git a/tools/opensbi/fw_jump.elf b/tools/opensbi/fw_jump.elf new file mode 100755 index 00000000..9fa3494a Binary files /dev/null and b/tools/opensbi/fw_jump.elf differ