| |||
| Home > Caches and Write Buffer > Cache lock down > Locking down the caches | |||
The procedure for locking down a line in the I Cache and the D Cache are slightly different. In both cases:
The cache must be put into lock down mode by programming register 9.
A line fill must be forced.
The corresponding data must be locked in the cache.
If more than one line is to be locked, a software loop must repeat this procedure.
For the D Cache, the procedure is as follows:
Write to CP15 register 9, setting DL=1 and Dindex=0.
Initialize the pointer to the first of the 16 words to be locked.
Execute an LDR from that location. This forces a linefill from that location, and the resulting four words are captured by the cache.
Increment the pointer by 16 to select cache bank 1.
Execute an LDR from that location. The resulting linefill is captured in cache bank 2.
Repeat steps 1 to 5 for cache banks 3 and 4.
Write to CP15 register 9, setting DL=0 and Dindex=1.
If there were more data to lock down, at the final step, step 7, the DL bit should be left HIGH, Dindex incremented by 1 line, and the process repeated. The DL bit should only be set LOW when all the lock down data has been loaded.
For the I Cache, this procedure is as follows:
Write to CP15 register 9, setting IL=1 and Iindex=0.
Initialize the pointer to the first of the sixteen words to lock down.
Force a line fill from that location by writing to CP15 register 7.
Increment the pointer by 16 to select cache segment 1.
Force a line fill from that location by writing to CP15 register 7. The resulting line fill is captured in segment 1.
Repeat for cache segments 3 and 4.
Write to CP15 register 9, setting IL=0 and Iindex=1.
If there were more data to lock down, at the final step 7, the IL bit should be left HIGH, Iindex increment by 1 line and the process repeated. The IL bit should be set LOW when all the lock down data had been loaded.
Performing lock down in the I Cache involves a similar sequence of operations, except that the IL and Iindex of CP15 register 9 are accessed.
The only significant difference in the sequence of operations is that an MCR instruction must be used to force the line fill in the I Cache, instead of an LDR, This is due to the Harvard nature of the processor. During the MCR, the value set up in the pointer register is output on the instruction address bus, and a memory access is forced. As this misses in the cache (due to earlier flushing), a line fill occurs.
The rest of the sequence of operations is exactly the same as for D Cache lock down.
The MCR to perform the I Cache lookup is a CP15 register 7 operation:
MCR p15, 0, Rd, c7, c13, 1
A macro used to lock down code in the instruction cache is given below:
; Subroutine lock_i_cache
; R1 contains start address of code to be locked down
;
; The subroutine performs a lock-down of instructions in the
; I Cache
; It first reads the current lock_down index and then locks
; down the number of lines requested.
;
; Note that this subroutine must be located in a non-cacheable
; region of memory in order to work, or these instructions
; themselves will be locked into the cache. Interrupts should also
; be disabled.
; The subroutine should be called via the ‘BL’ instruction.
;
; This subroutine returns the next free cache line number in R0, or
; 0 in R0.
; if an error occurs.
lock_i_cache
STMFD R13!, {R1-R3} ; save corrupted registers
BIC R1, R1, #0x3f ; align address to cache line
MRC p15, 0, R3, c9, c0, 1 ; get current instruction cache index
AND R2, R2, #0x3f ; mask off unwanted bits
ADD R3, R2, R0 ; Check to see if current index
CMP R3, #0x3f ; plus line count is greater than 63
; If so, branch to error as
; more lines are being locked down
; than permitted
ORR 2, R2, #0x80000000 ; set lock bit, r2 contains the cache
; line number to lock down
lock_loop
MCR p15, 0, R2, c9, c0, 1 ; write lock down register
MCR p15, 0, R1, c7, c13, 1 ; force line fetch from external memory
ADD R1, R1, #16 ; add 4 words to address
MCR p15, 0, R1, c7, c13, 1 ; force line fetch from external memory
ADD R1, R1, #16 ; add 4 words to address
MCR p15, 0, R1, c7, c13, 1 ; force line fetch from external memory
ADD R1, R1, #16 ; add 4 words to address
MCR p15, 0, R1, c7, c13, 1 ; force line fetch from external memory
ADD R1, R1, #16 ; add 4 words to address
ADD R2, R2, #0x1 ; increment cache line in lock down
; register
SUBS R0, R0, #0x1 ; decrement line count and set flags
BNE lock_loop ; if r0! = 0 then branch round
BIC R0, R2, #0x80000000 ; clear lock bit in lockdown register
MCR p15, 0, R0, c9, c0, 1 ; restrict victim counter to lines
; r0 to 63
LDMFD R13!, {R1-R3} ; restore corrupted registers and return
MOV PC, LR ; R0 contains the first free cache line
; number
error
LDR R0, =0 ; make r0 = 0 to indicate error
LDMFD R13!, {R1-R3} ; restore corrupted registers and return
MOV PC, LR