Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

microblaze: Add support for error injection

To inject the error using the tmr inject IP reset vectors need to be placed
in lmb(bram) due to the limitation in HW when this code runs out of DDR.
Below code adds the error inject code to the .init.ivt section to copy
it in machine_early_init to lmb/Bram location. C_BASE_VECTORS which allow
moving reset vectors out of 0 location is not currently supported by
Microblaze architecture, that's why all the time reset vectors with
injection code is all the time copied to address 0.

As of now getting this functionality working CPU switches to real mode
and simply jumps to bram, which causes triggering of fault which continues
to call_xmb_manager_break break handler which will at the end calls the
error count callback function and performs recovery.

Signed-off-by: Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
Link: https://lore.kernel.org/r/20220627064024.771037-4-appana.durga.rao@xilinx.com
Signed-off-by: Michal Simek <michal.simek@amd.com>

authored by

Appana Durga Kedareswara rao and committed by
Michal Simek
adc4cefa 88707ebe

+60
+8
arch/microblaze/include/asm/xilinx_mb_manager.h
··· 5 5 #ifndef _XILINX_MB_MANAGER_H 6 6 #define _XILINX_MB_MANAGER_H 7 7 8 + # ifndef __ASSEMBLY__ 9 + 8 10 #include <linux/of_address.h> 9 11 10 12 /* ··· 19 17 void xmb_manager_register(uintptr_t phys_baseaddr, u32 cr_val, 20 18 void (*callback)(void *data), 21 19 void *priv, void (*reset_callback)(void *data)); 20 + asmlinkage void xmb_inject_err(void); 21 + 22 + # endif /* __ASSEMBLY__ */ 23 + 24 + /* Error injection offset */ 25 + #define XMB_INJECT_ERR_OFFSET 0x200 22 26 23 27 #endif /* _XILINX_MB_MANAGER_H */
+52
arch/microblaze/kernel/entry.S
··· 27 27 28 28 #include <asm/page.h> 29 29 #include <asm/unistd.h> 30 + #include <asm/xilinx_mb_manager.h> 30 31 31 32 #include <linux/errno.h> 32 33 #include <asm/signal.h> ··· 1152 1151 nop 1153 1152 1154 1153 #ifdef CONFIG_MB_MANAGER 1154 + .global xmb_inject_err 1155 + .section .text 1156 + .align 2 1157 + .ent xmb_inject_err 1158 + .type xmb_inject_err, @function 1159 + xmb_inject_err: 1160 + addik r1, r1, -PT_SIZE 1161 + SAVE_REGS 1162 + 1163 + /* Switch to real mode */ 1164 + VM_OFF; 1165 + set_bip; 1166 + mbar 1 1167 + mbar 2 1168 + bralid r15, XMB_INJECT_ERR_OFFSET 1169 + nop; 1170 + 1171 + /* enable virtual mode */ 1172 + set_vms; 1173 + /* barrier for instructions and data accesses */ 1174 + mbar 1 1175 + mbar 2 1176 + /* 1177 + * Enable Interrupts, Virtual Protected Mode, equalize 1178 + * initial state for all possible entries. 1179 + */ 1180 + rtbd r0, 1f 1181 + nop; 1182 + 1: 1183 + RESTORE_REGS 1184 + addik r1, r1, PT_SIZE 1185 + rtsd r15, 8; 1186 + nop; 1187 + .end xmb_inject_err 1188 + 1155 1189 .section .data 1156 1190 .global xmb_manager_dev 1157 1191 .global xmb_manager_baseaddr ··· 1260 1224 #endif 1261 1225 .org 0x20 1262 1226 brai TOPHYS(_hw_exception_handler); /* HW exception handler */ 1227 + 1228 + #ifdef CONFIG_MB_MANAGER 1229 + /* 1230 + * For TMR Inject API which injects the error should 1231 + * be executed from LMB. 1232 + * TMR Inject is programmed with address of 0x200 so that 1233 + * when program counter matches with this address error will 1234 + * be injected. 0x200 is expected to be next available bram 1235 + * offset, hence used for this api. 1236 + */ 1237 + .org XMB_INJECT_ERR_OFFSET 1238 + xmb_inject_error: 1239 + nop 1240 + rtsd r15, 8 1241 + nop 1242 + #endif 1263 1243 1264 1244 .section .rodata,"a" 1265 1245 #include "syscall_table.S"