Browse Source

feat(supervisor): add console subsystem, support QEMU RV64

Signed-off-by: Zhouqi Jiang <luojia@hust.edu.cn>
Zhouqi Jiang 3 months ago
parent
commit
5652d3fa80

+ 3 - 1
Cargo.lock

@@ -506,10 +506,12 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "rustsbi-supervisor"
 name = "rustsbi-supervisor"
-version = "0.1.0"
+version = "0.0.0"
 dependencies = [
 dependencies = [
  "naked-function",
  "naked-function",
+ "rcore-console",
  "sbi-rt 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "sbi-rt 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "uart16550",
 ]
 ]
 
 
 [[package]]
 [[package]]

+ 8 - 9
prototyper/src/platform/console.rs

@@ -1,6 +1,6 @@
+use bouffalo_hal::uart::RegisterBlock as BflbUartRegisterBlock;
 use uart16550::{Register, Uart16550};
 use uart16550::{Register, Uart16550};
 use uart_xilinx::MmioUartAxiLite;
 use uart_xilinx::MmioUartAxiLite;
-use bouffalo_hal::uart::RegisterBlock as BflbUartRegisterBlock;
 
 
 use crate::sbi::console::ConsoleDevice;
 use crate::sbi::console::ConsoleDevice;
 pub(crate) const UART16650U8_COMPATIBLE: [&str; 1] = ["ns16550a"];
 pub(crate) const UART16650U8_COMPATIBLE: [&str; 1] = ["ns16550a"];
@@ -41,7 +41,6 @@ impl<R: Register> ConsoleDevice for Uart16550Wrap<R> {
     }
     }
 }
 }
 
 
