Timeline
Timeline
2025-10-25
init
This article introduces the basic concepts and working principles of caches in the ARM architecture. It first explains the key terms in classic cache architecture, including cache line, index, tag, offset, set, and way, and describes the role of set-associative structures in preventing cache thrashing. It then introduces the main types of caches on the ARM64 platform, such as instruction cache, data cache, and unified cache, as well as the three mapping methods: direct-mapped, fully associative, and set-associative. Through specific examples, it demonstrates the capacity and index calculation methods of set-associative caches. The article also compares the advantages and disadvantages of physical caches and virtual caches, focusing on the alias problem and homonym problem in virtual caches and their causes. On this basis, it further introduces three cache addressing methods: VIVT, PIPT, and VIPT, and details the working mechanism of VIPT, which uses the page offset of the virtual address as the index and the physical address as the tag, as well as the conditions for avoiding the alias problem and the reason it is limited by page size. Finally, the article outlines the hierarchical structure and access flow of multi-level caches, helping readers understand the data lookup process from L1 to L3 caches.
Reference documents:
Classic cache architecture:

Cache internal architecture diagram

- Cache line: The smallest unit of access 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 bits of the cache address, used to determine whether the data address cached in the cache line matches the processor’s addressing address.
- Offset: The offset within a cache line. The processor can address the contents of a cache line by word or byte.
- Set:Same index fieldform a set
- Way: In a set-associative cache, the cache is divided into several blocks of the same size.
The main purpose of sets is to prevent cache “thrashing”.

Cache types
On the ARM64 architecture, there are mainly:
- 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 (such as L2, L3) are often unified caches (storing both instructions and data), unlike L1 which is strictly split into instruction/data.
Sometimes a cache with both I-Cache and D-Cache is called a Separate Cache. It is a split cache structure: it has both an independent I-Cache and an independent D-Cache. Typical of L1 Cache。
Cache mapping methods
Direct mapping
When each set has only one cache line, it is called a direct-mapped 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, i.e., any address in main memory can map to any cache line, it is called fully associative.

Set-associative
- Taking a two-way set-associative cache as an example, each set contains 2 cache lines (ways), and the two cache lines in the same set can replace each other.
- 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 cache line size is 32 bytes, so the number of cache lines per way is: num_cache_line = 8KB/32B=256
From this, the cache structure diagram can be drawn:
The index value is 12-5+1 = 8 bits, totaling 2^8 = 256, which can index 256 cache lines.
12345678910 | Cache Level (L1 / L2 / L3)┌──────────────┐│ Set 0 │── Way 0 → Cache Line│ │── Way 1 → Cache Line│ │── Way 2 → Cache Line│ │── Way 3 → Cache Line├──────────────┤│ Set 1 │── Way 0 → Cache Line│ ... │└──────────────┘ |
Physical cache
After the processor queries the MMU and TLB to obtain the physical address, it uses the physical address to access the cache.
Disadvantages: The processor can only access the cache after querying the MMU and TLB, which increases pipeline latency.

virtual cache
The processor uses virtual addresses to address the cache.
Disadvantages: This will introduce quite a few problems:
- Aliasing problem
- Homonyms problem

Aliasing problem
Also known as the aliasing problem
- BeforeIn an operating system, multiple different virtual addresses may map to the same physical address. Since a virtual cache architecture is used, these different virtual addresses will 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 in the cache there are two cache lines caching VA1 and VA2.
- When the program writes data to VA1, the cache line corresponding to VA1 and the content of PA are changed, but VA2 still holds the old data. Thus, one physical address has two copies of data in the virtual cache, which creates ambiguity.

