Timeline
Timeline
2025-10-25
init
This article introduces the basic architecture and core concepts of ARM Cache, discussing in detail the components of cache lines, cache types, mapping methods, and the advantages and disadvantages of physical and virtual caches. It also summarizes the working principles and alias issues of cache architectures such as VIVT, PIPT, and VIPT, and briefly describes the hierarchical structure of multi-level cache systems.
Reference documents:
Classic cache architecture:

Cache internal architecture diagram

- Cache line: The smallest access unit in the cache
- Index field: Used to index and locate which line in the cache
- Tag: Part of the cache address encoding, usually the high-order part of the cache address, used to determine whether the data address cached in the cache line matches the processor’s addressing address
- Offset: Offset within a cache line. The processor can address the contents of a cache line by word or byte.
- Set:Same index fieldCache lines form a set
- Way: In set-associative caches, the cache is divided into several blocks of equal size.
The main purpose of sets is to prevent cache “thrashing”.

Cache types
On the ARM64 architecture, the main types are:
- Instruction Cache (I-Cache)
Dedicated to caching instruction streams to speed up instruction fetching. - Data Cache (D-Cache)
Caches data reads and writes (Load/Store). - Unified Cache
Some levels (e.g., L2, L3) are often unified caches (storing both instructions and data), unlike L1 which strictly separates instructions and data.
Sometimes a cache with both I-Cache and D-Cache is called a Separate Cache, which is a split cache structure: it has both an independent I-Cache and an independent D-Cache. Typical inL1 Cache。
Cache mapping methods
Direct mapping
When each group has only one cache line, it is called a direct-mapping cache.

Example:

0x00, 0x40, and 0x80 all map to the same cache line, causing frequent cache replacements and low performance.
Fully associative
When the cache has only one set, meaning only one address in main memory corresponds to n cache lines, it is called fully associative.

Set associative
- Taking a two-way set associative cache as an example, each way includes 4 cache lines, so every two sets have two cache lines available for replacement.
- Reduce cache thrashing

Example:
- The total cache size is 32KB, and it is 4-way, so each way is 8KB: way_size = 32/4 = 8 (KB).
- The size of a cache line is 32 bytes, so the number of cache lines per way is: num_cache_line = 8KB/32B=256
From this, the structure diagram of the cache can be drawn:
The index value is 12-5+1 = 8 bits, totaling 2^8=256, which can index 256 cache lines
1 | Cache Level (L1 / L2 / L3) |
Physical Cache
After the processor queries the MMU and TLB to obtain the physical address, it uses the physical address to query the cache
Disadvantages: The processor can only access the cache after querying the MMU and TLB, increasing pipeline latency

Virtual Cache
The processor uses virtual addresses to address the cache
Disadvantages: This introduces several problems:
- Aliasing Problem
- Homonyms Problem

Aliasing Problem
Also known as the synonym problem
- Inan operating system, multiple different virtual addresses may map to the same physical address. Due to the use of a virtual cache architecture, these different virtual addresses occupy different cache lines in the cache, but they correspond to the same physical address
- For example: VA1 and VA2 both map to PA, and there are two cache lines in the cache that cache VA1 and VA2
- When a program writes data to VA1, the cache line corresponding to VA1 and the content of PA are updated, but VA2 still holds the old data. Thus, one physical address has two copies of data in the virtual cache, which causes ambiguity

