Prechádzať zdrojové kódy

feat(prototyper): Add feature `fdt` to support Prototyper packaging device tree

guttatus 3 mesiacov pred
rodič
commit
3f26f9eb6d

+ 1 - 0
prototyper/Cargo.toml

@@ -33,3 +33,4 @@ bench = false
 [features]
 nemu = []
 payload = []
+fdt = []

+ 22 - 4
prototyper/build.rs

@@ -15,20 +15,30 @@ const LINKER_SCRIPT: &[u8] = b"OUTPUT_ARCH(riscv)
 ENTRY(_start) 
 SECTIONS {
     . = 0x80000000;
+
+    . = ALIGN(0x1000); /* Need this to create proper sections */
+
     sbi_start = .;
     .text : ALIGN(8) { 
         *(.text.entry)
         *(.text .text.*)
     }
+
+    . = ALIGN(0x1000); /* Ensure next section is page aligned */
+
     .rodata : ALIGN(8) { 
         srodata = .;
         *(.rodata .rodata.*)
         *(.srodata .srodata.*)
         . = ALIGN(8);  
     } 
+
     .dynsym : ALIGN(8) {
         *(.dynsym)
     }
+
+    . = ALIGN(0x1000); /* Ensure next section is page aligned */
+
     .rela.dyn : ALIGN(8) {
         __rel_dyn_start = .;
         *(.rela*)
@@ -36,6 +46,14 @@ SECTIONS {
     }
 
     erodata = .;
+
+	/*
+	 * PMP regions must be to be power-of-2. RX/RW will have separate
+	 * regions, so ensure that the split is power-of-2.
+	 */
+	. = ALIGN(1 << LOG2CEIL((SIZEOF(.rodata) + SIZEOF(.text)
+				+ SIZEOF(.dynsym) + SIZEOF(.rela.dyn))));
+
     .data : ALIGN(8) { 
         sdata = .;
         *(.data .data.*)
@@ -44,6 +62,9 @@ SECTIONS {
         edata = .;
     }
     sidata = LOADADDR(.data);
+
+    . = ALIGN(0x1000); /* Ensure next section is page aligned */
+
     .bss (NOLOAD) : ALIGN(8) {  
         *(.bss.uninit)
         sbss = .;
@@ -55,12 +76,9 @@ SECTIONS {
         *(.eh_frame)
     }
 
-    . = ALIGN(8);
+	. = ALIGN(0x1000); /* Need this to create proper sections */
     sbi_end = .;
 
-    .text 0x80100000 : ALIGN(8) {
-        *(.fw_fdt)
-    }
     .text 0x80200000 : ALIGN(8) {
         *(.payload)
     }

+ 7 - 22
prototyper/src/board.rs

@@ -91,38 +91,23 @@ impl Board {
     }
 
     pub fn have_console(&self) -> bool {
-        match self.sbi.console {
-            None => false,
-            Some(_) => true,
-        }
+        self.sbi.console.is_some()
     }
 
     pub fn have_reset(&self) -> bool {
-        match self.sbi.reset {
-            None => false,
-            Some(_) => true,
-        }
+        self.sbi.reset.is_some()
     }
 
     pub fn have_ipi(&self) -> bool {
-        match self.sbi.ipi {
-            None => false,
-            Some(_) => true,
-        }
+        self.sbi.ipi.is_some() 
     }
 
     pub fn have_hsm(&self) -> bool {
-        match self.sbi.hsm {
-            None => false,
-            Some(_) => true,
-        }
+        self.sbi.hsm.is_some()
     }
 
     pub fn have_rfence(&self) -> bool {
-        match self.sbi.rfence {
-            None => false,
-            Some(_) => true,
-        }
+        self.sbi.rfence.is_some() 
     }
 
     pub fn ready(&self) -> bool {
@@ -273,7 +258,7 @@ impl Board {
 
     fn sbi_hsm_init(&mut self) {
         // TODO: Can HSM work properly when there is no ipi device?
-        if let Some(_) = self.info.ipi {
+        if self.info.ipi.is_some() {
             self.sbi.hsm = Some(SbiHsm);
         } else {
             self.sbi.hsm = None;
@@ -282,7 +267,7 @@ impl Board {
 
     fn sbi_rfence_init(&mut self) {
         // TODO: Can rfence work properly when there is no ipi device?
-        if let Some(_) = self.info.ipi {
+        if self.info.ipi.is_some() {
             self.sbi.rfence = Some(SbiRFence);
         } else {
             self.sbi.rfence = None;

+ 1 - 1
prototyper/src/fail.rs

@@ -4,7 +4,7 @@ use crate::dt;
 use crate::sbi::reset;
 
 #[cfg(not(feature = "payload"))]
-use crate::platform::dynamic;
+use crate::firmware::dynamic;
 #[cfg(not(feature = "payload"))]
 use riscv::register::mstatus;
 

+ 5 - 10
prototyper/src/platform/dynamic.rs → prototyper/src/firmware/dynamic.rs

@@ -3,33 +3,28 @@
 use core::ops::Range;
 use core::sync::atomic::{AtomicBool, Ordering};
 
-use super::{BootHart, BootInfo};
+use super::BootInfo;
 use crate::fail;
 use crate::riscv_spec::current_hartid;
 
 use riscv::register::mstatus;
 
-/// Gets boot hart information based on opaque and nonstandard_a2 parameters.
+/// Determine whether the current hart is boot hart.
 ///
-/// Returns a BootHart struct containing FDT address and whether this is the boot hart.
-pub fn get_boot_hart(opaque: usize, nonstandard_a2: usize) -> BootHart {
+/// Return true if the current hart is boot hart.
+pub fn is_boot_hart(nonstandard_a2: usize) -> bool {
     // Track whether this is the first hart to boot
     static GENESIS: AtomicBool = AtomicBool::new(true);
 
     let info = read_paddr(nonstandard_a2).unwrap_or_else(fail::use_lottery);
 
     // Determine if this is the boot hart based on hart ID
-    let is_boot_hart = if info.boot_hart == usize::MAX {
+    if info.boot_hart == usize::MAX {
         // If boot_hart is MAX, use atomic bool to determine first hart
         GENESIS.swap(false, Ordering::AcqRel)
     } else {
         // Otherwise check if current hart matches designated boot hart
         current_hartid() == info.boot_hart
-    };
-
-    BootHart {
-        fdt_address: opaque,
-        is_boot_hart,
     }
 }
 

+ 42 - 2
prototyper/src/platform/mod.rs → prototyper/src/firmware/mod.rs

@@ -17,10 +17,50 @@ pub struct BootHart {
     pub is_boot_hart: bool,
 }
 
+
+#[naked]
+#[link_section = ".rodata.fw_fdt"]
+#[repr(align(16))]
+#[cfg(feature = "fdt")]
+pub unsafe extern "C" fn raw_fdt() {
+    asm!(
+        concat!(".incbin \"", env!("PROTOTYPER_FDT_PATH"), "\""),
+        options(noreturn)
+    );
+}
+
+#[inline]
+#[cfg(feature = "fdt")]
+fn get_fdt_address() -> usize {
+    raw_fdt as usize
+}
+
+
 #[cfg(not(feature = "payload"))]
-pub use dynamic::{get_boot_hart, get_boot_info};
+pub use dynamic::{is_boot_hart, get_boot_info};
 #[cfg(feature = "payload")]
-pub use payload::{get_boot_hart, get_boot_info};
+pub use payload::{is_boot_hart, get_boot_info};
+
+/// Gets boot hart information based on opaque and nonstandard_a2 parameters.
+///
+/// Returns a BootHart struct containing FDT address and whether this is the boot hart.
+#[allow(unused_mut, unused_assignments)]
+pub fn get_boot_hart(opaque: usize, nonstandard_a2: usize) -> BootHart {
+    let is_boot_hart = is_boot_hart(nonstandard_a2);
+
+    let mut fdt_address = opaque;
+
+    #[cfg(feature = "fdt")]
+    {
+        fdt_address = get_fdt_address();
+    }
+
+    BootHart {
+        fdt_address,
+        is_boot_hart,
+    }
+}
+
 
 pub fn set_pmp(memory_range: &Range<usize>) {
     unsafe {

+ 6 - 20
prototyper/src/platform/payload.rs → prototyper/src/firmware/payload.rs

@@ -4,13 +4,13 @@ use riscv::register::mstatus;
 
 use super::{BootHart, BootInfo};
 
-pub fn get_boot_hart(_opaque: usize, _nonstandard_a2: usize) -> BootHart {
+/// Determine whether the current hart is boot hart.
+///
+/// Return true if the current hart is boot hart.
+pub fn is_boot_hart(_nonstandard_a2: usize) -> bool {
     static GENESIS: AtomicBool = AtomicBool::new(true);
-    let is_boot_hart = GENESIS.swap(false, Ordering::AcqRel);
-    BootHart {
-        fdt_address: get_fdt_address(),
-        is_boot_hart,
-    }
+    GENESIS.swap(false, Ordering::AcqRel)
+
 }
 
 pub fn get_boot_info(_nonstandard_a2: usize) -> BootInfo {
@@ -20,15 +20,6 @@ pub fn get_boot_info(_nonstandard_a2: usize) -> BootInfo {
     }
 }
 
-#[naked]
-#[link_section = ".fw_fdt"]
-pub unsafe extern "C" fn raw_fdt() {
-    asm!(
-        concat!(".incbin \"", env!("PROTOTYPER_FDT_PATH"), "\""),
-        options(noreturn)
-    );
-}
-
 #[naked]
 #[link_section = ".payload"]
 pub unsafe extern "C" fn payload_image() {
@@ -38,11 +29,6 @@ pub unsafe extern "C" fn payload_image() {
     );
 }
 
-#[inline]
-fn get_fdt_address() -> usize {
-    raw_fdt as usize
-}
-
 #[inline]
 fn get_image_address() -> usize {
     payload_image as usize

+ 6 - 5
prototyper/src/main.rs

@@ -1,4 +1,5 @@
 #![feature(naked_functions)]
+#![feature(fn_align)]
 #![no_std]
 #![no_main]
 #![allow(static_mut_refs)]
@@ -11,7 +12,7 @@ mod macros;
 mod board;
 mod dt;
 mod fail;
-mod platform;
+mod firmware;
 mod riscv_spec;
 mod sbi;
 
@@ -33,7 +34,7 @@ pub const R_RISCV_RELATIVE: usize = 3;
 extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
     // Track whether SBI is initialized and ready.
 
-    let boot_hart_info = platform::get_boot_hart(opaque, nonstandard_a2);
+    let boot_hart_info = firmware::get_boot_hart(opaque, nonstandard_a2);
     // boot hart task entry.
     if boot_hart_info.is_boot_hart {
         // parse the device tree
@@ -45,10 +46,10 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
             BOARD.init(&dtb);
             BOARD.print_board_info();
         }
-        platform::set_pmp(unsafe { BOARD.info.memory_range.as_ref().unwrap() });
+        firmware::set_pmp(unsafe { BOARD.info.memory_range.as_ref().unwrap() });
 
         // Get boot information and prepare for kernel entry.
-        let boot_info = platform::get_boot_info(nonstandard_a2);
+        let boot_info = firmware::get_boot_info(nonstandard_a2);
         let (mpp, next_addr) = (boot_info.mpp, boot_info.next_address);
 
         // Start kernel.
@@ -73,7 +74,7 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
             core::hint::spin_loop()
         }
 
-        platform::set_pmp(unsafe { BOARD.info.memory_range.as_ref().unwrap() });
+        firmware::set_pmp(unsafe { BOARD.info.memory_range.as_ref().unwrap() });
     }
 
     // Clear all pending IPIs.

+ 2 - 2
xtask/src/prototyper.rs

@@ -51,7 +51,7 @@ pub fn run(arg: &PrototyperArg) -> Option<ExitStatus> {
             env::current_dir()
                 .unwrap()
                 .join("target")
-                .join(arch.to_string())
+                .join(arch)
                 .join("release")
                 .join("rustsbi-prototyper"),
         )
@@ -59,7 +59,7 @@ pub fn run(arg: &PrototyperArg) -> Option<ExitStatus> {
             env::current_dir()
                 .unwrap()
                 .join("target")
-                .join(arch.to_string())
+                .join(arch)
                 .join("release")
                 .join("rustsbi-prototyper.bin"),
         )

+ 1 - 1
xtask/src/test.rs

@@ -22,7 +22,7 @@ pub fn run(arg: &TestArg) -> Option<ExitStatus> {
         .as_ref()
         .unwrap()
         .join("target")
-        .join(arch.to_string())
+        .join(arch)
         .join("release");
 
     cargo::Cargo::new("build")