1 /******************************************************************************
3 * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /******************************************************************************
36 * Scrub LMB memory and all internal BRAMs (data cache, instruction cache,
37 * MMU UTLB and branch target cache) in MicroBlaze to reduce the possibility
38 * of an uncorrectable error when fault tolerance support is enabled.
40 * This routine assumes that the processor is in privileged mode when it is
41 * called, if the MMU is enabled.
43 * Call this routine regularly from a timer interrupt.
49 *******************************************************************************/
51 #include "xparameters.h"
53 /* Define if fault tolerance is used */
54 #ifdef XPAR_MICROBLAZE_FAULT_TOLERANT
55 #if XPAR_MICROBLAZE_FAULT_TOLERANT > 0
56 #define FAULT_TOLERANT
60 /* Define if LMB is used and can be scrubbed */
61 #if defined(XPAR_MICROBLAZE_D_LMB) && \
62 defined(XPAR_DLMB_CNTLR_BASEADDR) && \
63 defined(XPAR_DLMB_CNTLR_HIGHADDR)
64 #if XPAR_MICROBLAZE_D_LMB == 1
65 #define HAS_SCRUBBABLE_LMB
66 #define DLMB_MASK (XPAR_DLMB_CNTLR_HIGHADDR - XPAR_DLMB_CNTLR_BASEADDR)
70 /* Set default cache line lengths */
71 #ifndef XPAR_MICROBLAZE_DCACHE_LINE_LEN
72 #define XPAR_MICROBLAZE_DCACHE_LINE_LEN 4
75 #ifndef XPAR_MICROBLAZE_ICACHE_LINE_LEN
76 #define XPAR_MICROBLAZE_ICACHE_LINE_LEN 4
79 /* Define if internal Data Cache BRAMs are used */
80 #if defined(XPAR_MICROBLAZE_USE_DCACHE) && defined(XPAR_MICROBLAZE_DCACHE_BYTE_SIZE)
81 #if XPAR_MICROBLAZE_USE_DCACHE == 1 && XPAR_MICROBLAZE_DCACHE_BYTE_SIZE > 1024
82 #define HAS_BRAM_DCACHE
83 #define DCACHE_INCREMENT (XPAR_MICROBLAZE_DCACHE_LINE_LEN * 4)
84 #define DCACHE_MASK (XPAR_MICROBLAZE_DCACHE_BYTE_SIZE - 1)
88 /* Define if internal Instruction Cache BRAMs are used */
89 #if defined(XPAR_MICROBLAZE_USE_ICACHE) && defined(XPAR_MICROBLAZE_CACHE_BYTE_SIZE)
90 #if XPAR_MICROBLAZE_USE_ICACHE == 1 && XPAR_MICROBLAZE_CACHE_BYTE_SIZE > 1024
91 #define HAS_BRAM_ICACHE
92 #define ICACHE_INCREMENT (XPAR_MICROBLAZE_ICACHE_LINE_LEN * 4)
93 #define ICACHE_MASK (XPAR_MICROBLAZE_CACHE_BYTE_SIZE - 1)
97 /* Define if internal MMU UTLB BRAM is used */
98 #ifdef XPAR_MICROBLAZE_USE_MMU
99 #if XPAR_MICROBLAZE_USE_MMU > 1
100 #define HAS_BRAM_MMU_UTLB
104 /* Define if internal BTC BRAM is used, and match BTC clear to a complete cache scrub */
105 #if defined(XPAR_MICROBLAZE_USE_BRANCH_TARGET_CACHE) && \
106 defined(XPAR_MICROBLAZE_BRANCH_TARGET_CACHE_SIZE)
107 #if XPAR_MICROBLAZE_USE_BRANCH_TARGET_CACHE == 1
108 #if XPAR_MICROBLAZE_BRANCH_TARGET_CACHE_SIZE == 0 || \
109 XPAR_MICROBLAZE_BRANCH_TARGET_CACHE_SIZE > 4
110 #define HAS_BRAM_BRANCH_TARGET_CACHE
111 #ifdef HAS_BRAM_DCACHE
112 #define BTC_MASK_D (XPAR_MICROBLAZE_DCACHE_BYTE_SIZE/DCACHE_INCREMENT-1)
114 #define BTC_MASK_D 256
116 #ifdef HAS_BRAM_ICACHE
117 #define BTC_MASK_I (XPAR_MICROBLAZE_CACHE_BYTE_SIZE/ICACHE_INCREMENT-1)
119 #define BTC_MASK_I 256
121 #if BTC_MASK_D > BTC_MASK_I
122 #define BTC_MASK BTC_MASK_D
124 #define BTC_MASK BTC_MASK_I
130 /* Define index offsets to persistent data used by this routine */
131 #define DLMB_INDEX_OFFSET 0
132 #define DCACHE_INDEX_OFFSET 4
133 #define ICACHE_INDEX_OFFSET 8
134 #define MMU_INDEX_OFFSET 12
135 #define BTC_CALL_COUNT_OFFSET 16
138 .globl microblaze_scrub
139 .ent microblaze_scrub
143 #ifdef FAULT_TOLERANT
144 la r6, r0, L_persistent_data /* Get pointer to data */
146 #ifdef HAS_SCRUBBABLE_LMB
148 lwi r5, r6, DLMB_INDEX_OFFSET /* Get dlmb index */
149 lw r7, r5, r0 /* Load and store */
151 addik r5, r5, 4 /* Increment and save dlmb index */
152 andi r5, r5, DLMB_MASK
153 swi r5, r6, DLMB_INDEX_OFFSET
154 #endif /* HAS_SCRUBBABLE_LMB */
156 #ifdef HAS_BRAM_DCACHE
158 lwi r5, r6, DCACHE_INDEX_OFFSET /* Get dcache line index */
159 wdc r5, r0 /* Invalidate data cache line */
160 addik r5, r5, DCACHE_INCREMENT /* Increment and save entry index */
161 andi r5, r5, DCACHE_MASK
162 swi r5, r6, DCACHE_INDEX_OFFSET
163 #endif /* HAS_BRAM_DCACHE */
165 #ifdef HAS_BRAM_ICACHE
167 lwi r5, r6, ICACHE_INDEX_OFFSET /* Get icache line index */
168 wic r5, r0 /* Invalidate data cache line */
169 addik r5, r5, ICACHE_INCREMENT /* Increment and save entry index */
170 andi r5, r5, ICACHE_MASK
171 swi r5, r6, ICACHE_INDEX_OFFSET
172 #endif /* HAS_BRAM_ICACHE */
174 #ifdef HAS_BRAM_MMU_UTLB
176 lwi r5, r6, MMU_INDEX_OFFSET /* Get UTLB entry index */
177 mts rtlbx, r5 /* Access next entry in UTLB */
178 mts rtlbhi, r0 /* Clear the UTLB entry */
180 addik r5, r5, 1 /* Increment and save entry index */
182 swi r5, r6, MMU_INDEX_OFFSET
183 #endif /* HAS_BRAM_MMU_UTLB */
185 #ifdef HAS_BRAM_BRANCH_TARGET_CACHE
187 lwi r5, r6, BTC_CALL_COUNT_OFFSET /* Get BTC call count offset */
188 addik r5, r5, 1 /* Increment and save call count */
189 andi r5, r5, BTC_MASK
190 swi r5, r6, BTC_CALL_COUNT_OFFSET
192 bnei r5, L_skip_btc_scrub /* Skip scrub unless count wrap */
193 bri 4 /* Clear branch target cache */
195 #endif /* HAS_BRAM_BRANCH_TARGET_CACHE */
197 #endif /* FAULT_TOLERANT */
199 rtsd r15, 8 /* Return */
201 .end microblaze_scrub
203 /* Persistent data used by this routine */
207 .long 0 /* dlmb index */
208 .long 0 /* dcache index */
209 .long 0 /* icache index */
210 .long 0 /* mmu entry index */
211 .long 0 /* btc call count */