-
 /// For Uart AxiLite
 /// For Uart AxiLite
 impl ConsoleDevice for MmioUartAxiLite {
 impl ConsoleDevice for MmioUartAxiLite {
     fn read(&self, buf: &mut [u8]) -> usize {
     fn read(&self, buf: &mut [u8]) -> usize {
@@ -55,21 +54,20 @@ impl ConsoleDevice for MmioUartAxiLite {
 
 
 /// For Uart BFLB
 /// For Uart BFLB
 pub struct UartBflbWrap {
 pub struct UartBflbWrap {
-    inner: *const BflbUartRegisterBlock
+    inner: *const BflbUartRegisterBlock,
 }
 }
 
 
 impl UartBflbWrap {
 impl UartBflbWrap {
     pub fn new(base: usize) -> Self {
     pub fn new(base: usize) -> Self {
         Self {
         Self {
-            inner: base as *const BflbUartRegisterBlock
+            inner: base as *const BflbUartRegisterBlock,
         }
         }
-        
     }
     }
 }
 }
 
 
 impl ConsoleDevice for UartBflbWrap {
 impl ConsoleDevice for UartBflbWrap {
     fn read(&self, buf: &mut [u8]) -> usize {
     fn read(&self, buf: &mut [u8]) -> usize {
-        let  uart = unsafe {&(*self.inner) };
+        let uart = unsafe { &(*self.inner) };
         while uart.fifo_config_1.read().receive_available_bytes() == 0 {
         while uart.fifo_config_1.read().receive_available_bytes() == 0 {
             core::hint::spin_loop();
             core::hint::spin_loop();
         }
         }
@@ -84,16 +82,17 @@ impl ConsoleDevice for UartBflbWrap {
     }
     }
 
 
     fn write(&self, buf: &[u8]) -> usize {
     fn write(&self, buf: &[u8]) -> usize {
-        let  uart = unsafe {&(*self.inner) };
+        let uart = unsafe { &(*self.inner) };
         let mut count = 0;
         let mut count = 0;
         for current in buf {
         for current in buf {
             if uart.fifo_config_1.read().transmit_available_bytes() == 0 {
             if uart.fifo_config_1.read().transmit_available_bytes() == 0 {
                 break;
                 break;
             }
             }
             count += 1;
             count += 1;
-            unsafe { uart.fifo_write.write(*current); }
+            unsafe {
+                uart.fifo_write.write(*current);
+            }
         }
         }
         count
         count
     }
     }
-    
 }
 }

+ 3 - 1
supervisor/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 [package]
 name = "rustsbi-supervisor"
 name = "rustsbi-supervisor"
-version = "0.1.0"
+version = "0.0.0"
 edition.workspace = true
 edition.workspace = true
 license.workspace = true
 license.workspace = true
 repository.workspace = true
 repository.workspace = true
@@ -8,3 +8,5 @@ repository.workspace = true
 [dependencies]
 [dependencies]
 naked-function = "0.1.5"
 naked-function = "0.1.5"
 sbi-rt = "0.0.3"
 sbi-rt = "0.0.3"
+rcore-console = "0.0.0"
+uart16550 = "0.0.1"

+ 1 - 1
supervisor/build.rs

@@ -12,7 +12,7 @@ const LINKER: &[u8] = b"
 OUTPUT_ARCH(riscv)
 OUTPUT_ARCH(riscv)
 ENTRY(_start)
 ENTRY(_start)
 MEMORY {
 MEMORY {
-    RAM : ORIGIN = 0x0, LENGTH = 64M
+    RAM : ORIGIN = 0x80200000, LENGTH = 64M
 }
 }
 SECTIONS {
 SECTIONS {
     .text : {
     .text : {

+ 3 - 0
supervisor/src/drivers.rs

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

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

@@ -0,0 +1,17 @@
+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> {}

+ 58 - 0
supervisor/src/entry.rs

@@ -0,0 +1,58 @@
+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();
+    }
+}

+ 10 - 59
supervisor/src/main.rs

@@ -1,18 +1,20 @@
+#![feature(strict_provenance)]
 #![no_std]
 #![no_std]
 #![no_main]
 #![no_main]
 
 
 // TODO: RustSBI EFI module
 // TODO: RustSBI EFI module
+use rcore_console::println;
+
+mod drivers;
+mod entry;
+mod platform;
+
 #[no_mangle]
 #[no_mangle]
 extern "C" fn rust_main(_hart_id: usize, _opaque: usize) {
 extern "C" fn rust_main(_hart_id: usize, _opaque: usize) {
-    // TODO
-}
+    platform::platform_init();
 
 
-#[no_mangle]
-extern "C" fn rust_sbi_exit() -> ! {
-    sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::NoReason);
-    loop {
-        core::hint::spin_loop();
-    }
+    println!("Hello world!");
+    // TODO
 }
 }
 
 
 #[panic_handler]
 #[panic_handler]
@@ -22,54 +24,3 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
         core::hint::spin_loop();
         core::hint::spin_loop();
     }
     }
 }
 }
-
-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, 3f",
-        // clear bss segment
-        "   la      t0, sbss
-            la      t1, ebss
-        2:  bgeu    t0, t1, 2f
-            sd      zero, 0(t0)
-            addi    t0, t0, 8
-            j       2b",
-        // prepare data segment
-        "   la      t3, sidata
-            la      t4, sdata
-            la      t5, edata
-        2:  bgeu    t4, t5, 2f
-            ld      t6, 0(t3)
-            sd      t6, 0(t4)
-            addi    t3, t3, 8
-            addi    t4, t4, 8
-            j       2b",
-        "3:",
-        // 3. Prepare stack for each hart
-        "   la      sp, {stack}
-            li      t1, {per_hart_stack_size}
-            addi    t2, a0, 1
-        2:  add     sp, sp, t1
-            addi    t2, t2, -1
-            bnez    t2, 2b",
-        // 4. Start main function
-        "   call    {main}",
-        "   call    {exit}",
-        stack = sym STACK,
-        per_hart_stack_size = const LEN_STACK_PER_HART,
-        main = sym rust_main,
-        exit = sym rust_sbi_exit
-    )
-}

+ 5 - 0
supervisor/src/platform.rs

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

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

@@ -0,0 +1,18 @@
+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);
+}