Modify linker script to mipsel arch, add dts in kernel binary

Signed-off-by: Harry Chen <i@harrychen.xyz>
master
Harry Chen 6 years ago
parent d588a922ab
commit 34c3d139a1

@ -42,18 +42,24 @@ build_path := target/$(target)/$(mode)
kernel := $(build_path)/rcore kernel := $(build_path)/rcore
kernel_img := $(build_path)/kernel.img kernel_img := $(build_path)/kernel.img
bootimage := $(build_path)/bootimage.bin bootimage := $(build_path)/bootimage.bin
dtb := src/arch/$(arch)/boot/dts/$(board).dtb
bootloader_dir = ../bootloader bootloader_dir = ../bootloader
bootloader := $(bootloader_dir)/target/$(target)/$(mode)/rcore-bootloader bootloader := $(bootloader_dir)/target/$(target)/$(mode)/rcore-bootloader
bbl_path := $(PWD)/../riscv-pk bbl_path := $(PWD)/../riscv-pk
user_dir := ../user user_dir := ../user
ifeq ($(arch), aarch64)
board := raspi3
ifeq ($(arch), mipsel)
board := malta
### export environments ### ### export environments ###
export ARCH = $(arch) export ARCH = $(arch)
export BOARD = $(board) export BOARD = $(board)
export SMP = $(smp) export SMP = $(smp)
export DTB = $(dtb)
export SFSIMG = $(user_dir)/build/$(arch).qcow2 export SFSIMG = $(user_dir)/build/$(arch).qcow2
ifeq ($(arch), aarch64)
board := raspi3
export SFSIMG = $(user_dir)/build/$(arch).img export SFSIMG = $(user_dir)/build/$(arch).img
endif endif
@ -104,6 +110,13 @@ qemu_opts += \
-kernel $(kernel_img) -kernel $(kernel_img)
endif endif
else ifeq ($(arch), mipsel)
qemu_opts += \
-machine $(board) \
-serial null -serial mon:stdio \
-kernel $(kernel_img)
endif
ifdef d ifdef d
qemu_opts += -d $(d) qemu_opts += -d $(d)
endif endif
@ -171,6 +184,7 @@ cc := $(prefix)gcc
as := $(prefix)as as := $(prefix)as
gdb := $(prefix)gdb gdb := $(prefix)gdb
strip := $(prefix)strip strip := $(prefix)strip
dtc := dtc
export CC = $(cc) 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
@ -220,8 +234,18 @@ header:
sym: sym:
@$(objdump) -t $(kernel) | less @$(objdump) -t $(kernel) | less
### device tree process ###
%.dtb: %.dts
$(dtc) -I dts -O dtb -o $@ $<
### bootloader and kernel image ###
$(bootloader): $(kernel) $(bootloader): $(kernel)
ifeq ($(arch), aarch64) ifeq ($(arch), aarch64)
need_bootloader := true
endif
ifeq ($(need_bootloader), true)
@echo Building $(arch) bootloader @echo Building $(arch) bootloader
@$(strip) $(kernel) -o $(kernel)_stripped @$(strip) $(kernel) -o $(kernel)_stripped
@cd $(bootloader_dir) && make arch=$(arch) mode=$(mode) payload=../kernel/$(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) else ifeq ($(arch), aarch64)
@$(objcopy) $(bootloader) --strip-all -O binary $@ @$(objcopy) $(bootloader) --strip-all -O binary $@
else ifeq ($(arch), mipsel) else ifeq ($(arch), mipsel)
# TODO write mipsel bootloader # qemu-system-mipsel accepts ELF file only, so don't use objcopy
false @cp $(kernel) $(kernel)_orig
@$(strip) $(kernel) -o $(kernel)
endif endif
kernel: kernel: $(dtb)
@echo Building $(arch) kernel @echo Building $(arch) kernel
ifeq ($(arch), x86_64) ifeq ($(arch), x86_64)
@bootimage build $(build_args) @bootimage build $(build_args)

@ -19,6 +19,7 @@ fn main() {
"riscv64" => { "riscv64" => {
} }
"mipsel" => { "mipsel" => {
gen_dtb_asm().unwrap();
} }
"aarch64" => { "aarch64" => {
} }
@ -49,3 +50,32 @@ fn gen_vector_asm() -> Result<()> {
} }
Ok(()) 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(())
}

