Compare commits

..

No commits in common. "304152dbeb25186be3f39264859e4cb002ff1c61" and "1ff52acc427168d3b32a573538e2839908847467" have entirely different histories.

6 changed files with 27 additions and 97 deletions

View file

@ -2,7 +2,7 @@
fn main() { fn main() {
// Tell ld to use linker script. // Tell ld to use linker script.
println!("cargo::rustc-link-arg=-Tsrc/script.lds"); println!("cargo::rustc-link-arg=-Tsrc/script.ld");
// Don't do any magic linker stuff. // Don't do any magic linker stuff.
println!("cargo::rustc-link-arg=--omagic"); println!("cargo::rustc-link-arg=--omagic");
} }

View file

@ -1,75 +1,16 @@
// src/entry.rs use crate::abort;
#[no_mangle]
#[link_section = ".text.init"]
unsafe extern "C" fn _entry() {
use core::arch::asm;
// let id = riscv::register::mhartid::read();
// write_tp(&id);
// TODO set up stack for all harts
// TODO set up CSRs for all harts
// if id != 0 { abort(); }
asm!(
/* Global pointer register `gp`
Push current option stack to temporarily disable relaxation, load
_global_pointer symbol (provided by linker), then pop option stack.
Important to keep relaxation off for this instruction, so that
the instruction is emitted as:
1:
auipc gp, %pcrel_hi(_global_pointer)
addi gp, gp, %pcrel_lo(1b)"
instead of:
mv gp, gp
which would do nothing. */
".option push",
".option norelax",
"la gp, _global_pointer",
".option pop",
);
riscv::register::satp::write(0);
unsafe extern "C" fn _enter() {
let id = riscv::register::mhartid::read(); let id = riscv::register::mhartid::read();
if id != 0 { crate::abort(); } write_tp(&id);
// TODO: set up stack for all harts
// TODO: set up CSRs for all harts
if id != 0 { abort(); }
// Clear BSS section // TODO: clear BSS
asm!( // TODO: do hardware inits and wake other harts
"la t0, _bss_start",
"la t1, _bss_end",
"bgeu t0, t1, 2f",
"1:",
"sb zero, 0(t0)",
"addi t0, t0, 1",
"bne t0, t1, 1b",
"2:",
"la sp, _stack_end",
"li t0, (0b11 << 11) | (1 << 13)",
"csrw mstatus, t0",
"csrw mie, x0",
"la t1, {kinit}",
"csrw mepc, t1",
"la ra, 2f",
"mret",
"2:",
kinit = sym kinit,
);
} }
#[no_mangle]
extern "C" fn kinit() {
use crate::uart;
uart::Device::new(0x1000_0000);
}
#[no_mangle]
extern "C" fn kinit_hart() {}
#[inline] #[inline]
unsafe fn write_tp(id: &usize) { unsafe fn write_tp(id: &usize) {
use core::arch::asm; use core::arch::asm;

View file

@ -14,23 +14,23 @@ static ALLOCATOR: LockedHeap = LockedHeap::empty();
/// # Safety /// # Safety
/// Must be called at most once. /// Must be called at most once.
pub unsafe fn init() { pub unsafe fn init() {
let heap_start; let heap_bottom;
let heap_size; let heap_size;
// UNSAFE: This is fine, just loading some constants. // UNSAFE: This is fine, just loading some constants.
unsafe { unsafe {
// using inline assembly is easier to access linker constants // using inline assembly is easier to access linker constants
asm!( asm!(
"la {heap_start}, _heap_start", "la {heap_bottom}, _kernel_heap_bottom",
"la {heap_size}, _heap_size", "la {heap_size}, _kernel_heap_size",
heap_start = out(reg) heap_start, heap_bottom = out(reg) heap_bottom,
heap_size = out(reg) heap_size, heap_size = out(reg) heap_size,
options(nomem) options(nomem)
) )
}; };
println!( println!(
"Initialising kernel heap (bottom: {:#x}, size: {:#x})", "Initialising kernel heap (bottom: {:#x}, size: {:#x})",
heap_start as usize, heap_size heap_bottom as usize, heap_size
); );
// UNSAFE: Fine to call at most once. // UNSAFE: Fine to call at most once.
unsafe { ALLOCATOR.lock().init(heap_start, heap_size) }; unsafe { ALLOCATOR.lock().init(heap_bottom, heap_size) };
} }

View file

@ -40,7 +40,7 @@ unsafe extern "C" fn _enter() -> ! {
"csrw mideleg, t5", // delegate all machine interrupts "csrw mideleg, t5", // delegate all machine interrupts
// set the stack pointer // set the stack pointer
"la sp, _stack_end", "la sp, _init_stack_top",
// Make sure machine mode is set, and enable coarse interrupts // Make sure machine mode is set, and enable coarse interrupts
"li t0, (0b11 << 11) | (1 << 7) | (1 << 3)", "li t0, (0b11 << 11) | (1 << 7) | (1 << 3)",
@ -96,7 +96,7 @@ extern "C" fn start() -> ! {
// } // }
// println!("This should not print because the console is not initialised."); // println!("This should not print because the console is not initialised.");
uart::init_console(0x1000_0000); unsafe { uart::init_console(0x1000_0000) };
println!("Hello, world!"); println!("Hello, world!");
// print current hartid // print current hartid

View file

@ -1,4 +1,4 @@
/* src/script.lds */ # src/script.ld
OUTPUT_ARCH("riscv") OUTPUT_ARCH("riscv")
ENTRY(_enter) ENTRY(_enter)
@ -17,25 +17,18 @@ SECTIONS {
. = ORIGIN(ram); # start at 0x8000_0000 (DRAM) . = ORIGIN(ram); # start at 0x8000_0000 (DRAM)
.text : { # put code first .text : { # put code first
PROVIDE(_text_start = .);
*(.text.init) # start with anything in the .text.init section *(.text.init) # start with anything in the .text.init section
*(.text .text.*) # then put anything else in .text *(.text .text.*) # then put anything else in .text
PROVIDE(_text_end = .);
} >ram AT>ram :text # put this section into the text segment } >ram AT>ram :text # put this section into the text segment
PROVIDE(_global_pointer = .); # this is magic, google "linker relaxation" PROVIDE(_global_pointer = .); # this is magic, google "linker relaxation"
.rodata : { # next, read-only data .rodata : { # next, read-only data
PROVIDE(_rodata_start = .);
*(.rodata .rodata.*) *(.rodata .rodata.*)
PROVIDE(_rodata_end = .);
} >ram AT>ram :text # goes into the text segment as well (since instructions are generally read-only) } >ram AT>ram :text # goes into the text segment as well (since instructions are generally read-only)
.data : { # and the data section .data : { # and the data section
. = ALIGN(4096);
PROVIDE(_data_start = .);
*(.sdata .sdata.*) *(.data .data.*) *(.sdata .sdata.*) *(.data .data.*)
PROVIDE(_data_end = .);
} >ram AT>ram :data # this will go into the data segment } >ram AT>ram :data # this will go into the data segment
.bss :{ # finally, the BSS .bss :{ # finally, the BSS
@ -44,14 +37,10 @@ SECTIONS {
PROVIDE(_bss_end = .); # ... and one at the end PROVIDE(_bss_end = .); # ... and one at the end
} >ram AT>ram :bss # and this goes into the bss segment } >ram AT>ram :bss # and this goes into the bss segment
PROVIDE(_memory_start = ORIGIN(ram)); . = ALIGN(16); # our stack needs to be 16-byte aligned, per the C calling convention
PROVIDE(_init_stack_top = . + 0x1000); # reserve 0x1000 bytes (4 kB) for the initialisation stack
. = ALIGN(16); # stack is 16-byte aligned, per the C calling convention PROVIDE(_kernel_heap_bottom = _init_stack_top); # allocate heap to remaining physical memory
PROVIDE(_stack_start = .); PROVIDE(_kernel_heap_top = ORIGIN(ram) + LENGTH(ram)); # top of heap is end of ram
PROVIDE(_stack_end = _stack_start + 0x80000); # reserve 0x80000 bytes for the stack PROVIDE(_kernel_heap_size = _kernel_heap_top - _kernel_heap_bottom); # capture size of heap
PROVIDE(_memory_end = ORIGIN(ram) + LENGTH(ram));
PROVIDE(_heap_start = _stack_end); # allocate heap to remaining physical memory
PROVIDE(_heap_size = _memory_end - _heap_start); # capture size of heap
} }

View file

@ -14,7 +14,7 @@ impl Device {
/// Create a new UART device. /// Create a new UART device.
/// # Safety /// # Safety
/// `base` must be the base address of a UART device. /// `base` must be the base address of a UART device.
pub fn new(base: usize) -> Self { pub unsafe fn new(base: usize) -> Self {
use core::ptr::write_volatile; use core::ptr::write_volatile;
let addr = base as *mut u8; let addr = base as *mut u8;
// Set data size to 8 bits. // Set data size to 8 bits.
@ -64,9 +64,9 @@ impl core::fmt::Write for Device {
/// Initialise the UART debugging console. /// Initialise the UART debugging console.
/// # Safety /// # Safety
/// `base` must point to the base address of a UART device. /// `base` must point to the base address of a UART device.
pub fn init_console(base: usize) { pub unsafe fn init_console(base: usize) {
let mut console: spinning_top::lock_api::MutexGuard<spinning_top::RawSpinlock, Option<Device>> = CONSOLE.lock(); let mut console = CONSOLE.lock();
*console = Some(Device::new(base)); *console = Some(unsafe { Device::new(base) });
} }
/// Prints a formatted string to the [CONSOLE]. /// Prints a formatted string to the [CONSOLE].