Переглянути джерело

feat(supervisor): use ArceOS Unikernel to build a S-mode bootloader prototype

Signed-off-by: Zhouqi Jiang <luojia@hust.edu.cn>
Zhouqi Jiang 2 місяців тому
батько
коміт
e24ac6b5c6

+ 7 - 4
supervisor/Cargo.toml

@@ -6,7 +6,10 @@ license.workspace = true
 repository.workspace = true
 
 [dependencies]
-naked-function = "0.1.5"
-sbi-rt = "0.0.3"
-rcore-console = "0.0.0"
-uart16550 = "0.0.1"
+axstd = { git = "https://github.com/arceos-org/arceos.git", optional = true }
+
+[features]
+default = ["axstd"]
+axstd = ["dep:axstd"]
+
+log-level-trace = ["axstd/log-level-trace"]

+ 81 - 0
supervisor/axconfig.toml

@@ -0,0 +1,81 @@
+# Architecture identifier.
+arch = "riscv64" # str
+# Platform identifier.
+platform = "riscv64-qemu-virt" # str
+# Number of CPUs
+smp = 1 # uint
+# Stack size of each task.
+task-stack-size = 0x40000 # uint
+# Number of timer ticks per second (Hz). A timer tick may contain several timer
+# interrupts.
+ticks-per-sec = 100 # uint
+
+#
+# Device specifications
+#
+[devices]
+# MMIO regions with format (`base_paddr`, `size`).
+mmio-regions = [
+    [0x0010_1000, 0x1000],
+    [0x0c00_0000, 0x21_0000],
+    [0x1000_0000, 0x1000],
+    [0x1000_1000, 0x8000],
+    [0x3000_0000, 0x1000_0000],
+    [0x4000_0000, 0x4000_0000]
+] # [(uint, uint)]
+# End PCI bus number (`bus-range` property in device tree).
+pci-bus-end = 0xff # uint
+# Base physical address of the PCIe ECAM space.
+pci-ecam-base = 0x3000_0000 # uint
+# PCI device memory ranges (`ranges` property in device tree).
+pci-ranges = [
+    [0x0300_0000, 0x1_0000],
+    [0x4000_0000, 0x4000_0000],
+    [0x4_0000_0000, 0x4_0000_0000]
+] # [(uint, uint)]
+# rtc@101000 {
+#     interrupts = <0x0b>;
+#     interrupt-parent = <0x03>;
+#     reg = <0x00 0x101000 0x00 0x1000>;
+#     compatible = "google,goldfish-rtc";
+# };
+# RTC (goldfish) Address
+rtc-paddr = 0x10_1000 # uint
+# Timer interrupt frequency in Hz.
+timer-frequency = 10_000_000 # uint
+# VirtIO MMIO regions with format (`base_paddr`, `size`).
+virtio-mmio-regions = [
+    [0x1000_1000, 0x1000],
+    [0x1000_2000, 0x1000],
+    [0x1000_3000, 0x1000],
+    [0x1000_4000, 0x1000],
+    [0x1000_5000, 0x1000],
+    [0x1000_6000, 0x1000],
+    [0x1000_7000, 0x1000],
+    [0x1000_8000, 0x1000]
+] # [(uint, uint)]
+
+#
+# Platform configs
+#
+[plat]
+# Platform family.
+family = "riscv64-qemu-virt" # str
+# Kernel address space base.
+kernel-aspace-base = "0xffff_ffc0_0000_0000" # uint
+# Kernel address space size.
+kernel-aspace-size = "0x0000_003f_ffff_f000" # uint
+# Base physical address of the kernel image.
+kernel-base-paddr = 0x8020_0000 # uint
+# Base virtual address of the kernel image.
+kernel-base-vaddr = "0xffff_ffc0_8020_0000" # uint
+# Offset of bus address and phys address. some boards, the bus address is
+# different from the physical address.
+phys-bus-offset = 0 # uint
+# Base address of the whole physical memory.
+phys-memory-base = 0x8000_0000 # uint
+# Size of the whole physical memory. (128M)
+phys-memory-size = 0x800_0000 # uint
+# Linear mapping offset, for quick conversions between physical and virtual
+# addresses.
+phys-virt-offset = "0xffff_ffc0_0000_0000" # uint

+ 1 - 43
supervisor/build.rs

@@ -1,45 +1,3 @@
 fn main() {
-    use std::{env, fs, path::PathBuf};
-
-    let ld = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("linker.ld");
-    fs::write(&ld, LINKER).unwrap();
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=LOG");
-    println!("cargo:rustc-link-arg=-T{}", ld.display());
+    println!("cargo:rustc-link-arg=-Ttarget/riscv64imac-unknown-none-elf/release/linker_riscv64-qemu-virt.lds");
 }
