blob: a967ad40fb8148d82f75c220282ede2053dfd0cb [file]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use bitrs::{bitfield_repr, layout};
use regio::arm64::{SysReg, spec};
/// [arm/v8]: D13.2.33 CTR_EL0, Cache Type Register.
pub const CTR_EL0: SysReg<spec::CTR_EL0, CacheTypeRegister> = SysReg::new();
/// L1 instruction cache policy.
#[bitfield_repr(u8)]
#[derive(Clone, Copy)]
pub enum L1ICachePolicy {
Vpipt = 0b00,
Aivivt = 0b01,
Vipt = 0b10,
Pipt = 0b11,
}
layout!({
/// The layout of [`CTR_EL0`].
pub struct CacheTypeRegister(u64);
{
let __ @ 63..38;
let tmin_line @ 37..32;
let __ @ 31 = 1;
let __ @ 30;
let dic @ 29;
let idc @ 28;
let cwg @ 27..24;
let erg @ 23..20;
/// log2 of the number of words in the smallest data cache line.
let dmin_line @ 19..16;
let l1_ip @ 15..14: L1ICachePolicy;
let __ @ 13..4;
/// log2 of the number of words in the smallest instruction cache line.
let imin_line @ 3..0;
}
});
impl CacheTypeRegister {
/// Returns the smallest data cache line size in bytes.
pub const fn dcache_line_size(&self) -> usize {
(1 << self.dmin_line()) * size_of::<u32>()
}
/// Returns the smallest instruction cache line size in bytes.
pub const fn icache_line_size(&self) -> usize {
(1 << self.imin_line()) * size_of::<u32>()
}
}
/// [arm/v8]: D13.2.36 DCZID_EL0, Data Cache Zero ID register
pub const DCZID_EL0: SysReg<spec::DCZID_EL0, DataCacheZeroIdRegister> = SysReg::new();
layout!({
/// The layout of [`DCZID_EL0`].
pub struct DataCacheZeroIdRegister(u64);
{
let __ @ 63..5;
let dzp @ 4;
let bz @ 3..0;
}
});
impl DataCacheZeroIdRegister {
/// Returns the block size for DC ZVA in bytes.
pub fn zva_line_size(&self) -> usize {
(1 << self.bz()) * size_of::<u32>()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cache_type_el0() {
let ctr = *CacheTypeRegister::new().set_dmin_line(4).set_imin_line(4);
assert_eq!(ctr.dcache_line_size(), 64);
assert_eq!(ctr.icache_line_size(), 64);
}
#[test]
fn data_cache_zero_id_el0() {
let dczid = *DataCacheZeroIdRegister::new().set_bz(4);
assert_eq!(dczid.zva_line_size(), 64);
}
}