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