|
@@ -10,8 +10,11 @@ mod macros;
|
|
|
|
|
|
mod board;
|
|
|
mod dt;
|
|
|
+#[cfg(not(feature = "fw_payload"))]
|
|
|
mod dynamic;
|
|
|
mod fail;
|
|
|
+#[cfg(feature = "fw_payload")]
|
|
|
+mod payload;
|
|
|
mod riscv_spec;
|
|
|
mod sbi;
|
|
|
|
|
@@ -34,37 +37,53 @@ use crate::sbi::SBI;
|
|
|
#[no_mangle]
|
|
|
extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
|
|
|
// parse dynamic information
|
|
|
+ #[cfg(not(feature = "fw_payload"))]
|
|
|
let info = dynamic::read_paddr(nonstandard_a2).unwrap_or_else(fail::no_dynamic_info_available);
|
|
|
static GENESIS: AtomicBool = AtomicBool::new(true);
|
|
|
static SBI_READY: AtomicBool = AtomicBool::new(false);
|
|
|
|
|
|
+ #[cfg(not(feature = "fw_payload"))]
|
|
|
let is_boot_hart = if info.boot_hart == usize::MAX {
|
|
|
GENESIS.swap(false, Ordering::AcqRel)
|
|
|
} else {
|
|
|
current_hartid() == info.boot_hart
|
|
|
};
|
|
|
+ #[cfg(feature = "fw_payload")]
|
|
|
+ let is_boot_hart = true;
|
|
|
+
|
|
|
+ #[cfg(feature = "fw_payload")]
|
|
|
+ let fdt_address = payload::get_fdt_address();
|
|
|
+ #[cfg(not(feature = "fw_payload"))]
|
|
|
+ let fdt_address = opaque;
|
|
|
|
|
|
if is_boot_hart {
|
|
|
+ #[cfg(feature = "fw_payload")]
|
|
|
+ let (mpp, next_addr) = (mstatus::MPP::Supervisor, payload::get_image_address());
|
|
|
+ #[cfg(not(feature = "fw_payload"))]
|
|
|
let (mpp, next_addr) =
|
|
|
dynamic::mpp_next_addr(&info).unwrap_or_else(fail::invalid_dynamic_data);
|
|
|
|
|
|
- // parse the device tree
|
|
|
-
|
|
|
// 1. Init FDT
|
|
|
- let dtb = dt::parse_device_tree(opaque).unwrap_or_else(fail::device_tree_format);
|
|
|
+ // parse the device tree
|
|
|
+ let dtb = dt::parse_device_tree(fdt_address).unwrap_or_else(fail::device_tree_format);
|
|
|
let dtb = dtb.share();
|
|
|
let tree =
|
|
|
serde_device_tree::from_raw_mut(&dtb).unwrap_or_else(fail::device_tree_deserialize);
|
|
|
|
|
|
// 2. Init device
|
|
|
// TODO: The device base address should be find in a better way
|
|
|
- let reset_device = tree.soc.test.unwrap().iter().next().unwrap();
|
|
|
let console_base = tree.soc.serial.unwrap().iter().next().unwrap();
|
|
|
let clint_device = tree.soc.clint.unwrap().iter().next().unwrap();
|
|
|
- let reset_base_address = reset_device.at();
|
|
|
let console_base_address = console_base.at();
|
|
|
let ipi_base_address = clint_device.at();
|
|
|
- board::reset_dev_init(usize::from_str_radix(reset_base_address, 16).unwrap());
|
|
|
+
|
|
|
+ // Set reset device if found it
|
|
|
+ if let Some(test) = tree.soc.test {
|
|
|
+ let reset_device = test.iter().next().unwrap();
|
|
|
+ let reset_base_address = reset_device.at();
|
|
|
+ board::reset_dev_init(usize::from_str_radix(reset_base_address, 16).unwrap());
|
|
|
+ }
|
|
|
+
|
|
|
board::console_dev_init(usize::from_str_radix(console_base_address, 16).unwrap());
|
|
|
board::ipi_dev_init(usize::from_str_radix(ipi_base_address, 16).unwrap());
|
|
|
// Assume sstc is enabled only if all hart has sstc ext
|
|
@@ -82,6 +101,8 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
|
|
|
isa.iter().find(|&x| x == "sstc").is_some()
|
|
|
})
|
|
|
.all(|x| x);
|
|
|
+ #[cfg(feature = "nemu")]
|
|
|
+ let sstc_support = true;
|
|
|
// 3. Init SBI
|
|
|
unsafe {
|
|
|
SBI_IMPL = MaybeUninit::new(SBI {
|
|
@@ -105,7 +126,6 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
|
|
|
info!("Support sstc: {sstc_support}");
|
|
|
info!("Clint device: {}", ipi_base_address);
|
|
|
info!("Console deivce: {}", console_base_address);
|
|
|
- info!("Reset device: {}", reset_base_address);
|
|
|
info!(
|
|
|
"Chosen stdout item: {}",
|
|
|
tree.chosen
|
|
@@ -131,7 +151,7 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
|
|
|
local_remote_hsm().start(NextStage {
|
|
|
start_addr: next_addr,
|
|
|
next_mode: mpp,
|
|
|
- opaque,
|
|
|
+ opaque: fdt_address,
|
|
|
});
|
|
|
|
|
|
info!(
|
|
@@ -179,6 +199,7 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
|
|
|
#[naked]
|
|
|
#[link_section = ".text.entry"]
|
|
|
#[export_name = "_start"]
|
|
|
+#[cfg(not(feature = "fw_payload"))]
|
|
|
unsafe extern "C" fn start() -> ! {
|
|
|
core::arch::asm!(
|
|
|
// 1. Turn off interrupt
|
|
@@ -216,6 +237,37 @@ unsafe extern "C" fn start() -> ! {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+#[naked]
|
|
|
+#[link_section = ".text.entry"]
|
|
|
+#[export_name = "_start"]
|
|
|
+#[cfg(feature = "fw_payload")]
|
|
|
+unsafe extern "C" fn start() -> ! {
|
|
|
+ core::arch::asm!(
|
|
|
+ // 1. Turn off interrupt
|
|
|
+ " csrw mie, zero",
|
|
|
+ // 2. Initialize programming langauge runtime
|
|
|
+ // only clear bss if hartid matches preferred boot hart id
|
|
|
+ " csrr t0, mhartid",
|
|
|
+ // 3. clear bss segment
|
|
|
+ " la t0, sbss
|
|
|
+ la t1, ebss
|
|
|
+ 1: bgeu t0, t1, 2f
|
|
|
+ sd zero, 0(t0)
|
|
|
+ addi t0, t0, 8
|
|
|
+ j 1b",
|
|
|
+ "2:",
|
|
|
+ // 4. Prepare stack for each hart
|
|
|
+ " call {locate_stack}",
|
|
|
+ " call {main}",
|
|
|
+ " csrw mscratch, sp",
|
|
|
+ " j {hart_boot}",
|
|
|
+ locate_stack = sym trap_stack::locate,
|
|
|
+ main = sym rust_main,
|
|
|
+ hart_boot = sym trap::msoft,
|
|
|
+ options(noreturn)
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
#[panic_handler]
|
|
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
|
|
use riscv::register::*;
|