-
-const LINKER: &[u8] = b"
-OUTPUT_ARCH(riscv)
-ENTRY(_start)
-MEMORY {
-    RAM : ORIGIN = 0x80200000, LENGTH = 64M
-}
-SECTIONS {
-    .text : {
-        *(.text.entry)
-        *(.text .text.*)
-    } > RAM
-    .rodata : {
-        *(.rodata .rodata.*)
-        *(.srodata .srodata.*)
-    } > RAM
-    .data : {
-        sidata = LOADADDR(.data);
-        sdata = .;
-        *(.data .data.*)
-        *(.sdata .sdata.*)
-        edata = .;
-    } > RAM
-    .bss (NOLOAD) : {
-        *(.bss.uninit)
-        . = ALIGN(8);
-        sbss = .;
-        *(.bss .bss.*)
-        *(.sbss .sbss.*)
-        . = ALIGN(8);
-        ebss = .;
-    } > RAM
-    /DISCARD/ : {
-        *(.eh_frame)
-    }
-}";

+ 0 - 3
supervisor/src/drivers.rs

@@ -1,3 +0,0 @@
-mod uart16550u8;
-
-pub use uart16550u8::Uart16550U8;

+ 0 - 17
supervisor/src/drivers/uart16550u8.rs

@@ -1,17 +0,0 @@
-use core::{marker::PhantomData, ptr};
-
-pub struct Uart16550U8<'a> {
-    pub(crate) base: *const uart16550::Uart16550<u8>,
-    _marker: PhantomData<&'a ()>,
-}
-
-impl<'a> Uart16550U8<'a> {
-    pub const unsafe fn new(addr: usize) -> Self {
-        Self {
-            base: ptr::without_provenance(addr),
-            _marker: PhantomData,
-        }
-    }
-}
-
-unsafe impl<'a> Sync for Uart16550U8<'a> {}

+ 0 - 58
supervisor/src/entry.rs

@@ -1,58 +0,0 @@
-const LEN_STACK_PER_HART: usize = 16 * 1024;
-pub const NUM_HART_MAX: usize = 8;
-#[link_section = ".bss.uninit"]
-static mut STACK: [u8; NUM_HART_MAX * LEN_STACK_PER_HART] = [0; NUM_HART_MAX * LEN_STACK_PER_HART];
-
-// If booted with RISC-V SBI, a0 must include hart ID, while a1 must be an opaque register
-#[naked_function::naked]
-#[link_section = ".text.entry"]
-#[export_name = "_start"]
-unsafe extern "C" fn start() -> ! {
-    asm!(
-        // 1. Turn off interrupt
-        "   csrw    sie, zero",
-        // 2. Initialize programming language runtime
-        // only initialize if it is boot hart (hart ID 0)
-        "   bnez    a0, 4f",
-        // 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:",
-        // prepare data segment
-        "   la      t3, sidata
-            la      t4, sdata
-            la      t5, edata
-        3:  bgeu    t4, t5, 4f
-            ld      t6, 0(t3)
-            sd      t6, 0(t4)
-            addi    t3, t3, 8
-            addi    t4, t4, 8
-            j       3b",
-        "4:",
-        "   la      sp, {stack}
-            li      t0, {per_hart_stack_size}
-            addi    t1, a0, 1
-        5:  add     sp, sp, t0
-            addi    t1, t1, -1
-            bnez    t1, 5b",
-        // 4. Start main function
-        "   call    {main}",
-        "   call    {exit}",
-        stack = sym STACK,
-        per_hart_stack_size = const LEN_STACK_PER_HART,
-        main = sym crate::rust_main,
-        exit = sym rust_sbi_exit
-    )
-}
-
-#[no_mangle]
-extern "C" fn rust_sbi_exit() -> ! {
-    sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::NoReason);
-    loop {
-        core::hint::spin_loop();
-    }
-}

+ 7 - 23
supervisor/src/main.rs

@@ -1,26 +1,10 @@
-#![feature(strict_provenance)]
-#![no_std]
-#![no_main]
+#![cfg_attr(feature = "axstd", no_std)]
+#![cfg_attr(feature = "axstd", no_main)]
 
-// TODO: RustSBI EFI module
-use rcore_console::println;
+#[cfg(feature = "axstd")]
+use axstd::println;
 
-mod drivers;
-mod entry;
-mod platform;
-
-#[no_mangle]
-extern "C" fn rust_main(_hart_id: usize, _opaque: usize) {
-    platform::platform_init();
-
-    println!("Hello world!");
-    // TODO
-}
-
-#[panic_handler]
-fn panic(_info: &core::panic::PanicInfo) -> ! {
-    // TODO panic handler
-    loop {
-        core::hint::spin_loop();
-    }
+#[cfg_attr(feature = "axstd", no_mangle)]
+fn main() {
+    println!("Hello, world!");
 }

+ 0 - 5
supervisor/src/platform.rs

@@ -1,5 +0,0 @@
-mod qemu_system_riscv64;
-
-pub fn platform_init() {
-    qemu_system_riscv64::platform_init();
-}

+ 0 - 18
supervisor/src/platform/qemu_system_riscv64.rs

@@ -1,18 +0,0 @@
-use crate::drivers::Uart16550U8;
-
-static CONSOLE: Uart16550U8 = unsafe { Uart16550U8::new(0x10000000) };
-
-struct Console;
-
-impl rcore_console::Console for Console {
-    fn put_char(&self, c: u8) {
-        unsafe { &*CONSOLE.base }.write(&[c]);
-    }
-    fn put_str(&self, s: &str) {
-        unsafe { &*CONSOLE.base }.write(s.as_bytes());
-    }
-}
-
-pub fn platform_init() {
-    rcore_console::init_console(&Console);
-}