4.6.1. 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:

  1. The cache must be put into lock down mode by programming register 9.

  2. A line fill must be forced.

  3. 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.

Data cache lock down

For the D Cache, the procedure is as follows:

  1. Write to CP15 register 9, setting DL=1 and Dindex=0.

  2. Initialize the pointer to the first of the 16 words to be locked.

  3. Execute an LDR from that location. This forces a linefill from that location, and the resulting four words are captured by the cache.

  4. Increment the pointer by 16 to select cache bank 1.

  5. Execute an LDR from that location. The resulting linefill is captured in cache bank 2.

  6. Repeat steps 1 to 5 for cache banks 3 and 4.

  7. 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.

Instruction cache lock down

For the I Cache, this procedure is as follows:

  1. Write to CP15 register 9, setting IL=1 and Iindex=0.

  2. Initialize the pointer to the first of the sixteen words to lock down.

  3. Force a line fill from that location by writing to CP15 register 7.

  4. Increment the pointer by 16 to select cache segment 1.

  5. Force a line fill from that location by writing to CP15 register 7. The resulting line fill is captured in segment 1.

  6. Repeat for cache segments 3 and 4.

  7. 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
Copyright © 1998 ARM Limited. All rights reserved.DDI0092B
Non-Confidential