blob: efc78b2ccaa70b500a353d76652876c11a548466 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/arch/cache.h>
namespace arch {
CacheConsistencyContext::~CacheConsistencyContext() {
// If CTR_EL0.DIC is unset, invalidating the instruction cache to the PoU
// is required for data-to-instruction cache coherence. Furthermore, if there
// is possible aliasing then we cannot rely on invalidation by virtual
// address and must resort to invalidating the entirety of the instruction
// cache.
if (!CacheTypeEl0::Read().dic() && possible_aliasing_) {
__asm__ volatile("ic ialluis");
__isb(ARM_MB_SY);
}
}
void CacheConsistencyContext::SyncRange(uintptr_t vaddr, size_t size) {
const auto ctr = CacheTypeEl0::Read();
// If CTR_EL0.IDC is unset, cleaning the data cache to the PoU is required
// for instruction-to-data cache coherence.
if (!ctr.idc()) {
const size_t dcache_line_size = ctr.dcache_line_size();
// Ensure alignment with the data cache line size (a power of two).
const uintptr_t aligned_addr = vaddr & ~(dcache_line_size - 1);
const uintptr_t end_addr = aligned_addr + (vaddr - aligned_addr) + size;
for (uintptr_t line = aligned_addr; line < end_addr; line += dcache_line_size) {
__asm__ volatile("dc cvau, %0" ::"r"(line) : "memory");
}
__dsb(ARM_MB_ISH);
}
// A continuation of the comment on a similar block in the destructor. If
// CTR_EL0.DIC is unset, then we must invalidate - and if there is not
// aliasing, then we can rely on invalidation by virtual address.
if (!ctr.dic() && !possible_aliasing_) {
const size_t icache_line_size = ctr.icache_line_size();
// Ensure alignment with the data instruction line size (a power of two).
const uintptr_t aligned_addr = vaddr & ~(icache_line_size - 1);
const uintptr_t end_addr = aligned_addr + (vaddr - aligned_addr) + size;
for (uintptr_t line = aligned_addr; line < end_addr; line += icache_line_size) {
__asm__ volatile("ic ivau, %0" ::"r"(line) : "memory");
}
__isb(ARM_MB_SY);
}
}
} // namespace arch