Commit 4441760c authored by Jonathan Schwender's avatar Jonathan Schwender Committed by Stefan Lankes
Browse files

aarch64: Add WIP qemu raspi3 machine support

- Only initialize CPU 0 and spin on other CPUs (based on https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/)
- Adjust physical start address of RAM to correct value for raspi3 (again based on the raspberry tutorial)
- Add feature to map write_char() to use a special address for usage with qemu. The aarch64 solution doesn't seem to work on qemu. Didn't look to closely though.
 The feature is enabled by default for make arch=aarch64 for now. A toggle is future work
parent 2c26ea66
...@@ -6,6 +6,9 @@ license = "MIT/Apache-2.0" ...@@ -6,6 +6,9 @@ license = "MIT/Apache-2.0"
readme = "README.md" readme = "README.md"
edition = "2018" edition = "2018"
[features]
aarch64-qemu-stdout = [] # Output to special qemu address 0x3F20_1000 instead of trying to use uart
[dependencies] [dependencies]
bitflags = "1.2.*" bitflags = "1.2.*"
......
...@@ -10,6 +10,11 @@ opt := --release ...@@ -10,6 +10,11 @@ opt := --release
rdir := release rdir := release
endif endif
# Todo - make this feature toggleable
ifeq ($(arch), aarch64)
opt += --features "aarch64-qemu-stdout"
endif
CONVERT := CONVERT :=
RN := RN :=
ifdef COMSPEC ifdef COMSPEC
......
...@@ -12,6 +12,7 @@ extern "C" { ...@@ -12,6 +12,7 @@ extern "C" {
} }
const BOOT_STACK_SIZE: usize = 4096; const BOOT_STACK_SIZE: usize = 4096;
const BOOT_CORE_ID: u64 = 0; // ID of CPU for booting on SMP systems - this might be board specific in the future
#[link_section = ".data"] #[link_section = ".data"]
static STACK: [u8; BOOT_STACK_SIZE] = [0; BOOT_STACK_SIZE]; static STACK: [u8; BOOT_STACK_SIZE] = [0; BOOT_STACK_SIZE];
...@@ -51,16 +52,16 @@ fn tcr_size(x: u64) -> u64 { ...@@ -51,16 +52,16 @@ fn tcr_size(x: u64) -> u64 {
(((64) - (x)) << 16) | (((64) - (x)) << 0) (((64) - (x)) << 16) | (((64) - (x)) << 0)
} }
global_asm!(include_str!("entry.s"));
#[inline(never)] #[inline(never)]
#[no_mangle] #[no_mangle]
#[naked] pub unsafe fn _start_rust() -> ! {
pub unsafe extern "C" fn _start() -> ! {
// Pointer to stack base // Pointer to stack base
llvm_asm!("mov sp, $0" llvm_asm!("mov sp, $0"
:: "r"(&STACK[BOOT_STACK_SIZE - 0x10] as *const u8 as usize) :: "r"(&STACK[BOOT_STACK_SIZE - 0x10] as *const u8 as usize)
:: "volatile"); :: "volatile");
pre_init()
pre_init();
} }
unsafe fn pre_init() -> ! { unsafe fn pre_init() -> ! {
...@@ -172,3 +173,9 @@ unsafe fn pre_init() -> ! { ...@@ -172,3 +173,9 @@ unsafe fn pre_init() -> ! {
// we should never reach this point // we should never reach this point
loop {} loop {}
} }
pub unsafe fn wait_forever() -> ! {
loop {
asm!("wfe")
}
}
\ No newline at end of file
// Adapted from https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/master/02_runtime_init/src/_arch/aarch64/cpu/boot.s
.equ _core_id_mask, 0b11 //Assume 4 core raspi3
.section .text._start
_start:
// Only proceed on the boot core. Park it otherwise.
mrs x1, MPIDR_EL1
and x1, x1, _core_id_mask
mov x2, 0 // Assume CPU 0 is responsible for booting
cmp x1, x2
b.ne 1f
// If execution reaches here, it is the boot core. Now, prepare the jump to Rust code.
// Jump to Rust code.
b _start_rust
// Infinitely wait for events (aka "park the core").
1: wfe
b 1b
.size _start, . - _start
.type _start, function
.global _start
\ No newline at end of file
...@@ -3,7 +3,7 @@ OUTPUT_ARCH("aarch64") ...@@ -3,7 +3,7 @@ OUTPUT_ARCH("aarch64")
ENTRY(_start) ENTRY(_start)
/* start address of the RAM, below belongs to the flash */ /* start address of the RAM, below belongs to the flash */
phys = 0x40080000; phys = 0x00080000;
SECTIONS SECTIONS
{ {
......
...@@ -14,6 +14,14 @@ pub struct Console; ...@@ -14,6 +14,14 @@ pub struct Console;
/// a message to HermitCore's console. /// a message to HermitCore's console.
impl fmt::Write for Console { impl fmt::Write for Console {
/// Print a single character. /// Print a single character.
#[cfg(feature = "aarch64-qemu-stdout")]
fn write_char(&mut self, c: char) -> fmt::Result {
unsafe {
core::ptr::write_volatile(0x3F20_1000 as *mut u8, c as u8); //qemu raspi3
}
Ok(())
}
#[cfg(not(feature = "aarch64-qemu-stdout"))]
fn write_char(&mut self, c: char) -> fmt::Result { fn write_char(&mut self, c: char) -> fmt::Result {
arch::output_message_byte(c as u8); arch::output_message_byte(c as u8);
Ok(()) Ok(())
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#![feature(const_raw_ptr_to_usize_cast)] #![feature(const_raw_ptr_to_usize_cast)]
#![feature(lang_items)] #![feature(lang_items)]
#![feature(llvm_asm)] #![feature(llvm_asm)]
#![feature(global_asm)]
#![feature(asm)]
#![feature(panic_info_message)] #![feature(panic_info_message)]
#![feature(specialization)] #![feature(specialization)]
#![feature(naked_functions)] #![feature(naked_functions)]
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment