Refactor
This commit is contained in:
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user