feat(adapter-riscv): boot on QEMU virt with UART hello world
This commit is contained in:
3
.cargo/config.toml
Normal file
3
.cargo/config.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[target.riscv64gc-unknown-none-elf]
|
||||||
|
runner = "qemu-system-riscv64 -machine virt -nographic -bios default -kernel"
|
||||||
|
rustflags = ["-C", "link-arg=-Tcrates/adapter-riscv/linker.ld", "-C", "panic=abort"]
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"crates/adapter-riscv",
|
||||||
"crates/apps/snake",
|
"crates/apps/snake",
|
||||||
"crates/domain",
|
"crates/domain",
|
||||||
"crates/elf",
|
"crates/elf",
|
||||||
@@ -84,3 +85,7 @@ snake = { path = "crates/apps/snake" }
|
|||||||
strip = true
|
strip = true
|
||||||
lto = true
|
lto = true
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
|||||||
17
crates/adapter-riscv/Cargo.toml
Normal file
17
crates/adapter-riscv/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "adapter-riscv"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
types = { workspace = true }
|
||||||
|
domain = { workspace = true }
|
||||||
|
platform = { workspace = true }
|
||||||
|
kernel = { workspace = true }
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
opt-level = "s"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
36
crates/adapter-riscv/linker.ld
Normal file
36
crates/adapter-riscv/linker.ld
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
OUTPUT_ARCH(riscv)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x80200000;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text.entry)
|
||||||
|
*(.text .text.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.data : {
|
||||||
|
*(.data .data.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.bss : {
|
||||||
|
_bss_start = .;
|
||||||
|
*(.bss .bss.*)
|
||||||
|
*(.sbss .sbss.*)
|
||||||
|
_bss_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
_stack_bottom = .;
|
||||||
|
. += 0x10000;
|
||||||
|
_stack_top = .;
|
||||||
|
|
||||||
|
_heap_start = .;
|
||||||
|
}
|
||||||
61
crates/adapter-riscv/src/main.rs
Normal file
61
crates/adapter-riscv/src/main.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
mod uart;
|
||||||
|
|
||||||
|
use core::arch::global_asm;
|
||||||
|
use uart::Uart;
|
||||||
|
|
||||||
|
global_asm!(
|
||||||
|
r#"
|
||||||
|
.section .text.entry
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
la sp, _stack_top
|
||||||
|
call kmain
|
||||||
|
spin:
|
||||||
|
wfi
|
||||||
|
j spin
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
static _bss_start: u8;
|
||||||
|
static _bss_end: u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zero_bss() {
|
||||||
|
unsafe {
|
||||||
|
let start = &_bss_start as *const u8 as *mut u8;
|
||||||
|
let end = &_bss_end as *const u8 as *mut u8;
|
||||||
|
let len = end as usize - start as usize;
|
||||||
|
core::ptr::write_bytes(start, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn kmain() -> ! {
|
||||||
|
zero_bss();
|
||||||
|
|
||||||
|
let uart = Uart::new();
|
||||||
|
uart.write_str("k-os: booted on RISC-V\n");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
unsafe { core::arch::asm!("wfi") };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
let uart = Uart::new();
|
||||||
|
uart.write_str("PANIC: ");
|
||||||
|
if let Some(location) = info.location() {
|
||||||
|
uart.write_str(location.file());
|
||||||
|
uart.put_char(b':');
|
||||||
|
uart.write_dec(location.line() as usize);
|
||||||
|
}
|
||||||
|
uart.put_char(b'\n');
|
||||||
|
loop {
|
||||||
|
unsafe { core::arch::asm!("wfi") };
|
||||||
|
}
|
||||||
|
}
|
||||||
60
crates/adapter-riscv/src/uart.rs
Normal file
60
crates/adapter-riscv/src/uart.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
const UART_BASE: usize = 0x10000000;
|
||||||
|
|
||||||
|
pub struct Uart {
|
||||||
|
base: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Uart {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { base: UART_BASE }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_char(&self, byte: u8) {
|
||||||
|
let ptr = self.base as *mut u8;
|
||||||
|
unsafe { core::ptr::write_volatile(ptr, byte) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_str(&self, s: &str) {
|
||||||
|
for byte in s.bytes() {
|
||||||
|
self.put_char(byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_hex(&self, mut value: usize) {
|
||||||
|
self.write_str("0x");
|
||||||
|
if value == 0 {
|
||||||
|
self.put_char(b'0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut buf = [0u8; 16];
|
||||||
|
let mut i = 0;
|
||||||
|
while value > 0 {
|
||||||
|
let digit = (value & 0xF) as u8;
|
||||||
|
buf[i] = if digit < 10 { b'0' + digit } else { b'a' + digit - 10 };
|
||||||
|
value >>= 4;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
while i > 0 {
|
||||||
|
i -= 1;
|
||||||
|
self.put_char(buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_dec(&self, mut value: usize) {
|
||||||
|
if value == 0 {
|
||||||
|
self.put_char(b'0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut buf = [0u8; 20];
|
||||||
|
let mut i = 0;
|
||||||
|
while value > 0 {
|
||||||
|
buf[i] = b'0' + (value % 10) as u8;
|
||||||
|
value /= 10;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
while i > 0 {
|
||||||
|
i -= 1;
|
||||||
|
self.put_char(buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user