nrd_ras_sram.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <bl31/interrupt_mgmt.h>
  7. #include <lib/el3_runtime/context_mgmt.h>
  8. #include <plat/common/platform.h>
  9. #include <services/sdei.h>
  10. #include <services/spm_mm_svc.h>
  11. #include <platform_def.h>
  12. #include <nrd_ras.h>
  13. /* Base Element RAM Error Record offsets. */
  14. #define ERRSTATUS U(0)
  15. #define ERRCODE U(8)
  16. #define ERRADDR U(12)
  17. /*
  18. * Base Element RAM error information data structure communicated as part of MM
  19. * Communication data payload.
  20. */
  21. typedef struct nrd_sram_err_info {
  22. uint32_t err_status;
  23. uint32_t err_code;
  24. uint32_t err_addr;
  25. } nrd_sram_err_info_t;
  26. /*
  27. * MM Communicate message header GUID to indicate the payload is intended for
  28. * base element RAM MM driver.
  29. */
  30. struct efi_guid sram_ecc_event_guid = {
  31. 0x7312db4f, 0xd0c4, 0x4fb5,
  32. { 0x81, 0x2c, 0xb7, 0x4b, 0xc6, 0xc4, 0xa9, 0x38 }
  33. };
  34. /* Base element RAM RAS error interrupt handler */
  35. int nrd_ras_sram_intr_handler(const struct err_record_info *err_rec,
  36. int probe_data,
  37. const struct err_handler_data *const data)
  38. {
  39. struct nrd_ras_ev_map *ras_map;
  40. mm_communicate_header_t *header;
  41. nrd_sram_err_info_t sram_info;
  42. uintptr_t base_addr;
  43. uint32_t clear_status, intr;
  44. int ret;
  45. cm_el1_sysregs_context_save(NON_SECURE);
  46. intr = data->interrupt;
  47. INFO("NRD: Base element RAM interrupt [%d] handler\n", intr);
  48. /* Determine error record base address to read. */
  49. base_addr = 0;
  50. if (intr == NRD_CSS_NS_RAM_ECC_CE_INT ||
  51. intr == NRD_CSS_NS_RAM_ECC_UE_INT) {
  52. base_addr = NRD_CSS_NS_RAM_ERR_REC_BASE;
  53. }
  54. sram_info.err_status = mmio_read_32(base_addr + ERRSTATUS);
  55. sram_info.err_code = mmio_read_32(base_addr + ERRCODE);
  56. sram_info.err_addr = mmio_read_32(base_addr + ERRADDR);
  57. /* Clear the interrupt. */
  58. clear_status = mmio_read_32(base_addr + ERRSTATUS);
  59. mmio_write_32((base_addr + ERRSTATUS), clear_status);
  60. /*
  61. * Prepare the MM Communication buffer to pass the base element RAM
  62. * error information to Secure Partition.
  63. */
  64. header = (void *)PLAT_SPM_BUF_BASE;
  65. memset(header, 0, sizeof(*header));
  66. memcpy(&header->data, &sram_info, sizeof(sram_info));
  67. header->message_len = sizeof(sram_info);
  68. memcpy(&header->header_guid, (void *)&sram_ecc_event_guid,
  69. sizeof(struct efi_guid));
  70. spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
  71. plat_my_core_pos());
  72. plat_ic_end_of_interrupt(intr);
  73. /*
  74. * Find if this is a RAS interrupt. There must be an event against
  75. * this interrupt
  76. */
  77. ras_map = nrd_find_ras_event_map_by_intr(intr);
  78. if (ras_map == NULL) {
  79. ERROR("NRD: RAS error info for interrupt id: %d not found\n",
  80. intr);
  81. return -1;
  82. }
  83. /* Dispatch the event to the SDEI client */
  84. ret = sdei_dispatch_event(ras_map->sdei_ev_num);
  85. if (ret != 0) {
  86. /*
  87. * sdei_dispatch_event() may return failing result in some
  88. * cases, for example kernel may not have registered a handler
  89. * or RAS event may happen early during boot. We restore the NS
  90. * context when sdei_dispatch_event() returns failing result.
  91. */
  92. ERROR("SDEI dispatch failed: %d", ret);
  93. cm_el1_sysregs_context_restore(NON_SECURE);
  94. cm_set_next_eret_context(NON_SECURE);
  95. }
  96. return ret;
  97. }