Przeglądaj źródła

feat(bench-kernel): impl ipi test

feat(xtask): add bench kernel
fix(prototyper): rename fw_fdt
fix(prototyper): use ALIGN in section name

Signed-off-by: Woshiluo Luo <[email protected]>
Woshiluo Luo 3 miesięcy temu
rodzic
commit
afa1907da5

+ 1 - 0
.cargo/config.toml

@@ -2,3 +2,4 @@
 xtask = "run --package xtask --release --"
 prototyper = "xtask prototyper"
 test-kernel = "xtask test"
+bench-kernel = "xtask bench"

+ 77 - 11
Cargo.lock

@@ -200,6 +200,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
 
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
 [[package]]
 name = "proc-macro2"
 version = "1.0.92"
@@ -238,21 +244,54 @@ dependencies = [
  "embedded-hal",
 ]
 
+[[package]]
+name = "riscv"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7"
+dependencies = [
+ "critical-section",
+ "embedded-hal",
+ "paste",
+ "riscv-pac",
+]
+
 [[package]]
 name = "riscv-decode"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cf8b4cfb0da0528321d22daee4299a23a8c5ac8848623d716e898d2a9eec0694"
 
+[[package]]
+name = "riscv-pac"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436"
+
 [[package]]
 name = "rustsbi"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "44c13763120794ed11d64bac885fb31d384ae385c3287b0697711b97affbf8ab"
 dependencies = [
- "riscv",
+ "riscv 0.11.1",
  "rustsbi-macros",
- "sbi-spec",
+ "sbi-spec 0.0.7",
+]
+
+[[package]]
+name = "rustsbi-bench-kernel"
+version = "0.0.0"
+dependencies = [
+ "log",
+ "rcore-console",
+ "riscv 0.11.1",
+ "sbi-spec 0.0.8",
+ "sbi-testing 0.0.3-alpha.2 (git+https://github.com/rustsbi/rustsbi?rev=4821073)",
+ "serde",
+ "serde-device-tree",
+ "spin",
+ "uart16550",
 ]
 
 [[package]]
