1.1
/*
* __flush_dcache_all ()
* Flush the Wholed-cache.
* Corrupted registers:x0-x7, x9-x11
*/
ENTRY (__flush_dcache_all)
Guarantee the order of previous visit instructions
DSB Sy
Read Cache level ID Register
Mrs X0, CLIDR_EL1//Read CLIDR
Take bits[26:24] (level of coherency for the cache hierarchy.)
Cache consistency is required (e.g. with level 3 cache, but level 2 requires consistency)
And X3, x0, #0x7000000//extract loc from CLIDR
Logical right Shift 23 bits, put bits[26:24] to bits[2:0]
LSR X3, X3, #23//left align loc bit field
If you need to do cache consistency at the level of 0, you do not need to flush and jump to the finished mark.
CBZ X3, finished//If LOC is 0, then no need toclean
//x10 Store Cache level, from level0 Cache start doing Flush
// the following three loops LOOP3 is a Set/way ( x9 ),
//LOOP2 is a Index ( X7 ), LOOP1 is a Cachelevel (x10)
mov x10, #0//start clean at cache level 0
LOOP1:
X10+2 after the right shift is exactly equal to 1, plus x10 itself is exactly equal to 3
The number of executions per loop1,x2+3* is performed to move the X0 (clidr_el1) to the right by 3 bits,
Take down the CType Type fields field of the cache, Clidr_el1 in the form "ARMv8 ARM"
Add x2, x10, X10, LSR #1/
X0 logical right Shift x2 bit, to X1, extract the cache type into the X1, x0 storage: clidr_el1
LSR x1, x0, x2
Hide the high level and take the current cache type only
and X1, X1, #7
/* Determine what type of current cache is:
* No Cache.
* 001 instruction Cache only.
* 010 Data Cache only.
* 011 separate instruction and data caches.
* Unified Cache.
*/
Less than 2 indicates that the data cache does not exist or only icache,
Jump skip execution, greater than or equal to 2 continue execution
CMP x1, #2
b.lt Skip
/*
* save/disable and restore interrupts.
*. macro Save_and_disable_irqs, Olddaif
* Mrs \olddaif,daif
* DISABLE_IRQ
*. endm
*/
Save Daif to X9 Register, turn off interrupts
Save_and_disable_irqs x9//Make CSSELR and CCSIDR access atomic
Select the current cache level to operate, Csselr_el1 Register BIT[3:1] Select the cache level to operate
X10=0 at first execution, select level 0 cache
MSR csselr_el1,x10
ISB is used to synchronize new CSSR and CSIDR registers
Isb
Because "MSR csselr_el1,x10" is executed, the CCSIDR_EL1 is re-read
Mrs X1, CCSIDR_EL1//Read the new CCSIDR
/*
*. macro Restore_irqs, Olddaif
* MSR Daif, \olddaif
. * ENDM
*/
Restore_irqs x9
X1 Storage Ccsidr_el1 content, low three bits is (Log2 (number of bytes in cache line)) –4
// Plus 4 after x2= (Log2 (numberof bytes in cache line))
And x2, x1, #7//Extract the length of the Cachelines
Add x2, x2, #4//Add 4 (line length offset)
MOV x4, #0x3ff
Logical right Shift 3 bits, extract Bits[12:3] (associativityof cache) –1,
//x4 Storage Cache of the the number
And X4, x4, x1, LSR #3//Find maximum number on the the-the-the-
Calculate the number of X4 front 0 and save to X5
CLZX5, x4//Find bit position of the sizeincrement
Extract bits[27:13] bit: (number of sets in cache)-1
mov x7, #0x7fff
//x7 stored in Cache in the Set number
And X7, X7, x1, LSR #13//Extract max number of the the index size
LOOP2:
Back up the X4 value
mov x9, x4//Create working copy of Max Waysize
LOOP3:
Store the required operation to X6
LSL X6, X9, X5
Determine which tier of the operation (X10 specifies which level of cache to operate)
Orr X11, X10, X6//Factor and cache number intox11
Determine which set to operate
LSL X6, X7, x2
Orr X11, X11, X6//Factor index number into X11
What level of cache (10) is stored in the X11, which cache (x9), which set (X7)
DC CISW, x11//Clean & invalidate by Set/way
Number of-1
Subs X9, x9, #1//Decrementthe
B.ge LOOP3
Subs X7, X7, #1//Decrementthe Index
B.ge LOOP2
Skip
Add x10, X10, #2//increment cache number,
Why is add 2 not 1? See LOOP1 Marking Office explanation
CMP X3, x10
B.GT LOOP1
Finished:
mov x10, #0//Swith back-to-cache level 0
MSR Csselr_el1, x10//Select Current cache level INCSSELR
DSB Sy
Isb
Ret
Endproc (__flush_dcache_all)