Add support for cacheless PIM
This commit is contained in:
@@ -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 }
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user