@@ -274,10 +313,10 @@ dependencies = [
  "fast-trap",
  "log",
  "panic-halt",
- "riscv",
+ "riscv 0.11.1",
  "riscv-decode",
  "rustsbi",
- "sbi-spec",
+ "sbi-spec 0.0.7",
  "serde",
  "serde-device-tree",
  "sifive-test-device",
@@ -291,7 +330,7 @@ name = "rustsbi-supervisor"
 version = "0.1.0"
 dependencies = [
  "naked-function",
- "sbi-rt",
+ "sbi-rt 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -301,8 +340,8 @@ dependencies = [
  "dtb-walker",
  "log",
  "rcore-console",
- "riscv",
- "sbi-testing",
+ "riscv 0.11.1",
+ "sbi-testing 0.0.3-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "spin",
  "uart16550",
 ]
@@ -313,7 +352,15 @@ version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7fbaa69be1eedc61c426e6d489b2260482e928b465360576900d52d496a58bd0"
 dependencies = [
- "sbi-spec",
+ "sbi-spec 0.0.7",
+]
+
+[[package]]
+name = "sbi-rt"
+version = "0.0.3"
+source = "git+https://github.com/rustsbi/rustsbi?rev=4821073#4821073b56a7223781c11a49aba743785d89d3ea"
+dependencies = [
+ "sbi-spec 0.0.8",
 ]
 
 [[package]]
@@ -322,6 +369,14 @@ version = "0.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890"
 
+[[package]]
+name = "sbi-spec"
+version = "0.0.8"
+source = "git+https://github.com/rustsbi/rustsbi?rev=4821073#4821073b56a7223781c11a49aba743785d89d3ea"
+dependencies = [
+ "bitflags",
+]
+
 [[package]]
 name = "sbi-testing"
 version = "0.0.3-alpha.2"
@@ -329,9 +384,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "135c0f1ce07ede77a7e1c3daff35d20d37b54fd1037ac02ab9595c231518531e"
 dependencies = [
  "log",
- "riscv",
- "sbi-rt",
- "sbi-spec",
+ "riscv 0.11.1",
+ "sbi-rt 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sbi-spec 0.0.7",
+]
+
+[[package]]
+name = "sbi-testing"
+version = "0.0.3-alpha.2"
+source = "git+https://github.com/rustsbi/rustsbi?rev=4821073#4821073b56a7223781c11a49aba743785d89d3ea"
+dependencies = [
+ "log",
+ "riscv 0.12.1",
+ "sbi-rt 0.0.3 (git+https://github.com/rustsbi/rustsbi?rev=4821073)",
+ "sbi-spec 0.0.8",
 ]
 
 [[package]]

+ 1 - 0
Cargo.toml

@@ -2,6 +2,7 @@
 resolver = "2"
 members = [
   "prototyper",
+  "bench-kernel",
   "test-kernel",
   "supervisor", 
   "xtask"

+ 28 - 0
bench-kernel/Cargo.toml

@@ -0,0 +1,28 @@
+cargo-features = ["per-package-target"]
+
+[package]
+name = "rustsbi-bench-kernel"
+version = "0.0.0"
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+forced-target = "riscv64imac-unknown-none-elf"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+sbi-testing = { git = "https://github.com/rustsbi/rustsbi", rev = "4821073", features = ["log"] }
+sbi-spec = { git = "https://github.com/rustsbi/rustsbi", rev = "4821073" }
+serde-device-tree = { git = "https://github.com/rustsbi/serde-device-tree", default-features = false }
+serde = { version = "1.0.202", default-features = false, features = ["derive"] }
+log = "0.4"
+riscv = "0.11.1"
+spin = "0.9"
+uart16550 = "0.0.1"
+rcore-console = "0.0.0"
+
+[[bin]]
+name = "rustsbi-bench-kernel"
+test = false
+bench = false

+ 52 - 0
bench-kernel/build.rs

@@ -0,0 +1,52 @@
+use std::{env, path::PathBuf};
+
+fn main() {
+    let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+    let ld = &out.join("rustsbi-test-kernel.ld");
+
+    std::fs::write(ld, LINKER_SCRIPT).unwrap();
+
+    println!("cargo:rustc-link-arg=-T{}", ld.display());
+    println!("cargo:rustc-link-search={}", out.display());
+}
+
+const LINKER_SCRIPT: &[u8] = b"OUTPUT_ARCH(riscv)
+ENTRY(_start) 
+SECTIONS {
+    . = 0x80200000;
+    istart = .;
+	  .head.text : ALIGN(8) {		
+        KEEP(*(.head.text))
+	  }
+
+    .text : ALIGN(8) { 
+        *(.text.entry)
+        *(.text .text.*)
+    }
+    .rodata : ALIGN(8) { 
+        srodata = .;
+        *(.rodata .rodata.*)
+        *(.srodata .srodata.*)
+        . = ALIGN(8);  
+        erodata = .;
+    } 
+    .data : ALIGN(8) { 
+        sdata = .;
+        *(.data .data.*)
+        *(.sdata .sdata.*)
+        . = ALIGN(8); 
+        edata = .;
+    }
+    sidata = LOADADDR(.data);
+    .bss (NOLOAD) : ALIGN(8) {  
+        *(.bss.uninit)
+        sbss = .;
+        *(.bss .bss.*)
+        *(.sbss .sbss.*)
+        ebss = .;
+    } 
+    iend = .;
+    /DISCARD/ : {
+        *(.eh_frame)
+    }
+}";

+ 44 - 0
bench-kernel/scripts/rustsbi-bench-kernel.its

@@ -0,0 +1,44 @@
+/*
+ * Configuration to load RustSBI before RustSBI Test Kernel
+ */
+ 
+/dts-v1/;
+
+/ {
+			description = "Configuration to load RustSBI before RustSBI Test Kernel";
+
+			images {
+				kernel {
+					description = "rustsbi-bench-kernel";
+					data = /incbin/("./rustsbi-bench-kernel.bin");
+					type = "standalone";
+					os = "u-boot";
+					arch = "riscv";
+					compression = "none";
+					load = /bits/ 64 <0x80200000>;
+				};
+
+				rustsbi {
+					description = "RustSBI Firmware";
+					data = /incbin/("./rustsbi-prototyper.bin");
+					type = "firmware";
+					os = "opensbi";
+					arch = "riscv";
+					compression = "none";
+					load = /bits/ 64 <0x80100000>;
+					entry = /bits/ 64 <0x80100000>;
+				};
+
+			};
+
+		configurations {
+				default = "conf-1";
+
+				conf-1 {
+					description = "RustSBI & RustSBI Bench Kernel";
+					firmware = "rustsbi";
+					loadables = "kernel";
+				};
+		};
+};
+

+ 331 - 0
bench-kernel/src/main.rs

@@ -0,0 +1,331 @@
+#![no_std]
+#![no_main]
+#![feature(naked_functions)]
+#![allow(static_mut_refs)]
+
+#[macro_use]
+extern crate rcore_console;
+
+use core::mem::MaybeUninit;
+use core::sync::{atomic::AtomicBool, atomic::AtomicU64, atomic::Ordering};
+use core::{arch::asm, ptr::null};
+use log::*;
+use sbi::SbiRet;
+use sbi_spec::binary::{HartMask, MaskError};
+use sbi_spec::hsm::hart_state;
+use sbi_testing::sbi;
+use serde::Deserialize;
+use serde_device_tree::{
+    buildin::{Node, NodeSeq, Reg, StrSeq},
+    Dtb, DtbPtr,
+};
+use uart16550::Uart16550;
+
+const RISCV_HEAD_FLAGS: u64 = 0;
+const RISCV_HEADER_VERSION: u32 = 0x2;
+const RISCV_IMAGE_MAGIC: u64 = 0x5643534952; /* Magic number, little endian, "RISCV" */
+const RISCV_INAGE_MAGIC2: u32 = 0x05435352; /* Magic number 2, little endian, "RSC\x05" */
+
+/// boot header
+#[naked]
+#[no_mangle]
+#[link_section = ".head.text"]
+unsafe extern "C" fn _boot_header() -> ! {
+    asm!(
+        "j _start",
+        ".word 0",
+        ".balign 8",
+        ".dword 0x200000",
+        ".dword iend - istart",
+        ".dword {RISCV_HEAD_FLAGS}",
+        ".word  {RISCV_HEADER_VERSION}",
+        ".word  0",
+        ".dword 0",
+        ".dword {RISCV_IMAGE_MAGIC}",
+        ".balign 4",
+        ".word  {RISCV_IMAGE_MAGIC2}",
+        ".word  0",
+        RISCV_HEAD_FLAGS = const RISCV_HEAD_FLAGS,
+        RISCV_HEADER_VERSION = const RISCV_HEADER_VERSION,
+        RISCV_IMAGE_MAGIC = const RISCV_IMAGE_MAGIC,
+        RISCV_IMAGE_MAGIC2 = const RISCV_INAGE_MAGIC2,
+        options(noreturn)
+    );
+}
+
+const STACK_SIZE: usize = 512 * 1024; // 512 KiB
+const MAX_HART_NUM: usize = 128;
+
+#[allow(dead_code)]
+#[derive(Copy, Clone)]
+struct HartStack([u8; STACK_SIZE]);
+
+impl HartStack {
+    pub const fn new() -> Self {
+        HartStack([0; STACK_SIZE])
+    }
+}
+
+#[link_section = ".bss.uninit"]
+static mut STACK: HartStack = HartStack::new();
+#[link_section = ".bss.uninit"]
+static mut HART_STACK: [HartStack; MAX_HART_NUM] = [HartStack::new(); MAX_HART_NUM];
+#[link_section = ".bss.uninit"]
+static mut IPI_SENT: [MaybeUninit<AtomicBool>; MAX_HART_NUM] =
+    [const { MaybeUninit::uninit() }; MAX_HART_NUM];
+#[link_section = ".bss.uninit"]
+static mut SMP_COUNT: usize = 0;
+#[link_section = ".bss.uninit"]
+static mut BOOT_HART_ID: usize = 0;
+
+/// 内核入口。
+///
+/// # Safety
+///
+/// 裸函数。
+#[naked]
+#[no_mangle]
+#[link_section = ".text.entry"]
+unsafe extern "C" fn _start(hartid: usize, device_tree_paddr: usize) -> ! {
+    asm!(
+        // 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:",
+        "   la sp, {stack} + {stack_size}",
+        "   j  {main}",
+        stack_size = const STACK_SIZE,
+        stack      =   sym STACK,
+        main       =   sym rust_main,
+        options(noreturn),
+    )
+}
+
+#[naked]
+#[no_mangle]
+unsafe extern "C" fn init_hart(hartid: usize, opaque: usize) {
+    asm!(
+        "add sp, a1, zero",
+        "csrw sscratch, sp",
+        "call {init_main}",
+        init_main = sym init_main,
+        options(noreturn),
+    )
+}
+
+#[naked]
+#[no_mangle]
+unsafe extern "C" fn core_send_ipi(hartid: usize, opaque: usize) {
+    asm!(
+        "add sp, a1, zero",
+        "csrw sscratch, sp",
+        "call {send_ipi}",
+        send_ipi = sym send_ipi,
+        options(noreturn),
+    )
+}
+
+extern "C" fn send_ipi(hartid: usize) -> ! {
+    if unsafe { !(IPI_SENT[hartid].assume_init_mut().load(Ordering::Relaxed)) } {
+        unsafe {
+            IPI_SENT[hartid]
+                .assume_init_mut()
+                .swap(true, Ordering::AcqRel);
+        };
+        let mut mask = Some(HartMask::from_mask_base(0, 0));
+        for i in 0..unsafe { SMP_COUNT } {
+            if i == unsafe { BOOT_HART_ID } {
+                continue;
+            }
+            if let Some(ref mut mask) = mask {
+                match mask.insert(i) {
+                    Ok(_) => continue,
+                    Err(MaskError::InvalidBit) => {
+                        sbi::remote_sfence_vma(*mask, 0, 0);
+                    }
+                    Err(_) => unreachable!("Failed to construct mask"),
+                }
+            }
+            mask = Some(HartMask::from_mask_base(0b1, i));
+        }
+        if let Some(mask) = mask {
+            sbi::remote_sfence_vma(mask, 0, 0);
+        }
+        unsafe {
+            WAIT_COUNT.fetch_sub(1, Ordering::AcqRel);
+            while WAIT_COUNT.load(Ordering::Relaxed) != 0 {}
+        }
+    } else {
+        unreachable!("resend {}", hartid);
+    }
+    sbi::hart_suspend(sbi::NonRetentive, core_send_ipi as _, unsafe {
+        core::ptr::addr_of!(HART_STACK[hartid + 1]) as _
+    });
+    unreachable!()
+}
+
+extern "C" fn init_main(hartid: usize) -> ! {
+    sbi::hart_suspend(sbi::NonRetentive, core_send_ipi as _, unsafe {
+        core::ptr::addr_of!(HART_STACK[hartid + 1]) as _
+    });
+    unreachable!()
+}
+
+static mut WAIT_COUNT: AtomicU64 = AtomicU64::new(0);
+
+const SUSPENDED: SbiRet = SbiRet::success(hart_state::SUSPENDED);
+
+fn get_time() -> u64 {
+    const CSR_TIME: u32 = 0xc01;
+    let mut low_time: u64;
+    unsafe {
+        asm!("csrr {}, {CSR_TIME}", out(reg) low_time, CSR_TIME = const CSR_TIME);
+    }
+
+    low_time
+}
+
+extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
+    #[derive(Deserialize)]
+    struct Tree<'a> {
+        cpus: Cpus<'a>,
+        chosen: Chosen<'a>,
+    }
+    #[derive(Deserialize)]
+    #[serde(rename_all = "kebab-case")]
+    struct Cpus<'a> {
+        timebase_frequency: u32,
+        cpu: NodeSeq<'a>,
+    }
+    #[derive(Deserialize)]
+    #[serde(rename_all = "kebab-case")]
+    struct Chosen<'a> {
+        stdout_path: StrSeq<'a>,
+    }
+    rcore_console::init_console(&Console);
+    rcore_console::set_log_level(option_env!("LOG"));
+    let dtb_ptr = DtbPtr::from_raw(dtb_pa as _).unwrap();
+    let dtb = Dtb::from(dtb_ptr).share();
+    let root: Node = serde_device_tree::from_raw_mut(&dtb).unwrap();
+    let tree: Tree = root.deserialize();
+    let stdout_path = tree.chosen.stdout_path.iter().next().unwrap();
+    if let Some(node) = root.find(stdout_path) {
+        let reg = node.get_prop("reg").unwrap().deserialize::<Reg>();
+        let address = reg.iter().next().unwrap().0.start;
+        unsafe { UART = Uart16550Map(address as _) };
+    }
+    let smp = tree.cpus.cpu.len();
+    let frequency = tree.cpus.timebase_frequency;
+    info!(
+        r"
+ _____         _     _  __                    _
+|_   _|__  ___| |_  | |/ /___ _ __ _ __   ___| |
+  | |/ _ \/ __| __| | ' // _ \ '__| '_ \ / _ \ |
+  | |  __/\__ \ |_  | . \  __/ |  | | | |  __/ |
+  |_|\___||___/\__| |_|\_\___|_|  |_| |_|\___|_|
+================================================
+| boot hart id          | {hartid:20} |
+| smp                   | {smp:20} |
+| timebase frequency    | {frequency:17} Hz |
+| dtb physical address  | {dtb_pa:#20x} |
+------------------------------------------------"
+    );
+    unsafe {
+        SMP_COUNT = smp;
+        BOOT_HART_ID = hartid;
+    }
+    for i in 0..smp {
+        unsafe {
+            IPI_SENT[i].write(AtomicBool::new(false));
+        }
+        if i != hartid {
+            sbi::hart_start(i, init_hart as _, unsafe {
+                core::ptr::addr_of!(HART_STACK[i + 1]) as _
+            });
+            while sbi::hart_get_status(i) != SUSPENDED {
+                core::hint::spin_loop();
+            }
+        }
+    }
+    info!("Starting test");
+    for i in 0..4 {
+        info!("Test #{i} started");
+        unsafe {
+            for i in 0..smp {
+                IPI_SENT[i].assume_init_mut().swap(false, Ordering::AcqRel);
+                if i != hartid {
+                    while sbi::hart_get_status(i) != SUSPENDED {}
+                }
+            }
+            WAIT_COUNT.swap((smp - 1) as u64, Ordering::AcqRel);
+        }
+        debug!("send ipi!");
+        let start_time = get_time();
+        let mut mask = Some(HartMask::from_mask_base(0, 0));
+        for i in 0..smp {
+            if i == hartid {
+                continue;
+            }
+            if let Some(ref mut mask) = mask {
+                match mask.insert(i) {
+                    Ok(_) => continue,
+                    Err(MaskError::InvalidBit) => {
+                        sbi::send_ipi(*mask);
+                    }
+                    Err(_) => unreachable!("Failed to construct mask"),
+                }
+            }
+            mask = Some(HartMask::from_mask_base(0b1, i));
+        }
+        if let Some(mask) = mask {
+            sbi::send_ipi(mask);
+        }
+        while unsafe { WAIT_COUNT.load(Ordering::Acquire) } != 0 {}
+        let end_time = get_time();
+        println!("Test #{}: {}", i, end_time - start_time);
+    }
+    sbi::system_reset(sbi::Shutdown, sbi::NoReason);
+    unreachable!()
+}
+
+#[cfg_attr(not(test), panic_handler)]
+fn panic(info: &core::panic::PanicInfo) -> ! {
+    let (hart_id, pc): (usize, usize);
+    unsafe { asm!("mv    {}, tp", out(reg) hart_id) };
+    unsafe { asm!("auipc {},  0", out(reg) pc) };
+    info!("[test-kernel-panic] hart {hart_id} {info}");
+    info!("[test-kernel-panic] pc = {pc:#x}");
+    info!("[test-kernel-panic] SBI test FAILED due to panic");
+    sbi::system_reset(sbi::Shutdown, sbi::SystemFailure);
+    loop {}
+}
+
+struct Console;
+static mut UART: Uart16550Map = Uart16550Map(null());
+
+pub struct Uart16550Map(*const Uart16550<u8>);
+
+unsafe impl Sync for Uart16550Map {}
+
+impl Uart16550Map {
+    #[inline]
+    pub fn get(&self) -> &Uart16550<u8> {
+        unsafe { &*self.0 }
+    }
+}
+
+impl rcore_console::Console for Console {
+    #[inline]
+    fn put_char(&self, c: u8) {
+        unsafe { UART.get().write(core::slice::from_ref(&c)) };
+    }
+
+    #[inline]
+    fn put_str(&self, s: &str) {
+        unsafe { UART.get().write(s.as_bytes()) };
+    }
+}

