From cbe7affc5d3949b3c8e3f9a393c993f925b12894 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Tue, 7 Aug 2018 16:11:48 +0800 Subject: [PATCH] Merge riscv for QEMU & FPGA --- kernel/Cargo.toml | 1 + kernel/Makefile | 46 ++++++++++++++++++++------ kernel/src/arch/riscv32/boot/boot.asm | 16 +++++++++ kernel/src/arch/riscv32/boot/entry.asm | 20 ++--------- kernel/src/arch/riscv32/boot/linker.ld | 9 +++-- kernel/src/arch/riscv32/interrupt.rs | 8 ++--- kernel/src/arch/riscv32/io.rs | 21 ++++++++---- kernel/src/arch/riscv32/mod.rs | 3 ++ kernel/src/arch/riscv32/timer.rs | 4 +++ 9 files changed, 88 insertions(+), 40 deletions(-) create mode 100644 kernel/src/arch/riscv32/boot/boot.asm diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 6c756cc..0dc49f7 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["staticlib", "rlib"] [features] use_apic = [] link_user_program = [] +no_bbl = [] [profile.dev] # MUST >= 1 : Enable RVO to avoid stack overflow diff --git a/kernel/Makefile b/kernel/Makefile index 4321f80..1213feb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,19 +1,26 @@ -# Examples: -# make run Run in debug -# make justrun Run in debug without build -# make run int=1 Run with interrupt info by QEMU -# make run mode=release Run in release -# make run LOG=error Run with log level: error -# LOG = off | error | warn | info | debug | trace +# Commands: +# make build Build +# make run Build and run in QEMU +# make justrun Run the last build # make doc Generate docs # make asm Open the deassemble file of the last build +# make elf-h Open 'objdump -h' of the last build # make clean Clean +# +# Options: +# arch = x86_64 | riscv32 +# d = int | in_asm | ... QEMU debug info +# mode = debug | release +# LOG = off | error | warn | info | debug | trace +# board Only available on riscv32, build without bbl, run on board arch ?= riscv32 +mode ?= debug +LOG ?= debug + kernel := build/$(arch)/kernel.bin iso := build/$(arch)/os.iso -target ?= $(arch)-blog_os -mode ?= debug +target := $(arch)-blog_os rust_lib := target/$(target)/$(mode)/ucore boot_src := src/arch/$(arch)/boot @@ -34,7 +41,9 @@ qemu_opts := -machine virt -kernel $(iso) -nographic endif features := use_apic -LOG ?= debug +ifdef board +features := $(features) no_bbl +endif # Link user binaries at ../user ifdef link_user @@ -111,8 +120,23 @@ build/x86_64/os.iso: $(kernel) $(grub_cfg) @rm -r build/isofiles build/riscv32/os.iso: kernel - @cp $(rust_lib) $@ @cp $(rust_lib) $(kernel) +ifdef board + @cp $(rust_lib) $@ +else + @mkdir -p build/riscv32 + @cd ../riscv-pk && \ + mkdir -p build && \ + cd build && \ + ../configure \ + --enable-32bit \ + --enable-logo \ + --disable-fp-emulation \ + --host=riscv64-unknown-elf \ + --with-payload=$(abspath $(rust_lib)) && \ + make && \ + cp bbl ../../kernel/$@ +endif $(kernel): kernel $(assembly_object_files) $(linker_script) @$(ld) -n --gc-sections -T $(linker_script) -o $(kernel) \ diff --git a/kernel/src/arch/riscv32/boot/boot.asm b/kernel/src/arch/riscv32/boot/boot.asm new file mode 100644 index 0000000..b2ca901 --- /dev/null +++ b/kernel/src/arch/riscv32/boot/boot.asm @@ -0,0 +1,16 @@ + .section .text.boot +boot: + csrwi 0x304, 0 # mie + csrwi 0x344, 0 # mip + csrwi 0x340, 0 # mscratch + csrwi 0x180, 0 # satp + li t0, -1 + csrw 0x302, t0 # medeleg + csrw 0x303, t0 # mideleg + csrw 0x306, t0 # mcounteren + csrw 0x106, t0 # scounteren + li t0, 1 << 11 # MPP = S + csrw 0x300, t0 # mstatus + lui t0, 0x80020 + csrw 0x341, t0 # mepc + mret \ No newline at end of file diff --git a/kernel/src/arch/riscv32/boot/entry.asm b/kernel/src/arch/riscv32/boot/entry.asm index 5abca6c..8bb9268 100644 --- a/kernel/src/arch/riscv32/boot/entry.asm +++ b/kernel/src/arch/riscv32/boot/entry.asm @@ -1,23 +1,9 @@ - .section .entry - .global _start + .section .text.entry + .globl _start _start: - csrwi 0x304, 0 # mie - csrwi 0x344, 0 # mip - csrwi 0x340, 0 # mscratch - csrwi 0x180, 0 # satp - li t0, -1 - csrw 0x302, t0 # medeleg - csrw 0x303, t0 # mideleg - csrw 0x306, t0 # mcounteren - csrw 0x106, t0 # scounteren - li t0, 1 << 11 # MPP = S - csrw 0x300, t0 # mstatus - lui t0, %hi(rust_main) - addi t0, t0, %lo(rust_main) - csrw 0x341, t0 # mepc lui sp, %hi(bootstacktop) addi sp, sp, %lo(bootstacktop) - mret + call rust_main .section .bss .align 12 #PGSHIFT diff --git a/kernel/src/arch/riscv32/boot/linker.ld b/kernel/src/arch/riscv32/boot/linker.ld index 8914852..cd5de10 100644 --- a/kernel/src/arch/riscv32/boot/linker.ld +++ b/kernel/src/arch/riscv32/boot/linker.ld @@ -6,17 +6,22 @@ OUTPUT_ARCH(riscv) ENTRY(_start) -BASE_ADDRESS = 0x80000000; +BASE_ADDRESS = 0x80020000; SECTIONS { + . = 0x80000000; + .boot : { + KEEP(*(.text.boot)) + } + /* Load the kernel at this address: "." means the current address */ . = BASE_ADDRESS; start = .; .text : { stext = .; - *(.entry) + *(.text.entry) *(.text .stub .text.* .gnu.linkonce.t.*) . = ALIGN(4K); etext = .; diff --git a/kernel/src/arch/riscv32/interrupt.rs b/kernel/src/arch/riscv32/interrupt.rs index 8525036..58ed672 100644 --- a/kernel/src/arch/riscv32/interrupt.rs +++ b/kernel/src/arch/riscv32/interrupt.rs @@ -39,12 +39,12 @@ pub unsafe fn restore(flags: usize) { #[no_mangle] pub extern fn rust_trap(tf: &mut TrapFrame) { - use super::riscv::register::scause::{Trap, Interrupt, Exception}; + use super::riscv::register::scause::{Trap, Interrupt as I, Exception as E}; trace!("Interrupt: {:?}", tf.scause.cause()); match tf.scause.cause() { - Trap::Interrupt(SupervisorTimer) => timer(), - Trap::Exception(IllegalInstruction) => illegal_inst(tf), - Trap::Exception(UserEnvCall) => syscall(tf), + Trap::Interrupt(I::SupervisorTimer) => timer(), + Trap::Exception(E::IllegalInstruction) => illegal_inst(tf), + Trap::Exception(E::UserEnvCall) => syscall(tf), _ => ::trap::error(tf), } ::trap::before_return(); diff --git a/kernel/src/arch/riscv32/io.rs b/kernel/src/arch/riscv32/io.rs index d529ef1..8936a55 100644 --- a/kernel/src/arch/riscv32/io.rs +++ b/kernel/src/arch/riscv32/io.rs @@ -1,5 +1,6 @@ use core::fmt::{Write, Result, Arguments}; use core::ptr::{read_volatile, write_volatile}; +use super::bbl::sbi; struct SerialPort; @@ -11,7 +12,7 @@ impl Write for SerialPort { putchar(b' '); putchar(8); } else { - putchar(c as u8); + putchar(c); } } Ok(()) @@ -19,19 +20,27 @@ impl Write for SerialPort { } fn putchar(c: u8) { + #[cfg(feature = "no_bbl")] unsafe { while read_volatile(STATUS) & CAN_WRITE == 0 {} write_volatile(DATA, c as u8); } + #[cfg(not(feature = "no_bbl"))] + sbi::console_putchar(c as usize); } pub fn getchar() -> char { - unsafe { + #[cfg(feature = "no_bbl")] + let c = unsafe { while read_volatile(STATUS) & CAN_READ == 0 {} - match read_volatile(DATA) { - 255 => '\0', // null - c => c as char, - } + read_volatile(DATA) + }; + #[cfg(not(feature = "no_bbl"))] + let c = sbi::console_getchar() as u8; + + match c { + 255 => '\0', // null + c => c as char, } } diff --git a/kernel/src/arch/riscv32/mod.rs b/kernel/src/arch/riscv32/mod.rs index b4ae1b8..524201c 100644 --- a/kernel/src/arch/riscv32/mod.rs +++ b/kernel/src/arch/riscv32/mod.rs @@ -1,4 +1,5 @@ extern crate riscv; +extern crate bbl; pub mod io; pub mod interrupt; @@ -14,5 +15,7 @@ pub fn init() { timer::init(); } +#[cfg(feature = "no_bbl")] +global_asm!(include_str!("boot/boot.asm")); global_asm!(include_str!("boot/entry.asm")); global_asm!(include_str!("boot/trap.asm")); \ No newline at end of file diff --git a/kernel/src/arch/riscv32/timer.rs b/kernel/src/arch/riscv32/timer.rs index f5960ae..4fb16eb 100644 --- a/kernel/src/arch/riscv32/timer.rs +++ b/kernel/src/arch/riscv32/timer.rs @@ -1,4 +1,5 @@ use super::riscv::register::*; +use super::bbl::sbi; #[cfg(target_pointer_width = "64")] pub fn get_cycle() -> u64 { @@ -32,8 +33,11 @@ pub fn set_next() { } fn set_timer(t: u64) { + #[cfg(feature = "no_bbl")] unsafe { asm!("csrw 0x321, $0; csrw 0x322, $1" : : "r"(t as u32), "r"((t >> 32) as u32) : : "volatile"); } + #[cfg(not(feature = "no_bbl"))] + sbi::set_timer(t); } \ No newline at end of file