diff --git a/pim-os/Cargo.toml b/pim-os/Cargo.toml index 8c32bee..c3de38a 100644 --- a/pim-os/Cargo.toml +++ b/pim-os/Cargo.toml @@ -6,6 +6,9 @@ version = "0.1.0" edition = "2021" forced-target = "aarch64-unknown-none" +[features] +cacheless = [] + [dependencies] aarch64-cpu = "9.4.0" half = { version = "2.3.1", default-features = false } diff --git a/pim-os/src/main.rs b/pim-os/src/main.rs index 3ab8d8d..017e54f 100644 --- a/pim-os/src/main.rs +++ b/pim-os/src/main.rs @@ -1,8 +1,8 @@ #![no_std] #![no_main] +use aarch64_cpu::asm::barrier; use core::{ - arch::global_asm, fmt::Write, panic::PanicInfo, sync::atomic::{compiler_fence, Ordering}, @@ -15,13 +15,11 @@ use pim::{ }; use pim_isa::BankMode; use uart::Uart0; - +mod boot; mod m5ops; mod pim; mod uart; -global_asm!(include_str!("start.s")); - #[no_mangle] pub extern "C" fn entry() -> ! { let mut pim_state = PimState::new(&TEST_KERNEL); @@ -52,6 +50,7 @@ pub extern "C" fn entry() -> ! { // Invalidate and flush array just in case compute_array.invalidate_flush(); dummy_array.invalidate_flush(); + barrier::dsb(barrier::SY); pim_state.set_bank_mode(BankMode::PimAllBank); compute_array.0[0].execute_instruction_read(); @@ -62,6 +61,7 @@ pub extern "C" fn entry() -> ! { pim_state.set_bank_mode(BankMode::SingleBank); compute_array.invalidate(); + barrier::dsb(barrier::SY); writeln!( &mut uart, diff --git a/pim-os/src/pim/array.rs b/pim-os/src/pim/array.rs index 3784082..f165f15 100644 --- a/pim-os/src/pim/array.rs +++ b/pim-os/src/pim/array.rs @@ -1,3 +1,4 @@ +use aarch64_cpu::asm::barrier; use core::arch::asm; use half::f16; @@ -17,8 +18,13 @@ impl Default for BankArray { impl BankArray { pub fn execute_instruction_read(&self) { - self.invalidate_single_bank(0); + if !cfg!(cacheless) { + self.invalidate_single_bank(0); + barrier::dsb(barrier::SY); + } + self.read_data(); + barrier::dsb(barrier::SY); } pub fn read_data(&self) { @@ -30,9 +36,18 @@ impl BankArray { } pub fn execute_instruction_write(&mut self) { - self.preload_zero(); + if !cfg!(cacheless) { + self.preload_zero(); + barrier::dsb(barrier::SY); + } + self.write_data(); - self.invalidate_flush_single_bank(0); + + if !cfg!(cacheless) { + self.invalidate_flush_single_bank(0); + } + + barrier::dsb(barrier::SY); } pub fn write_data(&mut self) { @@ -53,7 +68,6 @@ impl BankArray { unsafe { // Invalidate first bank asm!("dc ivac, {val}", val = in(reg) &self.0[idx]); - asm!("dsb sy"); } } @@ -67,7 +81,6 @@ impl BankArray { unsafe { // Invalidate and flush first bank asm!("dc civac, {val}", val = in(reg) &self.0[idx]); - asm!("dsb sy"); } } @@ -81,7 +94,6 @@ impl BankArray { unsafe { // Preload first bank asm!("dc zva, {val}", val = in(reg) &self.0[idx]); - asm!("dsb sy"); } } } diff --git a/pim-os/src/pim/state.rs b/pim-os/src/pim/state.rs index 3f1fc15..f32a59d 100644 --- a/pim-os/src/pim/state.rs +++ b/pim-os/src/pim/state.rs @@ -1,10 +1,11 @@ +use crate::boot; + use super::config::PimWriter; use pim_isa::{BankMode, Kernel, PimConfig}; #[derive(Debug)] pub struct PimState { kernel: Kernel, - bank_mode: BankMode, writer: PimWriter, } @@ -12,18 +13,24 @@ impl PimState { pub fn new(kernel: &Kernel) -> Self { Self { kernel: kernel.clone(), - bank_mode: BankMode::SingleBank, writer: PimWriter, } } // TODO return token and return to singlebank when dropped pub fn set_bank_mode(&mut self, bank_mode: BankMode) { - self.bank_mode = bank_mode; + if cfg!(cacheless) { + match bank_mode { + BankMode::SingleBank => unsafe { boot::set_page_table_cache() }, + BankMode::AllBank => (), + BankMode::PimAllBank => unsafe { boot::set_page_table_non_cache() }, + } + } + self.writer.write( serde_json_core::to_string::(&PimConfig { kernel: self.kernel.clone(), - bank_mode: self.bank_mode, + bank_mode, }) .unwrap() .as_str(), diff --git a/pim-os/src/start.s b/pim-os/src/start.s index bd8845f..33fc66d 100644 --- a/pim-os/src/start.s +++ b/pim-os/src/start.s @@ -1,4 +1,4 @@ -.globl _start + .extern LD_STACK_PTR // Put a 64-bit value with little endianness. @@ -36,39 +36,55 @@ BLOCK_1GB (ADDR << 29), 0, 0x74C .set ADDR, ADDR+2 .endr +.align 12 +ttb0_base_non_cache: +.set ADDR, 0x000 +.rept 0x02 +BLOCK_1GB (ADDR << 29), 0, 0x740 +.set ADDR, ADDR+2 +.endr +.rept 0x3E +BLOCK_1GB (ADDR << 29), 0, 0x740 +.set ADDR, ADDR+2 +.endr + +.globl _start _start: ldr x30, =LD_STACK_PTR mov sp, x30 // Initialize translation table control registers - LDR X1, =0x13520 // 64GB space 4KB granularity Inner-shareable. Normal Inner and Outer Cacheable. - MSR TCR_EL3, X1 + ldr x1, =0x13520 // 64GB space 4KB granularity Inner-shareable. Normal Inner and Outer Cacheable. + msr tcr_el3, x1 - LDR X1, =0xFF440400 - MSR MAIR_EL3, X1 // ATTR0 Device-nGnRnE ATTR1 Device. ATTR2 Normal Non-Cacheable. ATTR3 Normal Cacheable. + ldr x1, =0xFF440400 + msr mair_el3, x1 // ATTR0 Device-nGnRnE ATTR1 Device. ATTR2 Normal Non-Cacheable. ATTR3 Normal Cacheable. - ADR X0, ttb0_base - MSR TTBR0_EL3, X0 + bl set_page_table_cache // Enable MMU and caches - // It is implemented in the CPUECTLR register. - MRS X0, S3_1_C15_C2_1 - ORR X0, X0, #(0x1 << 6) // The SMP bit. - MSR S3_1_C15_C2_1, X0 - - // Enable caches and the MMU. - MRS X0, SCTLR_EL3 - ORR X0, X0, #(0x1 << 2) // The C bit (data cache). - ORR X0, X0, #(0x1 << 12) // The I bit (instruction cache). - ORR X0, X0, #0x1 // The M bit (MMU). - MSR SCTLR_EL3, X0 - DSB SY - ISB + mrs x0, sctlr_el3 + orr x0, x0, #(0x1 << 2) // The C bit (data cache). + orr x0, x0, #(0x1 << 12) // The I bit (instruction cache). + orr x0, x0, #0x1 // The M bit (MMU). + msr sctlr_el3, x0 + dsb sy + isb bl entry -.equ PSCI_SYSTEM_OFF, 0x84000008 -.globl system_off -system_off: - ldr x0, =PSCI_SYSTEM_OFF - hvc #0 +.globl set_page_table_cache +set_page_table_cache: + adr x0, ttb0_base + msr ttbr0_el3, x0 + tlbi alle3 + isb + ret + +.globl set_page_table_non_cache +set_page_table_non_cache: + adr x0, ttb0_base_non_cache + msr ttbr0_el3, x0 + tlbi alle3 + isb + ret