Homonyms problem
- The same virtual address corresponds to different physical addresses, because different processes in the operating system have many identical virtual addresses, and after MMU translation, these identical virtual addresses yield different physical addresses, thus creating the homonyms problem.
- The most common place for the homonyms problem is 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, and this cached data is wrong and useless for the new process. The solution is to invalidate all the cache left behind by the old process during a process switch, so that the new process gets a clean virtual cache when it runs.
Cache classification
VIVT (Virtual Index Virtual Tag): usesthe virtual address’s index field and 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 aliasing problem (Synonym/Aliasing): when different virtual addresses map to the same physical address, multiple copies of data may appear in the cache, which can lead to data inconsistency.
PIPT (Physical Index Physical Tag): usesthe physical address’s index field and tag field, which is equivalent toPhysical cache
- The CPU first translates the virtual address into a physical address through the MMU, then uses the physical address for cache indexing and matching.
- No aliasing problem.
- Common L2 Cache
VIPT (Virtual Index Physical Tag): usesVirtual address index field and physical address tag field.
- CPU Use the low bits of the virtual address as the cache index.。Use the physical address as the tag., used for match determination. BecauseCache line alignment (usually 64 bytes or 128 bytes), the low bits of the virtual address match the low bits of the physical address., so it is safe to use the virtual address for indexing.
- Avoids the aliasing problem., because the physical address is used as the tag.
- Subject to Page Size Limitation: the virtual index length must be ≤ the page offset bits; otherwise, the same virtual index from different pages will conflict. (VIPT uses the low bits of the virtual address to index cache lines.)
- Common L1 Cache
VIPT working process
From a general perspective:
1 | VA = 虚拟页号 (VPN) | 页内偏移 (PO) |
From the VIPT perspectivePODivided into:
1 | PO = Cache Index | Cache Line Offset |
- The VIPT cache’sindex bits come only from the page offset portion of the virtual address(rather than the VPN), to avoid the index bits being affected by virtual address translation (the page offset is identical in virtual and physical addresses).
- The cache line offset is used to locate the specific byte within a cache line.
Assume the L1 cache is 64KB and the cache line is 64B:
Index bits = log₂(64KB / 64B) = log₂(1024) = 10 bits
So the cache index uses the virtual address’s 10 bits
Page offset = 12 bits (4KB page)
The page offset in virtual and physical addresses 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), 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 map to the same physical page, the two 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 alias problem can becache layout avoided by making the VIPT cache’sindex bits come only from the page offset portion of the virtual address(not VPN)
Cache hierarchy
two-level cachesystem

L3 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 cachein, then the CPU directly fromL1 cachefetches the data
- Case2: If the value of x1 is not inL1 cachein, but rather inL2 cachein
- ifL1 cachein, there is no space, then some will be evictedcache line
- data fromL2 cache lineload intoL1 cache line
- CPU fromL1 cache linereads data from
- Case3: the value of x1 is in neither L1 nor L2 cachein, but in memory
- ifL1 cacheandL2 cachein, there is no space, then some will be evictedcache line
- data loaded from memory into L2 and L1’scache linein
- CPU fromL1 cache linereads data from
Multi-level cache access latency

