diff --git a/kernel/Makefile b/kernel/Makefile index 3a077d7..9ba6c2c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -42,18 +42,24 @@ build_path := target/$(target)/$(mode) kernel := $(build_path)/rcore kernel_img := $(build_path)/kernel.img bootimage := $(build_path)/bootimage.bin +dtb := src/arch/$(arch)/boot/dts/$(board).dtb bootloader_dir = ../bootloader bootloader := $(bootloader_dir)/target/$(target)/$(mode)/rcore-bootloader bbl_path := $(PWD)/../riscv-pk user_dir := ../user +ifeq ($(arch), aarch64) +board := raspi3 + +ifeq ($(arch), mipsel) +board := malta + ### export environments ### export ARCH = $(arch) export BOARD = $(board) export SMP = $(smp) +export DTB = $(dtb) export SFSIMG = $(user_dir)/build/$(arch).qcow2 -ifeq ($(arch), aarch64) -board := raspi3 export SFSIMG = $(user_dir)/build/$(arch).img endif @@ -104,6 +110,13 @@ qemu_opts += \ -kernel $(kernel_img) endif +else ifeq ($(arch), mipsel) +qemu_opts += \ + -machine $(board) \ + -serial null -serial mon:stdio \ + -kernel $(kernel_img) +endif + ifdef d qemu_opts += -d $(d) endif @@ -171,9 +184,10 @@ cc := $(prefix)gcc as := $(prefix)as gdb := $(prefix)gdb strip := $(prefix)strip +dtc := dtc export CC = $(cc) -.PHONY: all clean build asm doc debug kernel sfsimg install run justrun runnet justrunnet runui justrunui runtest justruntest +.PHONY: all clean build asm doc debug kernel sfsimg install run justrun runnet justrunnet runui justrunui runtest justruntest all: kernel @@ -220,8 +234,18 @@ header: sym: @$(objdump) -t $(kernel) | less +### device tree process ### + +%.dtb: %.dts + $(dtc) -I dts -O dtb -o $@ $< + +### bootloader and kernel image ### + $(bootloader): $(kernel) ifeq ($(arch), aarch64) + need_bootloader := true +endif +ifeq ($(need_bootloader), true) @echo Building $(arch) bootloader @$(strip) $(kernel) -o $(kernel)_stripped @cd $(bootloader_dir) && make arch=$(arch) mode=$(mode) payload=../kernel/$(kernel)_stripped @@ -254,11 +278,12 @@ else ifeq ($(arch), riscv64) else ifeq ($(arch), aarch64) @$(objcopy) $(bootloader) --strip-all -O binary $@ else ifeq ($(arch), mipsel) - # TODO write mipsel bootloader - false + # qemu-system-mipsel accepts ELF file only, so don't use objcopy + @cp $(kernel) $(kernel)_orig + @$(strip) $(kernel) -o $(kernel) endif -kernel: +kernel: $(dtb) @echo Building $(arch) kernel ifeq ($(arch), x86_64) @bootimage build $(build_args) diff --git a/kernel/build.rs b/kernel/build.rs index 657f765..9602b9b 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -19,6 +19,7 @@ fn main() { "riscv64" => { } "mipsel" => { + gen_dtb_asm().unwrap(); } "aarch64" => { } @@ -49,3 +50,32 @@ fn gen_vector_asm() -> Result<()> { } Ok(()) } + + +fn gen_dtb_asm() -> Result<()> { + let arch = std::env::var("ARCH").unwrap(); + let dtb = std::env::var("DTB").unwrap(); + let board = std::env::var("BOARD").unwrap(); + + if !Path::new(&dtb).is_file() { + panic!("DTB `{}` not found", dtb) + } + + let mut f = File::create(format!("src/arch/{}/boot/dtb.S", arch)).unwrap(); + + println!("cargo:rerun-if-changed={}", dtb); + println!("cargo:rerun-if-env-changed=DTB"); + + writeln!(f, "# generated by build.rs - do not edit")?; + writeln!(f, ".intel_syntax noprefix")?; + write!(f, r#" + .section .dtb,"a" + .align 12 + .global _dtb_start, _dtb_end +_dtb_start: + .incbin "{}" +_dtb_end: + "#, dtb)?; + + Ok(()) +} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/board/u540/linker.ld b/kernel/src/arch/mipsel/board/u540/linker.ld deleted file mode 100644 index 6bbe85b..0000000 --- a/kernel/src/arch/mipsel/board/u540/linker.ld +++ /dev/null @@ -1,49 +0,0 @@ -/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ - -/* Simple linker script for the ucore kernel. - See the GNU ld 'info' manual ("info ld") to learn the syntax. */ - -OUTPUT_ARCH(riscv) -ENTRY(_start) - -BASE_ADDRESS = 0xffffffffc0020000; - -SECTIONS -{ - /* Load the kernel at this address: "." means the current address */ - . = BASE_ADDRESS; - start = .; - - .text : { - stext = .; - *(.text.entry) - *(.text .text.*) - . = ALIGN(4K); - etext = .; - } - - .rodata : { - srodata = .; - *(.rodata .rodata.*) - . = ALIGN(4K); - erodata = .; - } - - .data : { - sdata = .; - *(.data .data.*) - edata = .; - } - - .stack : { - *(.bss.stack) - } - - .bss : { - sbss = .; - *(.bss .bss.*) - ebss = .; - } - - PROVIDE(end = .); -} diff --git a/kernel/src/arch/mipsel/board/u540/mod.rs b/kernel/src/arch/mipsel/board/u540/mod.rs deleted file mode 100644 index cc53874..0000000 --- a/kernel/src/arch/mipsel/board/u540/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -use super::consts::KERNEL_OFFSET; - -/// Mask all external interrupt except serial. -pub unsafe fn init_external_interrupt() { - const HART1_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2100) as *mut u64; - const SERIAL: u64 = 4; - HART1_S_MODE_INTERRUPT_ENABLES.write(1 << SERIAL); -} - -/// Claim and complete external interrupt by reading and writing to -/// PLIC Interrupt Claim/Complete Register. -pub unsafe fn handle_external_interrupt() { - const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 = (KERNEL_OFFSET + 0x0C20_2004) as *mut u32; - // claim - let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read(); - // complete - HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.write(source); -} \ No newline at end of file diff --git a/kernel/src/arch/mipsel/boot/dts/malta.dts b/kernel/src/arch/mipsel/boot/dts/malta.dts new file mode 100644 index 0000000..e69de29 diff --git a/kernel/src/arch/mipsel/boot/entry.S b/kernel/src/arch/mipsel/boot/entry.S index 80ecb42..5d2ad14 100644 --- a/kernel/src/arch/mipsel/boot/entry.S +++ b/kernel/src/arch/mipsel/boot/entry.S @@ -3,8 +3,10 @@ .set noreorder .section .text.entry .globl _start + _start: la sp, bootstacktop + la gp, _gp b rust_main nop diff --git a/kernel/src/arch/mipsel/boot/linker.ld b/kernel/src/arch/mipsel/boot/linker.ld index bc3ba7f..8d09ddb 100644 --- a/kernel/src/arch/mipsel/boot/linker.ld +++ b/kernel/src/arch/mipsel/boot/linker.ld @@ -1,21 +1,14 @@ -/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ - /* Simple linker script for the ucore kernel. See the GNU ld 'info' manual ("info ld") to learn the syntax. */ OUTPUT_ARCH(riscv) ENTRY(_start) -BASE_ADDRESS = 0xC0020000; +BASE_ADDRESS = 0x80100000; SECTIONS { - . = 0xC0000000; - .boot : { - KEEP(*(.text.boot)) - } - /* Load the kernel at this address: "." means the current address */ . = BASE_ADDRESS; start = .; @@ -30,6 +23,7 @@ SECTIONS .rodata : { srodata = .; *(.rodata .rodata.*) + *(.dtb) . = ALIGN(4K); erodata = .; } diff --git a/kernel/src/arch/mipsel/boot/linker64.ld b/kernel/src/arch/mipsel/boot/linker64.ld deleted file mode 100644 index 6bbe85b..0000000 --- a/kernel/src/arch/mipsel/boot/linker64.ld +++ /dev/null @@ -1,49 +0,0 @@ -/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ - -/* Simple linker script for the ucore kernel. - See the GNU ld 'info' manual ("info ld") to learn the syntax. */ - -OUTPUT_ARCH(riscv) -ENTRY(_start) - -BASE_ADDRESS = 0xffffffffc0020000; - -SECTIONS -{ - /* Load the kernel at this address: "." means the current address */ - . = BASE_ADDRESS; - start = .; - - .text : { - stext = .; - *(.text.entry) - *(.text .text.*) - . = ALIGN(4K); - etext = .; - } - - .rodata : { - srodata = .; - *(.rodata .rodata.*) - . = ALIGN(4K); - erodata = .; - } - - .data : { - sdata = .; - *(.data .data.*) - edata = .; - } - - .stack : { - *(.bss.stack) - } - - .bss : { - sbss = .; - *(.bss .bss.*) - ebss = .; - } - - PROVIDE(end = .); -} diff --git a/kernel/src/arch/mipsel/consts.rs b/kernel/src/arch/mipsel/consts.rs index a3004b0..15d4f8e 100644 --- a/kernel/src/arch/mipsel/consts.rs +++ b/kernel/src/arch/mipsel/consts.rs @@ -1,40 +1,16 @@ // Physical address available on THINPAD: // [0x80000000, 0x80800000] -#[cfg(target_arch = "riscv32")] -pub const RECURSIVE_INDEX: usize = 0x3fd; -#[cfg(target_arch = "riscv64")] -pub const RECURSIVE_INDEX: usize = 0o774; -// Under riscv64, upon booting, paging is enabled by bbl and -// root_table[0777] maps to p3_table, -// and p3_table[0777] maps to gigapage 8000_0000H, -// so 0xFFFF_FFFF_8000_0000 maps to 0x8000_0000 -// root_table[0774] points to root_table itself as page table -// root_table[0775] points to root_table itself as leaf page -// root_table[0776] points to a temp page table as leaf page -#[cfg(target_arch = "riscv32")] pub const KERNEL_OFFSET: usize = 0xC000_0000; -#[cfg(target_arch = "riscv64")] -pub const KERNEL_OFFSET: usize = 0xFFFF_FFFF_C000_0000; #[cfg(target_arch = "riscv32")] pub const KERNEL_P2_INDEX: usize = (KERNEL_OFFSET >> 12 >> 10) & 0x3ff; -#[cfg(target_arch = "riscv64")] -pub const KERNEL_P4_INDEX: usize = (KERNEL_OFFSET >> 12 >> 9 >> 9 >> 9) & 0o777; pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000; -#[cfg(target_arch = "riscv32")] -pub const MEMORY_OFFSET: usize = 0x8000_0000; -#[cfg(target_arch = "riscv64")] pub const MEMORY_OFFSET: usize = 0x8000_0000; - -#[cfg(target_arch = "riscv32")] -pub const MEMORY_END: usize = 0x8100_0000; -#[cfg(target_arch = "riscv64")] pub const MEMORY_END: usize = 0x8100_0000; -// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ??? pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 0x10000; pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE; diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 02bb307..a84a54d 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -8,41 +8,48 @@ pub mod consts; pub mod cpu; pub mod syscall; pub mod rand; -#[cfg(feature = "board_u540")] -#[path = "board/u540/mod.rs"] -mod board; use log::*; +use mips::registers; +use mips::instructions; + +extern "C" { + fn _dtb_start(); + fn _dtb_end(); +} #[no_mangle] -pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! { - // An initial recursive page table has been set by BBL (shared by all cores) +pub extern fn rust_main() -> ! { + + // unsafe { cpu::set_cpu_id(hartid); } - unsafe { cpu::set_cpu_id(hartid); } + let ebase = cp0::ebase::read_u32(); + let cpu_id = ebase & 0x3ff; + let dtb_start = _dtb_start as usize; + let dtb_end = _dtb_end as usize; - if hartid != BOOT_HART_ID { - while unsafe { !cpu::has_started(hartid) } { } - println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); - others_main(); - //other_main -> ! + if cpu_id != BOOT_CPU_ID { + // TODO: run others_main on other CPU + // while unsafe { !cpu::has_started(hartid) } { } + // println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); + // others_main(); + loop {} } unsafe { memory::clear_bss(); } - println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); + println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); crate::logging::init(); interrupt::init(); memory::init(dtb); timer::init(); - // FIXME: init driver on u540 - #[cfg(not(feature = "board_u540"))] - crate::drivers::init(dtb); - #[cfg(feature = "board_u540")] - unsafe { board::init_external_interrupt(); } + // TODO: initialize device with dtb + // crate::drivers::init(dtb); crate::process::init(); - unsafe { cpu::start_others(hart_mask); } + // TODO: start other CPU + // unsafe { cpu::start_others(hart_mask); } crate::kmain(); } @@ -53,35 +60,8 @@ fn others_main() -> ! { crate::kmain(); } -#[cfg(not(feature = "board_u540"))] -const BOOT_HART_ID: usize = 0; -#[cfg(feature = "board_u540")] -const BOOT_HART_ID: usize = 1; - -/// Constant & Macro for `trap.asm` -#[cfg(target_arch = "riscv32")] -global_asm!(r" - .equ XLENB, 4 - .equ XLENb, 32 - .macro LOAD a1, a2 - lw \a1, \a2*XLENB(sp) - .endm - .macro STORE a1, a2 - sw \a1, \a2*XLENB(sp) - .endm -"); -#[cfg(target_arch = "riscv64")] -global_asm!(r" - .equ XLENB, 8 - .equ XLENb, 64 - .macro LOAD a1, a2 - ld \a1, \a2*XLENB(sp) - .endm - .macro STORE a1, a2 - sd \a1, \a2*XLENB(sp) - .endm -"); - +const BOOT_CPU_ID: usize = 0; global_asm!(include_str!("boot/entry.S")); global_asm!(include_str!("boot/trap.S")); +global_asm!(include_str!("boot/dtb.S"));