feat?: it boots on orange pi 3

This commit is contained in:
Mark Poliakov 2021-10-01 18:37:47 +03:00
parent 683861b401
commit e21d7fdd59
9 changed files with 226 additions and 15 deletions

View File

@ -6,6 +6,7 @@ GDB?=gdb-multiarch
LLVM_BASE=$(shell llvm-config --bindir) LLVM_BASE=$(shell llvm-config --bindir)
OBJCOPY=$(LLVM_BASE)/llvm-objcopy OBJCOPY=$(LLVM_BASE)/llvm-objcopy
MKIMAGE?=mkimage
PROFILE?=debug PROFILE?=debug
O=target/$(ARCH)-$(MACH)/$(PROFILE) O=target/$(ARCH)-$(MACH)/$(PROFILE)
@ -30,6 +31,12 @@ QEMU_OPTS+=-kernel $(O)/kernel.bin \
-m 512 \ -m 512 \
-serial chardev:serial0 -serial chardev:serial0
endif endif
ifeq ($(MACH),rpi3b)
QEMU_OPTS+=-kernel $(O)/kernel.bin \
-M raspi3b \
-serial null \
-serial chardev:serial0
endif
endif endif
.PHONY: address error etc kernel src .PHONY: address error etc kernel src
@ -41,6 +48,10 @@ kernel:
ifeq ($(ARCH),aarch64) ifeq ($(ARCH),aarch64)
$(OBJCOPY) -O binary $(O)/kernel $(O)/kernel.bin $(OBJCOPY) -O binary $(O)/kernel $(O)/kernel.bin
endif endif
ifeq ($(MACH),orangepi3)
$(LLVM_BASE)/llvm-strip $(O)/kernel
$(LLVM_BASE)/llvm-size $(O)/kernel
endif
clean: clean:
cargo clean cargo clean

View File

@ -0,0 +1,17 @@
{
"arch": "aarch64",
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
"disable-redzone": true,
"executables": true,
"features": "+strict-align,+neon,+fp-armv8",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"llvm-target": "aarch64-unknown-none",
"max-atomic-width": 128,
"panic-strategy": "abort",
"relocation-model": "static",
"target-pointer-width": "64",
"pre-link-args": {
"ld.lld": [ "-Tetc/aarch64-orangepi3.ld" ]
}
}

35
etc/aarch64-orangepi3.ld Normal file
View File

@ -0,0 +1,35 @@
ENTRY(_entry);
MEMORY {
ram : ORIGIN = 0x48000000, LENGTH = 992M
}
SECTIONS {
PROVIDE(__kernel_start = .);
.text : {
*(.text._entry)
*(.text*)
} >ram
. = ALIGN(4K);
.rodata : {
*(.rodata*)
} >ram
. = ALIGN(4K);
.data : {
*(.data*)
} >ram
. = ALIGN(4K);
.bss : {
PROVIDE(__bss_start = .);
*(COMMON)
*(.bss*)
. = ALIGN(4K);
PROVIDE(__bss_end = .);
} >ram
PROVIDE(__kernel_end = .);
}

View File

@ -20,4 +20,4 @@ cortex-a = { version = "6.x.x" }
[features] [features]
mach_qemu = [] mach_qemu = []
default = ["mach_qemu"] mach_orangepi3 = []

View File

@ -1,3 +1,5 @@
// vi:ft=a64asm.asm:
.macro ADR_REL reg, sym .macro ADR_REL reg, sym
adrp \reg, \sym adrp \reg, \sym
add \reg, \reg, #:lo12:\sym add \reg, \reg, #:lo12:\sym

View File

