Add support for cacheless PIM

This commit is contained in:
2023-12-11 18:52:02 +01:00
parent 71c766736a
commit beaa224252
5 changed files with 77 additions and 39 deletions

View File

@@ -6,6 +6,9 @@ version = "0.1.0"
edition = "2021" edition = "2021"
forced-target = "aarch64-unknown-none" forced-target = "aarch64-unknown-none"
[features]
cacheless = []
[dependencies] [dependencies]
aarch64-cpu = "9.4.0" aarch64-cpu = "9.4.0"
half = { version = "2.3.1", default-features = false } half = { version = "2.3.1", default-features = false }

View File

@@ -1,8 +1,8 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use aarch64_cpu::asm::barrier;
use core::{ use core::{
arch::global_asm,
fmt::Write, fmt::Write,
panic::PanicInfo, panic::PanicInfo,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{compiler_fence, Ordering},
@@ -15,13 +15,11 @@ use pim::{
}; };
use pim_isa::BankMode; use pim_isa::BankMode;
use uart::Uart0; use uart::Uart0;
mod boot;
mod m5ops; mod m5ops;
mod pim; mod pim;
mod uart; mod uart;
global_asm!(include_str!("start.s"));
#[no_mangle] #[no_mangle]
pub extern "C" fn entry() -> ! { pub extern "C" fn entry() -> ! {
let mut pim_state = PimState::new(&TEST_KERNEL); let mut pim_state = PimState::new(&TEST_KERNEL);
@@ -52,6 +50,7 @@ pub extern "C" fn entry() -> ! {
// Invalidate and flush array just in case // Invalidate and flush array just in case
compute_array.invalidate_flush(); compute_array.invalidate_flush();
dummy_array.invalidate_flush(); dummy_array.invalidate_flush();
barrier::dsb(barrier::SY);
pim_state.set_bank_mode(BankMode::PimAllBank); pim_state.set_bank_mode(BankMode::PimAllBank);
compute_array.0[0].execute_instruction_read(); compute_array.0[0].execute_instruction_read();
@@ -62,6 +61,7 @@ pub extern "C" fn entry() -> ! {
pim_state.set_bank_mode(BankMode::SingleBank); pim_state.set_bank_mode(BankMode::SingleBank);
compute_array.invalidate(); compute_array.invalidate();
barrier::dsb(barrier::SY);
writeln!( writeln!(
&mut uart, &mut uart,

View File

@@ -1,3 +1,4 @@
use aarch64_cpu::asm::barrier;
use core::arch::asm; use core::arch::asm;
use half::f16; use half::f16;
@@ -17,8 +18,13 @@ impl Default for BankArray {
impl BankArray { impl BankArray {
pub fn execute_instruction_read(&self) { 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(); self.read_data();
barrier::dsb(barrier::SY);
} }
pub fn read_data(&self) { pub fn read_data(&self) {
@@ -30,9 +36,18 @@ impl BankArray {
} }
pub fn execute_instruction_write(&mut self) { pub fn execute_instruction_write(&mut self) {
self.preload_zero(); if !cfg!(cacheless) {
self.preload_zero();
barrier::dsb(barrier::SY);
}
self.write_data(); 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) { pub fn write_data(&mut self) {
@@ -53,7 +68,6 @@ impl BankArray {
unsafe { unsafe {
// Invalidate first bank // Invalidate first bank
asm!("dc ivac, {val}", val = in(reg) &self.0[idx]); asm!("dc ivac, {val}", val = in(reg) &self.0[idx]);
asm!("dsb sy");
} }
} }
@@ -67,7 +81,6 @@ impl BankArray {
unsafe { unsafe {
// Invalidate and flush first bank // Invalidate and flush first bank
asm!("dc civac, {val}", val = in(reg) &self.0[idx]); asm!("dc civac, {val}", val = in(reg) &self.0[idx]);
asm!("dsb sy");
} }
} }
@@ -81,7 +94,6 @@ impl BankArray {
unsafe { unsafe {
// Preload first bank // Preload first bank
asm!("dc zva, {val}", val = in(reg) &self.0[idx]); asm!("dc zva, {val}", val = in(reg) &self.0[idx]);
asm!("dsb sy");
} }
} }
} }

View File

@@ -1,10 +1,11 @@
use crate::boot;
use super::config::PimWriter; use super::config::PimWriter;
use pim_isa::{BankMode, Kernel, PimConfig}; use pim_isa::{BankMode, Kernel, PimConfig};
#[derive(Debug)] #[derive(Debug)]
pub struct PimState { pub struct PimState {
kernel: Kernel, kernel: Kernel,
bank_mode: BankMode,
writer: PimWriter, writer: PimWriter,
} }
@@ -12,18 +13,24 @@ impl PimState {
pub fn new(kernel: &Kernel) -> Self { pub fn new(kernel: &Kernel) -> Self {
Self { Self {
kernel: kernel.clone(), kernel: kernel.clone(),
bank_mode: BankMode::SingleBank,
writer: PimWriter, writer: PimWriter,
} }
} }
// TODO return token and return to singlebank when dropped // TODO return token and return to singlebank when dropped
pub fn set_bank_mode(&mut self, bank_mode: BankMode) { 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( self.writer.write(
serde_json_core::to_string::<PimConfig, 1024>(&PimConfig { serde_json_core::to_string::<PimConfig, 1024>(&PimConfig {
kernel: self.kernel.clone(), kernel: self.kernel.clone(),
bank_mode: self.bank_mode, bank_mode,
}) })
.unwrap() .unwrap()
.as_str(), .as_str(),

View File

@@ -1,4 +1,4 @@
.globl _start
.extern LD_STACK_PTR .extern LD_STACK_PTR
// Put a 64-bit value with little endianness. // Put a 64-bit value with little endianness.
@@ -36,39 +36,55 @@ BLOCK_1GB (ADDR << 29), 0, 0x74C
.set ADDR, ADDR+2 .set ADDR, ADDR+2
.endr .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: _start:
ldr x30, =LD_STACK_PTR ldr x30, =LD_STACK_PTR
mov sp, x30 mov sp, x30
// Initialize translation table control registers // Initialize translation table control registers
LDR X1, =0x13520 // 64GB space 4KB granularity Inner-shareable. Normal Inner and Outer Cacheable. ldr x1, =0x13520 // 64GB space 4KB granularity Inner-shareable. Normal Inner and Outer Cacheable.
MSR TCR_EL3, X1 msr tcr_el3, x1
LDR X1, =0xFF440400 ldr x1, =0xFF440400
MSR MAIR_EL3, X1 // ATTR0 Device-nGnRnE ATTR1 Device. ATTR2 Normal Non-Cacheable. ATTR3 Normal Cacheable. msr mair_el3, x1 // ATTR0 Device-nGnRnE ATTR1 Device. ATTR2 Normal Non-Cacheable. ATTR3 Normal Cacheable.
ADR X0, ttb0_base bl set_page_table_cache
MSR TTBR0_EL3, X0
// Enable MMU and caches // Enable MMU and caches
// It is implemented in the CPUECTLR register. mrs x0, sctlr_el3
MRS X0, S3_1_C15_C2_1 orr x0, x0, #(0x1 << 2) // The C bit (data cache).
ORR X0, X0, #(0x1 << 6) // The SMP bit. orr x0, x0, #(0x1 << 12) // The I bit (instruction cache).
MSR S3_1_C15_C2_1, X0 orr x0, x0, #0x1 // The M bit (MMU).
msr sctlr_el3, x0
// Enable caches and the MMU. dsb sy
MRS X0, SCTLR_EL3 isb
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 bl entry
.equ PSCI_SYSTEM_OFF, 0x84000008 .globl set_page_table_cache
.globl system_off set_page_table_cache:
system_off: adr x0, ttb0_base
ldr x0, =PSCI_SYSTEM_OFF msr ttbr0_el3, x0
hvc #0 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