Homonym Problem
- The same virtual address corresponds to different physical addresses, because different processes in an operating system have many identical virtual addresses, and after MMU translation, these identical virtual addresses yield different physical addresses, thus creating the homonym problem
- The most common occurrence of the homonym problem is during process switching. When one process switches to another, if the new process uses virtual addresses to access the cache, it will access the cache left behind by the old process, which is incorrect and useless for the new process. The solution is to invalidate all cache entries left by the old process during process switching, ensuring that the new process gets a clean virtual cache when it executes.
Cache Classification
VIVT(Virtual Index Virtual Tag): Usesvirtual address index field and virtual address tag field, which is equivalent tovirtual cache
- When the CPU accesses the cache, it does not need to perform address translation (virtual address → physical address) first; it directly uses the virtual address to determine the cache line (index) and match the tag.
- There is an alias problem (Synonym/Aliasing): when different virtual addresses map to the same physical address, multiple copies of data may appear in the cache, potentially leading to data inconsistency.
PIPT(Physical Index Physical Tag): usesphysical address index field and physical address tag field, which is equivalent tophysical cache
- The CPU first converts the virtual address to a physical address through the MMU, then uses the physical address for cache indexing and matching.
- There is no alias problem
- Common L2 Cache
VIPT(Virtual Index Physical Tag): usesvirtual address index field and physical address tag field
- CPU uses the low-order part of the virtual address as the cache index。Use physical address as tag, for matching judgment. Becausecache line alignment (usually 64 bytes or 128 bytes), the low bits of virtual address are consistent with the low bits of physical address, so it is safe to index with virtual address.
- Avoids the aliasing problem, because physical address is used as tag
- Subject toPage Sizelimitation: virtual index length must be ≤ page offset bits, otherwise the same virtual index from different pages will conflict. (VIPT uses low bits of virtual address to index cache lines)
- Common L1 Cache
VIPT working process
From a general perspective:
1 | VA = 虚拟页号 (VPN) | 页内偏移 (PO) |
From a VIPT perspectivePODivided into:
1 | PO = Cache Index | Cache Line Offset |
- VIPT cache’sindex bits come only from the page offset part of the virtual address(rather than VPN), this is to prevent the index bits from being affected by virtual address translation (PO is consistent in both virtual and physical addresses).
- The cache line offset is used to locate specific bytes within a cache line.
Assume L1 Cache is 64KB with a cache line size of 64B:
Index bits = log₂(64KB / 64B) = log₂(1024) = 10 bits
So the cache index uses the virtual address’s10 bits
Page offset = 12 bits (4KB page)
The page offset isexactly the same(the paging mechanism only translates VPN, not PO).
If the index bits fall entirely within the page offset (i.e., index bit length ≤ page offset bit length), then the cache index uses address bits that are consistent between virtual and physical addresses, avoiding the cache alias problem caused by different VPNs but the same physical page.
Therefore, the requirement is: index bits ≤ page offset bits

The left and right steps proceed simultaneously
VIPT Alias Problem
When two virtual pages are simultaneously mapped to the same physical page, both virtual pages together fill one way of the cache.

As shown in the figure, after Virtual Page1 is modified, Virtual Page2 still accesses the original data.

This aliasing problem can be avoided bycache layoutmaking the index bits of the VIPT cachecome only from the page offset portion of the virtual address(rather than the VPN)
Cache hierarchy
Two-level cachesystem

Three-level cachesystem

Multi-level cache processing flow
Example:
1 | LDR x0,[x1] |
Load the value at address x1 into x0, assuming x1 is cacheable

- Case1: If the value of x1 is inL1 cache, then the CPU directly gets data fromL1 cachegets the data
- Case2: If the value of x1 is not inL1 cache, but inL2 cachemiddle
- IfL1 cachehas no space, then some data will be evicted fromcache line
- Data fromL2 cache lineloaded intoL1 cache line
- CPU fromL1 cache lineread data from
- Case3: the value of x1 is not in L1 or L2cache, but is in memory
- IfL1 cacheandL2 cachethere is no space in, then some will be evictedcache line
- data is loaded from memory into L2 and L1cache linein
- The CPU reads data fromL1 cache linereads data from
Access latency of multi-level cache

Cache Policies
Cache-related policies areconfigured in the MMU page table。Only Normal memory can be cacheable
Cache strategies include:
- Cacheable/non-cacheable
- Cacheable subdivision
- Read/write-allocate
- Write-Back cacheable, write-through cacheable
- Shareability
Cache allocation policy
- Write allocation(WA): Allocate a new cache line only on a write miss
- Read allocation(RA): Allocate a new cache line only on a read miss
Cache write-back policy:
- Write-back(WB): Write-back operation only updates the cache, not immediately updating memory (cache line is marked as dirty)
- Write through(WT): Write-through operation directly updates both cache and memory
Write Back and Write Through

