nrd_ras_cpu.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <string.h>
  8. #include <bl31/interrupt_mgmt.h>
  9. #include <lib/el3_runtime/context_mgmt.h>
  10. #include <lib/extensions/ras.h>
  11. #include <plat/common/platform.h>
  12. #include <services/sdei.h>
  13. #include <services/spm_mm_svc.h>
  14. #include <nrd_ras.h>
  15. #define CPU_CONTEXT_REG_GPR_ARR_SIZE 32
  16. #define CPU_CONTEXT_REG_EL1_ARR_SIZE 17
  17. #define CPU_CONTEXT_REG_EL2_ARR_SIZE 16
  18. #define CPU_CONTEXT_REG_EL3_ARR_SIZE 10
  19. /*
  20. * MM Communicate message header GUID to indicate the payload is intended for
  21. * CPU MM driver.
  22. */
  23. struct efi_guid cpu_ecc_event_guid = {
  24. 0x2c1b3bfc, 0x42cd, 0x4a66,
  25. {0xac, 0xd1, 0xa4, 0xd1, 0x63, 0xe9, 0x90, 0xf6}
  26. };
  27. /*
  28. * CPU error information data structure communicated as part of MM
  29. * Communication data payload.
  30. */
  31. typedef struct {
  32. uint64_t ErrStatus;
  33. uint64_t ErrMisc0;
  34. uint64_t ErrAddr;
  35. uint64_t SecurityState;
  36. uint64_t ErrCtxGpr[CPU_CONTEXT_REG_GPR_ARR_SIZE];
  37. uint64_t ErrCtxEl1Reg[CPU_CONTEXT_REG_EL1_ARR_SIZE];
  38. uint64_t ErrCtxEl2Reg[CPU_CONTEXT_REG_EL2_ARR_SIZE];
  39. uint64_t ErrCtxEl3Reg[CPU_CONTEXT_REG_EL3_ARR_SIZE];
  40. } cpu_err_info;
  41. /*
  42. * Reads the CPU context and error information from the relevant registers and
  43. * populates the CPU error information data structure.
  44. */
  45. static void populate_cpu_err_data(cpu_err_info *cpu_info,
  46. uint64_t security_state)
  47. {
  48. void *ctx;
  49. ctx = cm_get_context(security_state);
  50. cpu_info->ErrStatus = read_erxstatus_el1();
  51. cpu_info->ErrMisc0 = read_erxmisc0_el1();
  52. cpu_info->ErrAddr = read_erxaddr_el1();
  53. cpu_info->SecurityState = security_state;
  54. /* populate CPU EL1 context information. */
  55. cpu_info->ErrCtxEl1Reg[0] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  56. elr_el1);
  57. cpu_info->ErrCtxEl1Reg[1] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  58. esr_el1);
  59. cpu_info->ErrCtxEl1Reg[2] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  60. far_el1);
  61. cpu_info->ErrCtxEl1Reg[3] = read_isr_el1();
  62. cpu_info->ErrCtxEl1Reg[4] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  63. mair_el1);
  64. cpu_info->ErrCtxEl1Reg[5] = read_midr_el1();
  65. cpu_info->ErrCtxEl1Reg[6] = read_mpidr_el1();
  66. cpu_info->ErrCtxEl1Reg[7] = read_ctx_sctlr_el1_reg_errata(ctx);
  67. cpu_info->ErrCtxEl1Reg[8] = read_ctx_reg(get_gpregs_ctx(ctx),
  68. CTX_GPREG_SP_EL0);
  69. cpu_info->ErrCtxEl1Reg[9] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  70. sp_el1);
  71. cpu_info->ErrCtxEl1Reg[10] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  72. spsr_el1);
  73. cpu_info->ErrCtxEl1Reg[11] = read_ctx_tcr_el1_reg_errata(ctx);
  74. cpu_info->ErrCtxEl1Reg[12] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  75. tpidr_el0);
  76. cpu_info->ErrCtxEl1Reg[13] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  77. tpidr_el1);
  78. cpu_info->ErrCtxEl1Reg[14] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  79. tpidrro_el0);
  80. cpu_info->ErrCtxEl1Reg[15] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  81. ttbr0_el1);
  82. cpu_info->ErrCtxEl1Reg[16] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
  83. ttbr1_el1);
  84. #if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
  85. cpu_info->ErrCtxEl2Reg[0] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  86. elr_el2);
  87. cpu_info->ErrCtxEl2Reg[1] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  88. esr_el2);
  89. cpu_info->ErrCtxEl2Reg[2] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  90. far_el2);
  91. cpu_info->ErrCtxEl2Reg[3] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  92. hacr_el2);
  93. cpu_info->ErrCtxEl2Reg[4] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  94. hcr_el2);
  95. cpu_info->ErrCtxEl2Reg[5] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  96. hpfar_el2);
  97. cpu_info->ErrCtxEl2Reg[6] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  98. mair_el2);
  99. cpu_info->ErrCtxEl2Reg[7] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  100. sctlr_el2);
  101. cpu_info->ErrCtxEl2Reg[8] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  102. sp_el2);
  103. cpu_info->ErrCtxEl2Reg[9] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  104. spsr_el2);
  105. cpu_info->ErrCtxEl2Reg[10] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  106. tcr_el2);
  107. cpu_info->ErrCtxEl2Reg[11] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  108. tpidr_el2);
  109. cpu_info->ErrCtxEl2Reg[12] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  110. ttbr0_el2);
  111. cpu_info->ErrCtxEl2Reg[13] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  112. vtcr_el2);
  113. cpu_info->ErrCtxEl2Reg[14] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  114. vttbr_el2);
  115. cpu_info->ErrCtxEl2Reg[15] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
  116. esr_el2);
  117. #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
  118. cpu_info->ErrCtxEl3Reg[0] = read_ctx_reg(get_el3state_ctx(ctx),
  119. CTX_ELR_EL3);
  120. cpu_info->ErrCtxEl3Reg[1] = read_ctx_reg(get_el3state_ctx(ctx),
  121. CTX_ESR_EL3);
  122. cpu_info->ErrCtxEl3Reg[2] = read_far_el3();
  123. cpu_info->ErrCtxEl3Reg[4] = read_mair_el3();
  124. cpu_info->ErrCtxEl3Reg[5] = read_sctlr_el3();
  125. cpu_info->ErrCtxEl3Reg[6] = 0; /* sp_el3 */
  126. cpu_info->ErrCtxEl3Reg[7] = read_tcr_el3();
  127. cpu_info->ErrCtxEl3Reg[8] = read_tpidr_el3();
  128. cpu_info->ErrCtxEl3Reg[9] = read_ttbr0_el3();
  129. }
  130. /* CPU RAS interrupt handler */
  131. int nrd_ras_cpu_intr_handler(const struct err_record_info *err_rec,
  132. int probe_data,
  133. const struct err_handler_data *const data)
  134. {
  135. struct nrd_ras_ev_map *ras_map;
  136. mm_communicate_header_t *header;
  137. cpu_err_info cpu_info = {0};
  138. uint64_t clear_status;
  139. uint32_t intr;
  140. int ret;
  141. cm_el1_sysregs_context_save(NON_SECURE);
  142. intr = data->interrupt;
  143. INFO("[CPU RAS] CPU intr received = %d on cpu_id = %d\n",
  144. intr, plat_my_core_pos());
  145. INFO("[CPU RAS] ERXMISC0_EL1 = 0x%lx\n", read_erxmisc0_el1());
  146. INFO("[CPU RAS] ERXSTATUS_EL1 = 0x%lx\n", read_erxstatus_el1());
  147. INFO("[CPU RAS] ERXADDR_EL1 = 0x%lx\n", read_erxaddr_el1());
  148. /* Populate CPU Error Source Information. */
  149. populate_cpu_err_data(&cpu_info, get_interrupt_src_ss(data->flags));
  150. /* Clear the interrupt. */
  151. clear_status = read_erxstatus_el1();
  152. write_erxstatus_el1(clear_status);
  153. plat_ic_end_of_interrupt(intr);
  154. header = (void *) PLAT_SPM_BUF_BASE;
  155. memset(header, 0, sizeof(*header));
  156. memcpy(&header->data, &cpu_info, sizeof(cpu_info));
  157. header->message_len = sizeof(cpu_info);
  158. memcpy(&header->header_guid, (void *) &cpu_ecc_event_guid,
  159. sizeof(struct efi_guid));
  160. spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
  161. plat_my_core_pos());
  162. /*
  163. * Find if this is a RAS interrupt. There must be an event against
  164. * this interrupt
  165. */
  166. ras_map = nrd_find_ras_event_map_by_intr(intr);
  167. if (ras_map == NULL) {
  168. ERROR("NRD: RAS error info for interrupt id: %d not found\n",
  169. intr);
  170. return -1;
  171. }
  172. /* Dispatch the event to the SDEI client */
  173. ret = sdei_dispatch_event(ras_map->sdei_ev_num);
  174. if (ret != 0) {
  175. /*
  176. * sdei_dispatch_event() may return failing result in some
  177. * cases, for example kernel may not have registered a handler
  178. * or RAS event may happen early during boot. We restore the NS
  179. * context when sdei_dispatch_event() returns failing result.
  180. */
  181. ERROR("SDEI dispatch failed: %d", ret);
  182. cm_el1_sysregs_context_restore(NON_SECURE);
  183. cm_set_next_eret_context(NON_SECURE);
  184. }
  185. return ret;
  186. }