mmu: fix L1Table.update() flush

This commit is contained in:
Astro 2020-06-22 02:02:11 +02:00
parent c0e66a632c
commit 5c69bbdad6
2 changed files with 52 additions and 7 deletions

View File

@ -44,6 +44,15 @@ pub fn dcisw(setway: u32) {
} }
} }
/// Data cache clean by set/way
#[inline(always)]
pub fn dccisw(setway: u32) {
unsafe {
llvm_asm!("mcr p15, 0, $0, c7, c14, 2" :: "r" (setway) :: "volatile");
}
}
/// A made-up "instruction": invalidate all of the L1 D-Cache /// A made-up "instruction": invalidate all of the L1 D-Cache
#[inline(always)] #[inline(always)]
pub fn dciall() { pub fn dciall() {
@ -71,6 +80,33 @@ pub fn dciall() {
} }
} }
/// A made-up "instruction": flush and invalidate all of the L1 D-Cache
#[inline(always)]
pub fn dcciall() {
// the cache associativity could be read from a register, but will
// always be 4 in L1 data cache of a cortex a9
let ways = 4;
let bit_pos_of_way = 30; // 32 - log2(ways)
// the cache sets could be read from a register, but are always
// 256 for the cores in the zync-7000; in general, 128 or 512 are
// also possible.
let sets = 256;
let bit_pos_of_set = 5; // for a line size of 8 words = 2^5 bytes
// select L1 data cache
unsafe {
llvm_asm!("mcr p15, 2, $0, c0, c0, 0" :: "r" (0) :: "volatile");
}
// Invalidate entire D-Cache by iterating every set and every way
for set in 0..sets {
for way in 0..ways {
dccisw((set << bit_pos_of_set) | (way << bit_pos_of_way));
}
}
}
const CACHE_LINE: usize = 0x20; const CACHE_LINE: usize = 0x20;
const CACHE_LINE_MASK: usize = CACHE_LINE - 1; const CACHE_LINE_MASK: usize = CACHE_LINE - 1;

View File

@ -1,5 +1,5 @@
use bit_field::BitField; use bit_field::BitField;
use super::{regs::*, asm, cache}; use super::{regs::*, asm::*, cache::*};
use libregister::RegisterW; use libregister::RegisterW;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -368,10 +368,19 @@ impl L1Table {
let result = f(&mut section); let result = f(&mut section);
entry.set_section(section); entry.set_section(section);
asm::dmb(); // Flush L1Dcache
cache::tlbiall(); dcciall();
asm::dsb(); // // TODO: L2?
asm::isb();
// Invalidate TLB
tlbiall();
// Invalidate all branch predictors
bpiall();
// ensure completion of the BP and TLB invalidation
dsb();
// synchronize context on this processor
isb();
result result
} }
@ -406,9 +415,9 @@ pub fn with_mmu<F: FnMut() -> !>(l1table: &L1Table, mut f: F) -> ! {
// Synchronization barriers // Synchronization barriers
// Allows MMU to start // Allows MMU to start
asm::dsb(); dsb();
// Flushes pre-fetch buffer // Flushes pre-fetch buffer
asm::isb(); isb();
f(); f();
} }