- WT write-through mode
- When performing a write operation, data is written simultaneously to the current cache, the next-level cache, or main memory
- Write-through mode can reduce the difficulty of implementing cache coherence, but its biggest drawback is consuming more bus bandwidth
- ARM Cortex-A series processors treat WT mode as Non-cacheable
- The Cortex-A72 processor memory system treats all Write-Through pages as Non-cacheable

WB mode write-back mode
- Write only updates the cache and marks the cache line as dirty. The external memory is updated only when the cache line is flushed or explicitly cleared.
- Cache line becomes dirty data

WB
Inner and Outer Shareability
- Normal memoryCan set inner or outer shareability
- How to distinguish between inner and outer varies with different designs
- inner attributeUsuallyCPU IPIntegrated caches
- outer attribute are exported on the bus



- The inner attribute is the internally integrated cache
- The outer attribute is the external cache attached to the external bus

Prefetch instruction
Prefetch instruction in AArch64 (ARMv8 64-bit)
In A64, the one used isPRFM(Prefetch Memory)。
Instruction format
1 | PRFM <prfop>, [Xn, #imm] // Prefetch cache from address Xn + offset |
prfop syntax structure description
1 | <prfop> = <type><target><policy> | #uimm5 |
| Field | Meaning | Example value |
|---|---|---|
<type> | Prefetch purpose | PLDRead,PSTWrite |
<target> | Prefetch target cache level | L1,L2,L3 |
<policy> | Cache usage policy | KEEP(Reuse),STRM(Streaming/one-time use) |
#uimm5 | 5-bit encoding form | #0~#31 |
Example
Prefetch data to L1, keep in cache
1 | PRFM PLDL1KEEP, [X0, #32] |
Meaning: load the address(X0 + 32)corresponding data intoL1 Cache, and mark it aslikely to be reused。
Prefetch for one-time read (streaming access)
1 | PRFM PLDL1STRM, [X1] |
Meaning: load[X1]into cache, butdo not keep long-term(suitable for sequential streaming reads like memcpy).
Equivalent immediate value notation
1 | PRFM #0, [X0] |
#0In the ARM prefetch hint table, the defaultPLDL1KEEP。
| uimm5 value | corresponds to prfop | meaning |
|---|---|---|
#0 | PLDL1KEEP | Read prefetch to L1, reuse (most common) |
#1 | PLDL1STRM | Read prefetch to L1, streaming (use once) |
#4 | PLDL2KEEP | Read prefetch to L2 |
#8 | PLDL3KEEP | Read prefetch to L3 |
#16 | PSTL1KEEP | Write prefetch |
#17 | PSTL1STRM | Write prefetch (streaming) |
Point of Unification (PoU) and Point of Coherency (PoC)
- PoU: indicates within a CPUinstruction cache,data cacheandMMU,TLBetc. see the same copy of memory
- PoU for a PE, meaning to ensurePEwhat is seen byI/D cacheandMMUIt is the same copy. In most cases,PoU is observed from the perspective of a single-core system,
- PoU for inner sharemeaning that withininner shareallPEcan see the same copy
- PoC: all observers in the system, such asDSP, GPU, CPU, DMAetc., can see the same memory copy


The difference between PoU and PoC
- PoCis a system concept, related to system configuration
- For example,Cortex-A53can be configured withL2 cacheand withoutL2 cache, which may affectPoUthe scope


Cache maintenance
- Cache management operations
- Invalidate (Invalidate) the entire cache or a specific cache line. Data in the cache will be discarded.
- Clean (Clean) the entire cache or a specific cache line. The corresponding cache line will be marked as dirty, and datawill be written back to the next level cache or main memory(also known as flush)
- Zero (Zero) operation
- Objects of cache management
- ALL: Entire cache
- VA: A specific virtual address, sometimes called MVA (Modified Virtual Address, which is a cache line containing a specific virtual address)
- Set/Way: Specific cache line or set and way
- Scope of Cache Management
- PoC
- PoU
- Shareability
- inner
Cache Instruction Format



Instructions that accept an address parameter use a 64-bit register holding the virtual address to be maintained. This address has no alignment restrictions.
The AArch64 data cache invalidate by address instruction DC IVAC requires write permission, otherwise a permission error is generated.
Example 1
Traverse all CPU data cache levels (L1/L2/L3…) and perform a clean by set/way for each cache level to ensure all data in the cache is written back to memory:
1 | // AArch64: Data Cache Clean by Set/Way |
CLIDR_EL1
| Bit field | Meaning |
|---|---|
| bits [26:24] | LoC = Level of Coherency (cache coherency level × 2) |
| bits [2:0] | L1 cache type |
| bits [5:3] | L2 cache type |
| … | … |
Overall code flow:
| Step | Action | Explanation |
|---|---|---|
| 1 | Read CLIDR_EL1 | Get the number of cache levels and their types in the system |
| 2 | Parse LoC (Level of Coherence) | Determine how many cache levels need to be traversed |
| 3 | Loop through each level | Process each cache level sequentially from L1 → L2 → L3… |
| 4 | Select the cache level using CSSELR_EL1 | Tell the CPU which cache level to access next |
| 5 | Read CCSIDR_EL1 | Query the detailed configuration of the cache (number of sets, ways, and line size) |
| 6 | Double loop | Iterate over sets and ways, cleaning the cache line by line |
| 7 | DC CSW | ExecuteClean by Set/Way |
| 8 | DSB+ISB | Data synchronization barrier to ensure cleanup completes before proceeding |
Under normal circumstances, cleaning or invalidating the entire cache is something only firmware should do, as part of the kernel power-up or power-down sequence. It can also be very time-consuming; the number of lines in the L2 cache can be extremely large, and it is necessary to loop through them one by one. Therefore, this kind of cleanup is definitely only for special occasions!
Example 2
1 | /* Coherency example for data and instruction accesses within the same Inner |
This code is standardSelf-modifying code / JIT compilation synchronizationSteps:
- Write new instructions to memory (possibly in D-Cache)
- Clean D-Cache, write data back to PoU
- DSB: Ensure write-back completion
- Invalidate the corresponding address in I-Cache
- DSB: Ensure invalidation completion
- ISB: Flush the instruction fetch pipeline, CPU executes new instructions
Cache discovery
- When performing cache instruction management, you need to know the following information:
- How many levels of cache does the system support?
- What is the cache line size?
- For each cache level, what are its sets and ways?
- For zero operations, we need to know how much data can be zeroed?

- Cache Level ID Register (CLIDR, CLIDR_EL1): List how many levels of cache there are, can read the number of cache levels
- Cache Type Register(CTR, CTR_EL0): Cache line size, can read the size of the cache line
- If this needs to be accessed by user code running at execution level EL0, this can be done by setting the system control register (SCTLR/SCTLR_EL1)'sUCTbit.
- Sets and ways: Need to access two registers to obtain
- Tell the Cache Size Selection Register (CSSELR, CSSELR_EL1) which cache to query
- From the Cache Size ID Register (CCSIDR, CCSIDR_EL1) read the relevant information
Cache Discovery Additional Notes
The Data Cache Zero ID Register (DCZID_EL0) contains the block size to be zeroed for zero operations.
DC ZVA (Data Cache Zero by Virtual Address)
- Clear the memory corresponding to a cache line to zero
- DCZID_EL0stores the block size that can be zeroed
- Access permissions: Only privileged levels (EL1 and above) can access DCZID_EL0
Control bit:
- SCTLR_EL1.DZE: Controls whether EL0 is allowed to use DC ZVA
- HCR_EL2.TDZ: Controls whether EL0/EL1 is allowed to use DC ZVA in the non-secure world
SCTLR/SCTLR_The [DZE] bit of EL1 and the Hypervisor Configuration Register (HCR/HCR_EL2) [TDZ] bit control which execution levels and which worlds can access DCZID_EL0。CLIDR_EL1、CSSELR_EL1 and CCSIDR_EL1 can only be accessed by privileged code, i.e., PL1 or higher in AArch32, or EL1 or higher in AArch64.
If the Data Cache Zero by Virtual Address (DC ZVA) instruction is prohibited at an exception level, EL0 is controlled by SCTLR_EL1.DZE bit, and non-secure execution in EL1 and EL0 is controlled by HCR_EL2.TDZ bit; then reading this register returns a value indicating the instruction is not supported.
The CLIDR register only knows how many levels of cache are integrated in the processor itself. It cannot provide information about any caches in the external memory system. For example, if only L1 and L2 are integrated, CLIDR/CLIDR_EL1 identifies two levels of cache, and the processor is unaware of any external L3 cache. When performing cache maintenance or maintaining coherence with integrated caches, non-integrated caches may need to be considered.
Cache Experiment 1: Cache Discovery

Experiment run results:

Code
Core idea:
- First identify each cache level type (CLIDR)
- Select level and type, read configuration registers (CSSELR/CCSIDR)
- Calculate set/way/line size and total size for each cache level
- Print boundary information and L1 I-Cache addressing strategy**
1 |
|
Related Registers
CSSELR_EL1
Cache Size Selection Register

| Bits | Name | Meaning |
|---|---|---|
| 63:5 | RES0 | Reserved bits, read/write have no meaning |
| 4 | TnD | Allocation Tag not Data: Whether to select a separate Allocation Tag cache 0b0 → Data, instruction, or unified cache 0b1 → Separate Allocation Tag cache Note: When InD = 1(instruction cache), this bit is RES0 (invalid) |
| 3:1 | Level | Cache Level to query 0b000 → L1 0b001 → L2 0b010 → L3 0b011 → L4 0b100 → L5 0b101 → L6 0b110 → L7 Other values reserved. Note: If an unimplemented cache level is selected, the return value of reading CSSELR_EL1 is UNKNOWN |
| 0 | InD | Instruction not Data: Cache type: 0b0 → Data or unified cache (Data Cache or Unified Cache ) 0b1 → Instruction cache (Instruction Cache ) If an unimplemented cache level is selected, the return values of Level and InD when reading CSSELR_EL1 are UNKNOWN |



CCSIDR_EL1
Current Cache Size ID Register


| Bits | Name | Meaning |
|---|---|---|
| 63:56 | RES0 | Reserved bits |
| 55:32 | NumSets | Number of sets in cache minus 1 → actual number of sets = NumSets + 1. Note: The number of sets is not necessarily a power of 2. |
| 31:24 | RES0 | Reserved bits |
| 23:3 | Associativity | Describes the cache’snumber of ways, cache associativity (ways) minus 1 → actual associativity = Associativity + 1. Note: Not necessarily a power of 2. |
| 2:0 | LineSize | Log2 of cache line size minus 4. Calculation formula:line_size_bytes = 1 << (LineSize + 4) |

IfARMv8.5-MemTag is implemented and enabled

CCSIDR2_EL1
Current Cache Size ID Register 2
ARMv8.3-CCIDX is implementedis valid

| Bits | Name | Meaning |
|---|---|---|
| 63:24 | RES0 | Reserved bits, read/write has no meaning |
| 23:0 | NumSets | Number of sets in cache minus 1Calculation method:NumSets + 1Get the actual number of setsNote: The number of sets is not necessarily a power of 2 |
- Purpose: Query the specified cache’snumber of sets。
- This register is generally used withCSSELR_EL1in conjunction:
- Write CSSELR_EL1 to select Cache Level and type (data/instruction/Tag)
- Read CCSIDR2_EL1 to get the number of sets for that cache
- NumSets = 0indicates1 set
- NumSets > 0indicatesActual number of sets = NumSets + 1

Notes on reading CCSIDR2_EL1:

CLIDR_EL1
Cache Level ID Register

- Purpose:
- Identifies the type of cache at each level of the processor (Instruction/Data/Unified/Tag).
- Indicates the cache that can be managed usingSet/Way cache maintenance instructionsManaged cache.
- Providescoherency and sharing level information of the cache hierarchy(LoC、LoU、LoUIS)。
- Supports up to 7 levels of cache.
| Bits | Name | Meaning |
|---|---|---|
| 63:47 | RES0 | Reserved bits |
| 46:35 | Ttype(n=1…7) | Tag Cache Type 0b00: No Tag Cache 0b01: Separate Allocation Tag Cache 0b10: Unified Allocation Tag + Data (same line) 0b11: Unified Allocation Tag + Data (separate lines) |
| 34:32 | ICB | Inner Cache Boundary 0b000: Not disclosed by this mechanism. 0b001: L1 is the highest Inner Cacheable level 0b010: L2 is the highest Inner Cacheable level …… 0b110: L6 is the highest Inner Cacheable level 0b111: L7 is the highest Inner Cacheable level |
| 31:29 | LoUU | Level of Unification Uniprocessor |
| 28:26 | LoC | Level of Coherence |
| 25:23 | LoUIS | Level of Unification Inner Shareable |
| 22:0 | Ctype(n=1…7) | Cache Type (per-level cache type) 0b000: No cache 0b001: Instruction cache only 0b010: Data cache only 0b011: Seprate instruction and data cache 0b100: Unified cache |
CTR_EL0
Cache Type Register
Used to provide cache architecture information

| Bit field | Bits | Name | Description |
|---|---|---|---|
| 63-38 | RES0 | Reserved | Reserved, reads as 0 |
| 37-32 | TimeLine | Tag minimum Line | Tag minimum line granularity, indicating the size of the smallest cache line covered by the Allocation Tag (log2 in units of word=4B) and**Memory Tagging Extension (MTE)**related |
| 31 | RES1 | Reserved | Reserved, fixed to 1 |
| 30 | RES0 | Reserved | Reserved, fixed to 0 |
| 29 | DIC | Instruction cache invalidation requirements for data to instruction coherence | Determines whether I-cache invalidation is required to ensure data writes are visible to the I-cache 0 = After data write, I-cache must be invalidated for instructions to fetch the latest data. 1 = I-cache invalidation is not required. |
| 28 | IDC | Data cache clean requirements for instruction to data coherence | Determines whether D-cache cleaning is required to ensure I/D coherence 0 = Data cache needs to be cleaned to PoU to ensure I/D coherence. 1 = D-cache clean is not required. Usually modern cores set it to 1, indicating hardware automatically ensures coherence. |
| 27-24 | CWG | Cache Writeback Granule | Cache Writeback Granule, the maximum granularity of cache write-back (log2, in units of word=4B). Indicates the maximum memory block size (in units of word=4B) that may be affected when a cache line is written back. For example, CWG=0b0100 → 2^(4) = 16 words = 64 bytes. |
| 23-20 | ERG | Exclusives reservation granule | Exclusive Reservation Granule, the maximum reservation granularity of atomic instructions (LDXR/STXR) (log2, in units of word=4B). |
| 19-16 | DminLine | D minline | Data cache minimum line size (log2, in units of word=4B). |
| 15-14 | L1IP | Level 1 Instruction cache policy | L1 instruction cache addressing policy: 0 = VPIPT 1 = Reserved 2 = VIPT 3 = PIPT |
| 13-12 | RES1 | Reserved | Reserved. |
| 3-0 | IMINLINE / DMINLINE | Instruction minline / Data minline | Instruction cache minimum line size (log2, in units of word=4B). |
L1Ip
Indicates the type of L1 instruction cache:

Instruction cache invalidation requirements for data to instruction coherence

Data cache clean requirements from instruction to data coherence

Cache Writeback Granule

Under normal circumstances,CWG = maximum cache line size, because write-back is done in units of entire cache lines.
However, the ARM specification allows for microarchitectural differences:
- CWG ≥ cache line size: Some implementations may merge multiple cache lines into a larger burst write during writeback, such as 128B.
- CWG = cache line size: Common case, for example line=64B → CWG=0b0100 (16 words).
- CWG not provided (
0b0000): Must assumethe maximum writeback granularity is 2KB, or read the Cache Size ID Registers to deduce it yourself.
