This commit is contained in:
2021-08-30 11:02:22 +03:00
parent aa46b28b72
commit d90c32acaf
10 changed files with 183 additions and 45 deletions
+7
View File
@@ -87,6 +87,13 @@ impl<T: AddressSpace + TrivialConvert> From<PhysicalAddress> for VirtualAddress<
}
}
impl From<PhysicalAddress> for usize {
#[inline(always)]
fn from(p: PhysicalAddress) -> Self {
p.0 as usize
}
}
#[cfg(target_pointer_width = "64")]
impl From<PhysicalAddress> for u64 {
#[inline(always)]
+5
View File
@@ -121,6 +121,11 @@ impl<T: AddressSpace> VirtualAddress<T> {
pub unsafe fn as_mut<U>(self) -> &'static mut U {
&mut *(self.0 as *mut U)
}
#[inline(always)]
pub unsafe fn from_ref<U>(r: &U) -> Self {
Self(r as *const U as usize, PhantomData)
}
}
// Step
+9 -7
View File
@@ -1,4 +1,5 @@
use crate::{
arch::intrin,
entry_common,
mem::phys::{self, PageUsage},
proc::Scheduler,
@@ -23,19 +24,20 @@ static CPU_COUNT: AtomicUsize = AtomicUsize::new(1);
#[inline(always)]
pub fn get_cpu() -> &'static mut Cpu {
unsafe {
let mut out: usize;
llvm_asm!("mrs $0, tpidr_el1":"=r"(out));
&mut *(out as *mut _)
}
unsafe { &mut *(intrin::read_tpidr_el1() as *mut _) }
}
fn set_cpu(cpu: *mut Cpu) {
unsafe {
llvm_asm!("msr tpidr_el1, $0"::"r"(cpu));
intrin::write_tpidr_el1(cpu as usize);
}
}
#[inline(always)]
pub fn get_phys_id() -> usize {
intrin::read_mpidr_el1() & 0x3
}
#[no_mangle]
extern "C" fn kernel_ap_main() -> ! {
let cpu = get_cpu();
@@ -82,7 +84,7 @@ pub fn wakeup_single_ap() {
// Wakeup a single AP for test
core::ptr::write_volatile(&mut ap_init_value, cpu_addr_phys.into());
// Ensure all writes are complete before waking up an AP
llvm_asm!("dsb sy");
intrin::dsb_sy();
core::ptr::write_volatile(&mut ap_wakeup_lock, 0);
}
+60
View File
@@ -0,0 +1,60 @@
#[inline(always)]
pub unsafe fn disable_irq() {
llvm_asm!("msr daifset, #0xF");
}
#[inline(always)]
pub unsafe fn enable_irq() {
llvm_asm!("msr daifclr, #0xF");
}
// TPIDR
#[inline(always)]
pub fn read_tpidr_el1() -> usize {
let mut out: usize;
unsafe {
llvm_asm!("mrs $0, tpidr_el1":"=r"(out));
}
out
}
#[inline(always)]
pub unsafe fn write_tpidr_el1(value: usize) {
llvm_asm!("msr tpidr_el1, $0"::"r"(value));
}
// MPIDR
#[inline(always)]
pub fn read_mpidr_el1() -> usize {
let mut out: usize;
unsafe {
llvm_asm!("mrs $0, mpidr_el1":"=r"(out));
}
out
}
// CNTP_CTL
#[inline(always)]
pub unsafe fn write_cntp_ctl_el0(value: usize) {
llvm_asm!("msr cntp_ctl_el0, $0"::"r"(value));
}
// CNTP_CVAL
pub fn read_cntp_cval_el0() -> usize {
let mut out: usize;
unsafe {
llvm_asm!("mrs $0, cntp_cval_el0":"=r"(out));
}
out
}
pub unsafe fn write_cntp_cval_el0(value: usize) {
llvm_asm!("msr cntp_cval_el0, $0"::"r"(value));
}
#[inline(always)]
pub fn dsb_sy() {
unsafe {
llvm_asm!("dsb sy");
}
}
+81
View File
@@ -0,0 +1,81 @@
use super::{intrin, mmio_read, mmio_write};
use crate::KernelSpace;
use address::{PhysicalAddress, VirtualAddress};
const MBOX_BASE: usize = 0x3F00B880;
const MBOX_READ: usize = MBOX_BASE + 0x00;
const MBOX_POLL: usize = MBOX_BASE + 0x10;
const MBOX_STATUS: usize = MBOX_BASE + 0x18;
const MBOX_WRITE: usize = MBOX_BASE + 0x20;
const MBOX_STATUS_FULL: u32 = 1 << 31;
const MBOX_STATUS_EMPTY: u32 = 1 << 30;
const MBOX_RESPONSE: u32 = 1 << 31;
const MBOX_REQUEST: u32 = 0;
const MBOX_CHAR_PROPERTY: u32 = 8;
const MBOX_TAG_GET_SERIAL: u32 = 0x10004;
const MBOX_TAG_GET_REV: u32 = 0x10002;
const MBOX_TAG_GET_MODEL: u32 = 0x10001;
const MBOX_TAG_GET_ARM_MEMORY: u32 = 0x10005;
const MBOX_TAG_LAST: u32 = 0;
#[repr(C, align(16))]
#[derive(Debug)]
struct Message {
data: [u32; 36],
}
static mut MESSAGE: Message = Message { data: [0; 36] };
unsafe fn call(ch: u32) -> Result<(), ()> {
let value = (usize::from(PhysicalAddress::from(
VirtualAddress::<KernelSpace>::from_ref(&MESSAGE),
)) as u32)
| (ch & 0xF);
while mmio_read(MBOX_STATUS) & MBOX_STATUS_FULL != 0 {
llvm_asm!("nop");
}
intrin::dsb_sy();
mmio_write(MBOX_WRITE, value);
loop {
while mmio_read(MBOX_STATUS) & MBOX_STATUS_EMPTY != 0 {
llvm_asm!("nop");
}
if mmio_read(MBOX_READ) == value {
if MESSAGE.data[1] == MBOX_RESPONSE {
return Ok(());
} else {
return Err(());
}
}
}
}
pub fn get_arm_memory() -> Result<usize, ()> {
unsafe {
MESSAGE.data[0] = 8 * 4;
MESSAGE.data[1] = MBOX_REQUEST;
MESSAGE.data[2] = MBOX_TAG_GET_ARM_MEMORY;
MESSAGE.data[3] = 8;
MESSAGE.data[4] = 0;
MESSAGE.data[5] = 0;
MESSAGE.data[6] = 0;
MESSAGE.data[7] = MBOX_TAG_LAST;
call(MBOX_CHAR_PROPERTY)?;
assert!(MESSAGE.data[4] == 0x80000008); // Response of 8 bytes
assert!(MESSAGE.data[5] == 0x00000000); // Base address of RAM is zero
Ok(MESSAGE.data[6] as usize)
}
}
+5 -3
View File
@@ -1,9 +1,11 @@
use address::{PhysicalAddress, VirtualAddress};
use crate::KernelSpace;
use address::{PhysicalAddress, VirtualAddress};
pub mod exception;
pub mod timer;
pub mod cpu;
pub mod exception;
pub mod intrin;
pub mod mbox;
pub mod timer;
pub unsafe fn mmio_write(addr: usize, value: u32) {
core::ptr::write_volatile(
+6 -19
View File
@@ -1,4 +1,4 @@
use super::{cpu::get_cpu, mmio_read, mmio_write};
use super::{cpu, intrin, mmio_read, mmio_write};
pub struct LocalTimer;
@@ -10,15 +10,10 @@ impl LocalTimer {
// as I didn't yet write a way to determine
// "ARM" core number
pub unsafe fn enable() {
let mut phys_core_id: usize;
llvm_asm!(r#"
mrs $0, mpidr_el1;
and $0, $0, #3
"#:"=r"(phys_core_id));
let phys_core_id = cpu::get_phys_id();
debug!(
"cpu{}: physical core id is {}\n",
get_cpu().cpu_id,
cpu::get_cpu().cpu_id,
phys_core_id
);
@@ -26,21 +21,13 @@ impl LocalTimer {
let tmp = mmio_read(CORE_TIMER_INTC + 4 * phys_core_id);
mmio_write(CORE_TIMER_INTC + 4 * phys_core_id, tmp | (1 << 1));
llvm_asm!(
r#"
mov x0, #1
msr cntp_ctl_el0, x0
"#
);
intrin::write_cntp_ctl_el0(1);
}
pub fn update(value: usize) {
let current = intrin::read_cntp_cval_el0();
unsafe {
llvm_asm!(r#"
mrs x0, cntpct_el0
add x0, x0, $0
msr cntp_cval_el0, x0
"#::"r"(value):"x0");
intrin::write_cntp_cval_el0(current + value);
}
}
}
+5 -4
View File
@@ -13,14 +13,14 @@ pub mod proc;
pub use mem::KernelSpace;
use address::PhysicalAddress;
use arch::{cpu, intrin, mbox, timer::LocalTimer};
use mem::phys::{SimpleMemoryIterator, UsableMemory};
use arch::{cpu, timer::LocalTimer};
pub fn entry_common() -> ! {
cpu::wakeup_single_ap();
unsafe {
llvm_asm!("msr daifset, #0xF");
intrin::disable_irq();
LocalTimer::enable();
}
proc::enter();
@@ -28,12 +28,13 @@ pub fn entry_common() -> ! {
#[no_mangle]
extern "C" fn kernel_bsp_main() -> ! {
// TODO determine VC/ARM split
cpu::bsp_init();
let arm_memory = mbox::get_arm_memory().expect("Failed to determine ARM memory");
let iter = SimpleMemoryIterator::new(UsableMemory {
start: PhysicalAddress::from(0usize),
end: PhysicalAddress::from(0x30000000usize),
end: PhysicalAddress::from(arm_memory),
});
unsafe {
mem::phys::initialize(iter);
+2 -5
View File
@@ -32,7 +32,7 @@ impl ReservedRegion {
ReservedRegion {
start,
end,
next: null_mut()
next: null_mut(),
}
}
}
@@ -55,10 +55,7 @@ pub(super) unsafe fn reserve_kernel() {
}
pub(super) unsafe fn reserve_pages(base: PhysicalAddress, count: usize) {
RESERVED_REGION_PAGES.write(ReservedRegion::new(
base,
base + count * PAGE_SIZE
));
RESERVED_REGION_PAGES.write(ReservedRegion::new(base, base + count * PAGE_SIZE));
reserve(RESERVED_REGION_PAGES.as_mut_ptr());
}
+3 -7
View File
@@ -9,8 +9,8 @@ global_asm!(include_str!("context.S"));
#[repr(C)]
pub(super) struct Context {
pub kernel_sp: VirtualAddress<KernelSpace>, // 0x00
cpu_id: u32, // 0x08
pub kernel_sp: VirtualAddress<KernelSpace>, // 0x00
cpu_id: u32, // 0x08
}
struct StackBuilder {
@@ -50,10 +50,7 @@ impl Context {
impl StackBuilder {
pub unsafe fn new(bp: VirtualAddress<KernelSpace>, size: usize) -> Self {
Self {
bp,
sp: bp + size,
}
Self { bp, sp: bp + size }
}
pub fn push<A: Into<usize>>(&mut self, value: A) {
@@ -73,4 +70,3 @@ extern "C" {
fn context_enter_kernel();
}