1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* 3 * Copyright (C) 2024, Charleye <wangkart@aliyun.com> 4 * All rights reserved. 5 */ 6 #include <lib/extensions/ras.h> 7 #include <services/sdei.h> 8 #include <plat/common/platform.h> 9 #include <lib/libc/aarch64/inttypes_.h> 10 11 static int injected_fault_handler(const struct err_record_info *info, 12 int probe_data, const struct err_handler_data *const data) 13 { 14 uint64_t status; 15 uint64_t misc0; 16 uint32_t intr; 17 // int ret; 18 19 intr = data->interrupt; 20 21 NOTICE("ERXMISC0_EL1 = 0x%lx\n", read_erxmisc0_el1()); 22 NOTICE("ERXSTATUS_EL1 = 0x%lx\n", read_erxstatus_el1()); 23 NOTICE("Raw Interrupt: %d\n", intr); 24 /* 25 * The faulting error record is already selected by the SER probe 26 * function. 27 */ 28 status = read_erxstatus_el1(); 29 /* Clear error */ 30 write_erxstatus_el1(status); 31 isb(); 32 dsb(); 33 NOTICE("[Cleared] ERXMISC0_EL1 = 0x%lx\n", read_erxmisc0_el1()); 34 NOTICE("[Cleared] ERXSTATUS_EL1 = 0x%lx\n", read_erxstatus_el1()); 35 36 ERROR("Fault reported by system error record %d on 0x%lx: status=0x%" PRIx64 "\n", 37 probe_data, read_mpidr_el1(), status); 38 ERROR(" exception reason=%u syndrome=0x%" PRIx64 "\n", data->ea_reason, 39 data->flags); 40 41 misc0 = read_erxmisc0_el1(); 42 43 /* Clear Other Error Count Overflow */ 44 if (misc0 & BIT(47)) { 45 misc0 &= ~BIT(47); 46 misc0 &= ~GENMASK_64(46, 40); 47 write_erxmisc0_el1(misc0); 48 } 49 50 /* Clear Repeat Error Count Overflow */ 51 if (misc0 & BIT(39)) { 52 misc0 &= ~BIT(39); 53 misc0 &= ~GENMASK_64(38, 32); 54 write_erxmisc0_el1(misc0); 55 } 56 57 /* Clear errors again 58 * It might clear more than one error(CE and UC) 59 * at the same time. 60 */ 61 status = read_erxstatus_el1(); 62 write_erxstatus_el1(status); 63 plat_ic_end_of_interrupt(intr); 64 65 // ret = sdei_dispatch_event(5001); 66 // if (ret < 0) { 67 // ERROR("Can't dispatch event to SDEI\n"); 68 // panic(); 69 // } else { 70 // INFO("SDEI event dispatched\n"); 71 // } 72 73 return 0; 74 } 75 76 void plat_handle_uncontainable_ea(void) 77 { 78 /* Do not change the string, CI expects it. Wait forever */ 79 INFO("Injected Uncontainable Error\n"); 80 while (true) { 81 wfe(); 82 } 83 } 84 85 struct err_record_info lua_err_records[] = { 86 /* Record for injected fault */ 87 ERR_RECORD_SYSREG_V1(0, 2, ras_err_ser_probe_sysreg, 88 injected_fault_handler, NULL), 89 }; 90 REGISTER_ERR_RECORD_INFO(lua_err_records); 91 92 struct ras_interrupt lua_ras_interrupts[] = { 93 { 94 .intr_number = PLAT_LUA_DSU_ERRIRQ, 95 .err_record = &lua_err_records[0], 96 }, 97 { 98 .intr_number = PLAT_LUA_DSU_FAULTIRQ, 99 .err_record = &lua_err_records[0], 100 }, 101 { 102 .intr_number = PLAT_LUA_CPU0_ERRIRQ, 103 .err_record = &lua_err_records[0], 104 }, 105 { 106 .intr_number = PLAT_LUA_CPU1_ERRIRQ, 107 .err_record = &lua_err_records[0], 108 }, 109 { 110 .intr_number = PLAT_LUA_CPU2_ERRIRQ, 111 .err_record = &lua_err_records[0], 112 }, 113 { 114 .intr_number = PLAT_LUA_CPU3_ERRIRQ, 115 .err_record = &lua_err_records[0], 116 }, 117 { 118 .intr_number = PLAT_LUA_CPU0_FAULTIRQ, 119 .err_record = &lua_err_records[0], 120 }, 121 { 122 .intr_number = PLAT_LUA_CPU1_FAULTIRQ, 123 .err_record = &lua_err_records[0], 124 }, 125 { 126 .intr_number = PLAT_LUA_CPU2_FAULTIRQ, 127 .err_record = &lua_err_records[0], 128 }, 129 { 130 .intr_number = PLAT_LUA_CPU3_FAULTIRQ, 131 .err_record = &lua_err_records[0], 132 }, 133 }; 134 REGISTER_RAS_INTERRUPTS(lua_ras_interrupts); 135