+ 9 - 15
prototyper/build.rs

@@ -19,27 +19,23 @@ SECTIONS {
     . = ALIGN(0x1000); /* Need this to create proper sections */
 
     sbi_start = .;
-    .text : ALIGN(8) { 
+    .text : ALIGN(0x1000) { 
         *(.text.entry)
         *(.text .text.*)
     }
 
-    . = ALIGN(0x1000); /* Ensure next section is page aligned */
-
-    .rodata : ALIGN(8) { 
+    .rodata : ALIGN(0x1000) { 
         srodata = .;
         *(.rodata .rodata.*)
         *(.srodata .srodata.*)
-        . = ALIGN(8);  
+        . = ALIGN(0x1000);  
     } 
 
-    .dynsym : ALIGN(8) {
+    .dynsym : ALIGN(0x1000) {
         *(.dynsym)
     }
 
-    . = ALIGN(0x1000); /* Ensure next section is page aligned */
-
-    .rela.dyn : ALIGN(8) {
+    .rela.dyn : ALIGN(0x1000) {
         __rel_dyn_start = .;
         *(.rela*)
         __rel_dyn_end = .;
@@ -54,18 +50,16 @@ SECTIONS {
 	. = ALIGN(1 << LOG2CEIL((SIZEOF(.rodata) + SIZEOF(.text)
 				+ SIZEOF(.dynsym) + SIZEOF(.rela.dyn))));
 
-    .data : ALIGN(8) { 
+    .data : ALIGN(0x1000) { 
         sdata = .;
         *(.data .data.*)
         *(.sdata .sdata.*)
-        . = ALIGN(8); 
+        . = ALIGN(0x1000); 
         edata = .;
     }
     sidata = LOADADDR(.data);
 
-    . = ALIGN(0x1000); /* Ensure next section is page aligned */
-
-    .bss (NOLOAD) : ALIGN(8) {  
+    .bss (NOLOAD) : ALIGN(0x1000) {  
         *(.bss.uninit)
         sbss = .;
         *(.bss .bss.*)
@@ -79,7 +73,7 @@ SECTIONS {
 	. = ALIGN(0x1000); /* Need this to create proper sections */
     sbi_end = .;
 
-    .text 0x80200000 : ALIGN(8) {
+    .text 0x80200000 : ALIGN(0x1000) {
         *(.payload)
     }
 }";

+ 3 - 6
prototyper/src/firmware/mod.rs

@@ -17,9 +17,8 @@ pub struct BootHart {
     pub is_boot_hart: bool,
 }
 
-
 #[naked]
-#[link_section = ".rodata.fw_fdt"]
+#[link_section = ".rodata.fdt"]
 #[repr(align(16))]
 #[cfg(feature = "fdt")]
 pub unsafe extern "C" fn raw_fdt() {
@@ -35,11 +34,10 @@ fn get_fdt_address() -> usize {
     raw_fdt as usize
 }
 
-
 #[cfg(not(feature = "payload"))]
-pub use dynamic::{is_boot_hart, get_boot_info};
+pub use dynamic::{get_boot_info, is_boot_hart};
 #[cfg(feature = "payload")]
-pub use payload::{is_boot_hart, get_boot_info};
+pub use payload::{get_boot_info, is_boot_hart};
 
 /// Gets boot hart information based on opaque and nonstandard_a2 parameters.
 ///
@@ -61,7 +59,6 @@ pub fn get_boot_hart(opaque: usize, nonstandard_a2: usize) -> BootHart {
     }
 }
 
-
 pub fn set_pmp(memory_range: &Range<usize>) {
     unsafe {
         // [0..memory_range.start] RW

+ 72 - 0
xtask/src/bench.rs

@@ -0,0 +1,72 @@
+use std::{
+    env, fs,
+    process::{Command, ExitStatus},
+};
+
+use clap::Args;
+
+use crate::utils::cargo;
+
+#[derive(Debug, Args, Clone)]
+pub struct BenchArg {
+    /// Package Prototyper and Test-Kernel
+    #[clap(long)]
+    pub pack: bool,
+}
+
+#[must_use]
+pub fn run(arg: &BenchArg) -> Option<ExitStatus> {
+    let arch = "riscv64imac-unknown-none-elf";
+    let current_dir = env::current_dir();
+    let target_dir = current_dir
+        .as_ref()
+        .unwrap()
+        .join("target")
+        .join(arch)
+        .join("release");
+
+    cargo::Cargo::new("build")
+        .package("rustsbi-bench-kernel")
+        .target(arch)
+        .release()
+        .status()
+        .ok()?;
+
+    let exit_status = Command::new("rust-objcopy")
+        .args(["-O", "binary"])
+        .arg("--binary-architecture=riscv64")
+        .arg(target_dir.join("rustsbi-bench-kernel"))
+        .arg(target_dir.join("rustsbi-bench-kernel.bin"))
+        .status()
+        .ok()?;
+
+    if arg.pack {
+        match fs::exists(target_dir.join("rustsbi-prototyper.bin")) {
+            Ok(true) => {}
+            Ok(false) => {
+                panic!(" Couldn't open \"rustsbi-prototyper.bin\": No such file or directory. Please compile Prototyper first");
+            }
+            Err(_) => {
+                panic!("Can't check existence of file rustsbi-prototyper.bin, please compile Prototyper first");
+            }
+        }
+        fs::copy(
+            current_dir
+                .as_ref()
+                .unwrap()
+                .join("bench-kernel")
+                .join("scripts")
+                .join("rustsbi-bench-kernel.its"),
+            target_dir.join("rustsbi-bench-kernel.its"),
+        )
+        .ok()?;
+        env::set_current_dir(&target_dir).ok()?;
+        Command::new("mkimage")
+            .args(["-f", "rustsbi-bench-kernel.its"])
+            .arg("rustsbi-bench-kernel.itb")
+            .status()
+            .ok()?;
+        fs::remove_file(env::current_dir().unwrap().join("rustsbi-bench-kernel.its")).ok()?;
+    }
+    Some(exit_status)
+}

+ 5 - 2
xtask/src/main.rs

@@ -1,12 +1,13 @@
-use std::process::ExitCode;
 use clap::{Parser, Subcommand};
+use std::process::ExitCode;
 
 #[macro_use]
 mod utils;
+mod bench;
 mod prototyper;
 mod test;
 
-
+use crate::bench::BenchArg;
 use crate::prototyper::PrototyperArg;
 use crate::test::TestArg;
 
@@ -25,12 +26,14 @@ struct Cli {
 enum Cmd {
     Prototyper(PrototyperArg),
     Test(TestArg),
+    Bench(BenchArg),
 }
 
 fn main() -> ExitCode {
     if let Some(code) = match Cli::parse().cmd {
         Cmd::Prototyper(ref arg) => prototyper::run(arg),
         Cmd::Test(ref arg) => test::run(arg),
+        Cmd::Bench(ref arg) => bench::run(arg),
     } {
         if code.success() {
             return ExitCode::SUCCESS;