@ -1,37 +1,71 @@
//! aarch64 common boot logic //! aarch64 common boot logic
use crate::arch::aarch64::asm::CPACR_EL1;
use cortex_a::registers::VBAR_EL1; use crate::arch::aarch64::asm::{CPACR_EL1};
use tock_registers::interfaces::Writeable; use cortex_a::registers::{VBAR_EL1, SCTLR_EL1};
use tock_registers::interfaces::{Writeable, ReadWriteable};
use cortex_a::asm::barrier::{self, dsb, isb};
#[no_mangle] #[no_mangle]
fn __aa64_bsp_main() { fn __aa64_bsp_main() {
// Disable FP instruction trapping // Disable FP instruction trapping
CPACR_EL1.write(CPACR_EL1::FPEN::TrapNone); CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNone);
extern "C" { extern "C" {
static aa64_el1_vectors: u8; static aa64_el1_vectors: u8;
} }
unsafe { unsafe {
VBAR_EL1.set(&aa64_el1_vectors as *const _ as u64); VBAR_EL1.set(&aa64_el1_vectors as *const _ as u64);
// Setup caching in SCTLR_EL1
dsb(barrier::SY);
isb(barrier::SY);
SCTLR_EL1.modify(SCTLR_EL1::I::SET +
SCTLR_EL1::SA::SET +
SCTLR_EL1::C::SET +
SCTLR_EL1::A::SET);
dsb(barrier::SY);
isb(barrier::SY);
} }
debugln!("Test"); debugln!("Test");
use crate::arch::machine; let mut el: u64;
use crate::dev::{serial::SerialDevice, timer::TimestampSource, Device}; let mut sctlr_el1: u64;
unsafe { unsafe {
machine::console().lock().enable().unwrap(); asm!("mrs {}, currentel", out(reg) el);
machine::local_timer().lock().enable().unwrap(); asm!("mrs {}, sctlr_el1", out(reg) sctlr_el1);
} }
el >>= 2;
el &= 0x3;
let base = machine::local_timer().lock().timestamp().unwrap(); debugln!("Current EL = {}", el);
debugln!("SCTLR_EL1 = {:#x}", sctlr_el1);
//use crate::arch::machine;
//use crate::dev::{serial::SerialDevice, timer::TimestampSource, Device};
//unsafe {
//machine::console().lock().enable().unwrap();
//machine::local_timer().lock().enable().unwrap();
//}
//let base = machine::local_timer().lock().timestamp().unwrap();
loop { loop {
let count = machine::local_timer().lock().timestamp().unwrap(); cortex_a::asm::wfe();
let ch = machine::console().lock().recv(true).unwrap(); //let count = machine::local_timer().lock().timestamp().unwrap();
debugln!("[{:?}] {:#04x} = '{}'!", count - base, ch, ch as char); //let ch = machine::console().lock().recv(true).unwrap();
//debugln!("[{:?}] {:#04x} = '{}'!", count - base, ch, ch as char);
} }
} }
global_asm!(include_str!("entry.S")); cfg_if! {
if #[cfg(feature = "mach_orangepi3")] {
global_asm!(include_str!("uboot.S"));
} else {
global_asm!(include_str!("entry.S"));
}
}

View File

@ -0,0 +1,46 @@
// vi:ft=a64asm.asm:
.set UART0_BASE, 0x05000000
.set SPSR_EL2_EL1h, 0x5
.set HCR_EL2_RW, 1 << 31
.set HCR_EL2_HCD, 1 << 29
.macro ADR_REL reg, sym
adrp \reg, \sym
add \reg, \reg, #:lo12:\sym
.endm
.section .text._entry
.global _entry
_entry:
// Test for EL2
mrs x0, CurrentEL
lsr x0, x0, #2
cmp x0, #2
bne 1f
// Exit EL2
// TODO cnthtctl_el2 setup
ADR_REL x0, 1f
msr elr_el2, x0
mov x0, #SPSR_EL2_EL1h
msr spsr_el2, x0
mov x0, #(HCR_EL2_RW | HCR_EL2_HCD)
msr hcr_el2, x0
eret
1:
dsb sy
isb
ADR_REL x0, bsp_stack_top
mov sp, x0
b __aa64_bsp_main
.section .bss
.p2align 12
bsp_stack_bottom:
.skip 32768
bsp_stack_top:

View File

@ -0,0 +1,62 @@
//! QEMU virt machine
use crate::arch::aarch64::timer::GenericTimer;
use crate::dev::{Device, serial::SerialDevice};
use crate::dev::timer::TimestampSource;
use crate::sync::Spin;
use error::Errno;
fn delay(mut p: usize) {
while p != 0 {
cortex_a::asm::nop();
p -= 1;
}
}
struct Uart {
base: usize
}
impl Device for Uart {
fn name() -> &'static str {
"Allwinner H6 UART"
}
unsafe fn enable(&mut self) -> Result<(), Errno> {
todo!()
}
}
impl SerialDevice for Uart {
fn send(&mut self, byte: u8) -> Result<(), Errno> {
unsafe {
if byte == b'\n' {
core::ptr::write_volatile(self.base as *mut u32, 13u32);
delay(10000);
}
core::ptr::write_volatile(self.base as *mut u32, byte as u32);
delay(10000);
}
Ok(())
}
fn recv(&mut self, blocking: bool) -> Result<u8, Errno> {
todo!()
}
}
const UART0_BASE: usize = 0x05000000;
/// Returns primary console for this machine
#[inline]
pub fn console() -> &'static Spin<impl SerialDevice> {
&UART0
}
///// Returns the timer used as CPU-local periodic IRQ source
//#[inline]
//pub fn local_timer() -> &'static Spin<impl TimestampSource> {
// &LOCAL_TIMER
//}
static UART0: Spin<Uart> = Spin::new(Uart { base: UART0_BASE });

View File

@ -10,5 +10,9 @@ cfg_if! {
pub mod mach_qemu; pub mod mach_qemu;
pub use mach_qemu as machine; pub use mach_qemu as machine;
} else if #[cfg(feature = "mach_orangepi3")] {
pub mod mach_orangepi3;
pub use mach_orangepi3 as machine;
} }
} }