Cache strategies (Cache Policies)
Cache-related policies areconfigured in the MMU page table。Only Normal memory can be cacheable
Cache strategies include:
- Cacheable/non-cacheable
- Cacheable subcategories
- 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 policy:
- Write-back(WB): Write-back operation only updates the cache and does not immediately update 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; its biggest disadvantage is that it consumes 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)
- Writes only update the cache and mark the cache line as dirty. 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 memoryYou can set inner or outer shareability.
- How to distinguish inner or outer varies by design.
- inner attributeUsually,CPU 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 instructions in AArch64 (ARMv8 64-bit)
In A64, the one used is PRFM(Prefetch Memory)。
Instruction format
1 | PRFM <prfop>, [Xn, #imm] // Prefetch the cache from the address Xn + offset |
Description of the prfop syntax structure
1 | <prfop> = <type><target><policy> | #uimm5 |
| field | meaning | Example values |
|---|---|---|
<type> | Prefetch purpose | PLDRead,PSTWrite |
<target> | Prefetch target cache level | L1,L2,L3 |
<policy> | Cache usage policy | KEEP(reuse),STRM(streaming access / one-time use) |
#uimm5 | 5-bit encoding form | #0~#31 |
example
Prefetch read data to L1, keep it in the cache
1 | PRFM PLDL1KEEP, [X0, #32] |
Meaning: take the address(X0 + 32)the corresponding data is loaded in advance to L1 Cache, and marked asmay be reused repeatedly。
Prefetch one-time read (streaming access)
1 | PRFM PLDL1STRM, [X1] |
Meaning: take[X1]preload into the cache, butnot retained for long(suitable for sequential streaming reads like memcpy).
Equivalent immediate notation
1 | PRFM #0, [X0] |
#0Corresponds to the default in the ARM prefetch hint tablePLDL1KEEP。
| uimm5 value | Corresponds to prfop | meaning |
|---|---|---|
#0 | PLDL1KEEP | Read prefetch to L1, reuse (most common) |
#1 | PLDL1STRM | Read prefetch to L1, streaming (used only 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 in a CPUinstruction cache,data cacheandMMU,TLBetc. see the same copy of memory
- PoU for a PE, meaning to guaranteePEwhat is seenI/D cacheandMMUis the same copy. In most cases,PoU is viewed from the perspective of a single-core system
- PoU for inner share, meaning that ininner shareall withinPEcan all see the same copy
- PoC: all observers in the system, such asDSP, GPU, CPU, DMAetc. can all see the same memory copy


Difference between PoU and PoC
- PoCIt is a system concept, related to system configuration.
- For example,Cortex-A53can be configuredL2 cacheand withoutL2 cache, may affectPoUthe scope of


Cache maintenance
- Cache management operations
- Invalidate (Invalidate) the entire cache or a particular cache line. The data in the cache will be discarded.
- Clean (Clean) the entire cache or a particular cache line.Write back dirty cache line data to the next-level cache or main memory.(also called flush)
- Zero (Zero) operation
- Cache management objects
- ALL : the entire cache
- VA: a virtual address, sometimes called MVA (Modified Virtual Address, which is a cache line containing a particular virtual address)
- Set/Way: a specific cache line or set and way
- Scope of Cache management
- PoC
- PoU
- Shareability
- inner
Cache instruction format



Instructions that take an address parameter use a 64-bit register that holds 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 fault is generated.
Example 1
Iterate through all CPU data cache levels (L1/L2/L3…) and perform clean by set/way on each cache level to ensure all data in the cache is written back to memory:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 | // AArch64: Data Cache Clean by Set/Way// Can be executed at EL1 (kernel mode).global clean_data_cacheclean_data_cache: // Read cache level ID (CLIDR_EL1) MRS X0, CLIDR_EL1 // Extract Level of Coherency (3-bit per level) AND W3, W0, #0x07000000 // mask[26:24] LSR W3, W3, #23 // W3 = 2 * LoC CBZ W3, Finished // Exit if no cache MOV W10, #0 // W10 = 2 * cache level index MOV W8, #1 // Constant 1Loop1: // Calculate 3 × cache level (3 bits per level describe cache type) ADD W2, W10, W10, LSR #1 // W2 = 3*level = level*2 + level/2 LSR W1, W0, W2 // Get current level cache type AND W1, W1, #0x7 // Extract the lowest three bits CMP W1, #2 // 2 = Data Cache,3 = Unified B.LT Skip // Skip levels without D cache // ---- Select current cache level for operation ---- MSR CSSELR_EL1, X10 // X10 low bits specify the level ISB // Wait for selection to take effect // Read cache configuration from CCSIDR_EL1 MRS X1, CCSIDR_EL1 // X1 holds CCSIDR // ---- Parse Cache Line size ---- AND W2, W1, #7 // bits[2:0]: log2(line_len)-4 ADD W2, W2, #4 // W2 = log2(line_len) // ---- Parse Way ---- UBFX W4, W1, #3, #10 // bits[12:3]: ways-1 CLZ W5, W4 // W5 = leading zero count LSL W9, W4, W5 // Initialize way bit offset value LSL W16, W8, W5 // Step size for each decrementLoop2: // ---- Parse Set ---- UBFX W7, W1, #13, #15 // bits[27:13]: sets-1 LSL W7, W7, W2 // Align set bits LSL W17, W8, W2 // Step size for each decrementLoop3: // ---- Assemble DC operation parameters ---- ORR W11, W10, W9 // Combine level + way ORR W11, W11, W7 // Add set // The middle and low bit fields in X11 encode Way + Set + Cache level, telling the CPU which cache line to clean. DC CSW, X11 // CLEAN by set/way SUBS W7, W7, W17 // set-- loop B.GE Loop3 SUBS X9, X9, X16 // way-- loop B.GE Loop2Skip: ADD W10, W10, #2 // Next cache level CMP W3, W10 DSB // Ensure the previous clean is fully executed B.GT Loop1Finished: DSB SY // Synchronization barrier ISB RET |
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 types in the system |
| 2 | Parse LoC | Determine how many cache levels need to be traversed |
| 3 | Loop through each level | Process each cache level in sequence from L1 → L2 → L3… |
| 4 | Use CSSELR_EL1 to select the cache level | Tell the CPU which cache level to access next |
| 5 | Read CCSIDR_EL1 | Query the detailed configuration of this Cache (number of sets, ways, line size) |
| 6 | Nested loop | Iterate over Set and Way, cleaning the cache line by line |
| 7 | DC CSW | Execute Clean by Set/Way |
| 8 | DSB+ISB | Data synchronization barrier, ensuring that execution continues only after the cleanup is complete |
Under normal circumstances, cleaning or invalidating the entire cache is something only firmware should do, as part of the kernel power-on or power-off sequence. It may also take a significant amount of time; the number of lines in an L2 cache can be very 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
123456789 | /* Coherency example for data and instruction accesses within the same InnerShareable domain. Enter this code with <Wt> containing a new 32-bit instruction,to be held in Cacheable space at a location pointed to by Xn. */STR Wt, [Xn]DC CVAU, Xn // Clean data cache by VA to point of unification (PoU)DSB ISH // Ensure visibility of the data cleaned from cacheIC IVAU, Xn // Invalidate instruction cache by VA to PoUDSB ISH // Ensure completion of the invalidationsISB // Synchronize the fetched instruction stream |
This code is standard. Self-modifying code / JIT compilation synchronizationSteps:
- Write new instructions to memory (possibly in D-Cache)
- Clean D-Cache, write data back to PoU
- DSB: ensure the write-back completes
- Invalidate the corresponding address in I-Cache
- DSB: ensure invalidation completes
- ISB: flush the instruction fetch pipeline, CPU executes new instructions
Cache discovery
- When we perform 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 level of cache, what are its set and way counts?
- For the zero operation, 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; you can read the number of cache levels
- Cache Type Register(CTR, CTR_EL0): cache line size; you 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) UCT bit to complete.
- sets and ways: requires accessing 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 a zero operation.
DC ZVA (Data Cache Zero by Virtual Address)
- Zero the memory corresponding to a cache line
- DCZID_EL0 Stores the block size that can be zeroed
- Access permissions: Only privileged levels (EL1 and above) can access DCZID_EL0
Control bits:
- SCTLR_EL1.DZE: Controls whether DC ZVA is allowed at EL0
- HCR_EL2.TDZ: Controls whether DC ZVA is allowed for EL0/EL1 in the Non-secure world
SCTLR/SCTLR_The [DZE] bit of EL1 and the [TDZ] bit of the Hypervisor Configuration Register (HCR/HCR_EL2) 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’s TDZ bit. In this case, reading DCZID_EL0 returns 0, indicating that the instruction is not supported.
The CLIDR register only knows how many levels of cache the processor itself integrates. 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 does not know about any external L3 cache. When executing cache maintenance or maintaining consistency with integrated caches, non-integrated caches may need to be considered.
Cache Experiment 1: Cache Enumeration (Cache Discovery)

Experimental results:

Code
Core idea:
- First identify the cache type at each level (CLIDR)
- Select level and type, read configuration registers (CSSELR/CCSIDR)
- Calculate the set/way/line size and total size of each cache level
- Print boundary information and L1 I-Cache addressing strategy**
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 | static const char *cache_type_string[] = {"nocache", "i-cache", "d-cache", "separate cache", "unified cache"};// Instruction cache policies// L1 instruction cache addressing strategy// 0 = VPIPT// 1 = Reserved// 2 = VIPT// 3 = PIPTstatic const char *icache_policy_str[] = { [0 ... ICACHE_POLICY_PIPT] = "RESERVED/UNKNOWN", [ICACHE_POLICY_VIPT] = "VIPT", [ICACHE_POLICY_PIPT] = "PIPT", [ICACHE_POLICY_VPIPT] = "VPIPT",};// Read CTR_CTR at EL0_CWG(Cache WriteBack Granule)// Maximum granularity of cache write-back: 2^(val) * 4 bytesstatic inline unsigned int cache_type_cwg(void) { return (read_sysreg(CTR_EL0) >> CTR_CWG_SHIFT) & CTR_CWG_MASK;}// Under normal circumstances, cache_line_size = CWG// Get the cache line size: 2^(CWG) * 4 = 4 << CWGstatic inline int cache_line_size(void) { unsigned int cwg = cache_type_cwg(); return 4 << cwg;}// Read CLIDR_EL1, Cache Level ID Register// Get the cache type, read the CTYPE field of CLIDR_EL1static inline enum cache_type get_cache_type(int level) { unsigned long clidr; if (level > MAX_CACHE_LEVEL) return CACHE_TYPE_NOCACHE; clidr = read_sysreg(clidr_el1); return CLIDR_CTYPE(clidr, level);}/* * Get each levelcacheofwayandset * * From the Raspberry Pi official website, we can know: * https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/README.md * * Caches: 32 KB data + 48 KB instruction L1 cache per core. 1MB L2 cache. * */static void get_cache_set_way(unsigned int level, unsigned int ind) { unsigned long val; unsigned int line_size, set, way; int tmp; /* 1. First write the CSSELR_EL1 register (Cache Size Selection Register) to indicate which cache to query */ // Write the level and cache type (0b0 data cache or unified cache, or 0b1 instruction // cache) tmp = (level - 1) << CSSELR_LEVEL_SHIFT | ind; write_sysreg(tmp, CSSELR_EL1); /* * 2. * ReadCCSIDR_EL1the register value,When not implementedARMv8.3-CCIDXwhen,This register only has the low32is valid。 * Note that this register has twolayoutways。 * */ val = read_sysreg(CCSIDR_EL1); // NumSets bit field, describes the number of sets in the cache set = (val & CCSIDR_NUMSETS_MASK) >> CCSIDR_NUMSETS_SHIFT; set += 1; // Associativity bit field, describes the number of ways of the cache way = (val & CCSIDR_ASS_MASK) >> CCSIDR_ASS_SHIFT; way += 1; // LineSize bit field of CCSIDR_EL1 // line_size_bytes = 1 << (LineSize + 4) line_size = (val & CCSIDR_LINESIZE_MASK); line_size = 1 << (line_size + 4); printk(" %s: set %u way %u line_size %u size %uKB\n", ind ? "i-cache" : "d/u cache", set, way, line_size, (line_size * way * set) / 1024);}int init_cache_info(void) { int level; unsigned long ctype; printk("parse cache info:\n"); // Traverse each cache level for (level = 1; level <= MAX_CACHE_LEVEL; level++) { /* Get cache type */ ctype = get_cache_type(level); /* If the cache type is NONCACHE, exit the loop */ if (ctype == CACHE_TYPE_NOCACHE) { level--; break; } printk(" L%u: %s, cache line size(CWG) %u\n", level, cache_type_string[ctype], cache_line_size()); if (ctype == CACHE_TYPE_SEPARATE) { get_cache_set_way(level, 1); get_cache_set_way(level, 0); } else if (ctype == CACHE_TYPE_UNIFIED) get_cache_set_way(level, 0); } /* * GetICB,LOUU,LOCandLOUIS * ICB: Inner cache boundary * LOUU: Single-core processorPoUofcacheBoundary。 * LOC: PoCofcacheBoundary * LOUIS:PoU for inner shareofcacheBoundary。 * */ unsigned clidr = read_sysreg(clidr_el1); printk(" IBC:%u LOUU:%u LoC:%u LoUIS:%u\n", CLIDR_ICB(clidr), CLIDR_LOUU(clidr), CLIDR_LOC(clidr), CLIDR_LOUIS(clidr)); unsigned ctr = read_sysreg(ctr_el0); printk(" Detected %s I-cache\n", icache_policy_str[CTR_L1IP(ctr)]); return level;} |
Related registers
CSSELR_EL1
Cache Size Selection Register

| Bits | Name | meaning |
|---|---|---|
| 63:5 | RES0 | Reserved bit, read/write has 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 (Cache Level) 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 read from CSSELR_EL1 is indeterminate. |
| 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 read from CSSELR_EL1 are indeterminate. |



CCSIDR_EL1
Current Cache Size ID Register


| Bits | Name | meaning |
|---|---|---|
| 63:56 | RES0 | Reserved bit |
| 55:32 | NumSets | Number of sets in the 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 bit |
| 23:3 | Associativity | Describes cache way countCache’s associativity (ways) minus 1 → actual associativity = Associativity + 1. Note: not necessarily a power of 2. |
| 2:0 | LineSize | Calculation formula for log2 of cache line size minus 4:line_size_bytes = 1 << (LineSize + 4) |

ifARMv8.5-MemTag is implemented and enabed

CCSIDR2_EL1
Current Cache Size ID Register 2
ARMv8.3-CCIDX is implementedonly then is it effective

| Bits | Name | meaning |
|---|---|---|
| 63:24 | RES0 | Reserved bit, read/write has no meaning |
| 23:0 | NumSets | The number of sets in the cache is reduced by 1.Calculation method:NumSets + 1Get the actual number of sets.Note:set number is not necessarily a power of 2 |
- Purpose: query of the specified cache set quantity。
- This register is generally with CSSELR_EL1 For use with:
- Write CSSELR_EL1 to select cache level and type (data/instruction/tag)
- Read CCSIDR2_EL1 to get the number of sets of this cache.
- NumSets = 0 represents 1 set
- NumSets > 0 represents Actual number of sets = NumSets + 1

Notes on reading CCSIDR2_EL1:

CLIDR_EL1
Cache Level ID Register

- Purpose:
- Identify the type of each level of cache in the processor (Instruction/Data/Unified/Tag).
- point out that it can be used Set/Way cache maintenance instructions Managed cache.
- provide Cache hierarchy consistency and sharing level information(LoC、LoU、LoUIS)。
- Supports up to 7 levels of cache.
| Bits | Name | meaning |
|---|---|---|
| 63:47 | RES0 | Reserved bit |
| 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: Separate instruction and data cache 0b100: Unified cache |
CTR_EL0
Cache Type Register
Its purpose is 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 minimum cache line size covered by 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 an I-cache invalidate is required to make data writes visible to the I-cache. 0 = After a data write, the I-cache must be invalidated for instructions to fetch the latest data. 1 = No need to invalidate the I-cache. |
| 28 | IDC | Data cache clean requirements for instruction to data coherence | Determines whether the D-cache needs to be cleaned to ensure I/D consistency. 0 = The data cache needs to be cleaned to PoU to ensure I/D consistency. 1 = D-cache clean is not required. Usually modern cores set this to 1, indicating that hardware automatically ensures consistency. |
| 27-24 | CWG | Cache Writeback Granule | Cache Writeback Granule, the maximum writeback granularity of the cache (log2, in units of word=4B). Indicates the maximum memory block size that may be affected when a cache line is written back (in units of word=4B). For example, CWG=0b0100 → 2^(4) = 16 words = 64 bytes. |
| 23-20 | ERG | Exclusives reservation granule | Exclusive Reservation Granule, the maximum reservation range 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

In general,CWG = maximum cache line size, because write-back is performed in units of entire cache lines.
However, the ARM specification allows microarchitectural differences:
- CWG ≥ cache line size: some implementations may merge multiple cache lines into a larger burst write (e.g., 128B) during write-back.
- CWG = cache line size: common case, e.g., line=64B → CWG=0b0100 (16 words).
- CWG not provided (
0b0000): must assumemaximum write-back granularity is 2KB, or read the Cache Size ID Registers yourself to infer.