@ -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 = .);
}

@ -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);
}

@ -3,8 +3,10 @@
.set noreorder .set noreorder
.section .text.entry .section .text.entry
.globl _start .globl _start
_start: _start:
la sp, bootstacktop la sp, bootstacktop
la gp, _gp
b rust_main b rust_main
nop nop

@ -1,21 +1,14 @@
/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */
/* Simple linker script for the ucore kernel. /* Simple linker script for the ucore kernel.
See the GNU ld 'info' manual ("info ld") to learn the syntax. */ See the GNU ld 'info' manual ("info ld") to learn the syntax. */
OUTPUT_ARCH(riscv) OUTPUT_ARCH(riscv)
ENTRY(_start) ENTRY(_start)
BASE_ADDRESS = 0xC0020000; BASE_ADDRESS = 0x80100000;
SECTIONS SECTIONS
{ {
. = 0xC0000000;
.boot : {
KEEP(*(.text.boot))
}
/* Load the kernel at this address: "." means the current address */
. = BASE_ADDRESS; . = BASE_ADDRESS;
start = .; start = .;
@ -30,6 +23,7 @@ SECTIONS
.rodata : { .rodata : {
srodata = .; srodata = .;
*(.rodata .rodata.*) *(.rodata .rodata.*)
*(.dtb)
. = ALIGN(4K); . = ALIGN(4K);
erodata = .; erodata = .;
} }

@ -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 = .);
}

@ -1,40 +1,16 @@
// Physical address available on THINPAD: // Physical address available on THINPAD:
// [0x80000000, 0x80800000] // [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; pub const KERNEL_OFFSET: usize = 0xC000_0000;
#[cfg(target_arch = "riscv64")]
pub const KERNEL_OFFSET: usize = 0xFFFF_FFFF_C000_0000;
#[cfg(target_arch = "riscv32")] #[cfg(target_arch = "riscv32")]
pub const KERNEL_P2_INDEX: usize = (KERNEL_OFFSET >> 12 >> 10) & 0x3ff; 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; 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; 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; 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_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;
pub const USER_STACK_SIZE: usize = 0x10000; pub const USER_STACK_SIZE: usize = 0x10000;
pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE; pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE;

@ -8,41 +8,48 @@ pub mod consts;
pub mod cpu; pub mod cpu;
pub mod syscall; pub mod syscall;
pub mod rand; pub mod rand;
#[cfg(feature = "board_u540")]
#[path = "board/u540/mod.rs"]
mod board;
use log::*; use log::*;
use mips::registers;
use mips::instructions;
extern "C" {
fn _dtb_start();
fn _dtb_end();
}
#[no_mangle] #[no_mangle]
pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! { pub extern fn rust_main() -> ! {
// An initial recursive page table has been set by BBL (shared by all cores)
// 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 { if cpu_id != BOOT_CPU_ID {
while unsafe { !cpu::has_started(hartid) } { } // TODO: run others_main on other CPU
println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb); // while unsafe { !cpu::has_started(hartid) } { }
others_main(); // println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb);
//other_main -> ! // others_main();
loop {}
} }
unsafe { memory::clear_bss(); } 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(); crate::logging::init();
interrupt::init(); interrupt::init();
memory::init(dtb); memory::init(dtb);
timer::init(); timer::init();
// FIXME: init driver on u540 // TODO: initialize device with dtb
#[cfg(not(feature = "board_u540"))] // crate::drivers::init(dtb);
crate::drivers::init(dtb);
#[cfg(feature = "board_u540")]
unsafe { board::init_external_interrupt(); }
crate::process::init(); crate::process::init();
unsafe { cpu::start_others(hart_mask); } // TODO: start other CPU
// unsafe { cpu::start_others(hart_mask); }
crate::kmain(); crate::kmain();
} }
@ -53,35 +60,8 @@ fn others_main() -> ! {
crate::kmain(); crate::kmain();
} }
#[cfg(not(feature = "board_u540"))] const BOOT_CPU_ID: usize = 0;
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
");
global_asm!(include_str!("boot/entry.S")); global_asm!(include_str!("boot/entry.S"));
global_asm!(include_str!("boot/trap.S")); global_asm!(include_str!("boot/trap.S"));
global_asm!(include_str!("boot/dtb.S"));

Loading…
Cancel
Save