xref: /arm-trusted-firmware/lib/extensions/ras/std_err_record.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <lib/extensions/ras_arch.h>
8*91f16700Schasinglulu #include <lib/utils_def.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu /*
11*91f16700Schasinglulu  * Probe for error in memory-mapped registers containing error records
12*91f16700Schasinglulu  * implemented Standard Error Record format. Upon detecting an error, set probe
13*91f16700Schasinglulu  * data to the index of the record in error, and return 1; otherwise, return 0.
14*91f16700Schasinglulu  */
15*91f16700Schasinglulu int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data)
16*91f16700Schasinglulu {
17*91f16700Schasinglulu 	unsigned int num_records, num_group_regs, i;
18*91f16700Schasinglulu 	uint64_t gsr;
19*91f16700Schasinglulu 
20*91f16700Schasinglulu 	assert(base != 0UL);
21*91f16700Schasinglulu 
22*91f16700Schasinglulu 	/* Only 4K supported for now */
23*91f16700Schasinglulu 	assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K);
24*91f16700Schasinglulu 
25*91f16700Schasinglulu 	num_records = (unsigned int)
26*91f16700Schasinglulu 		(mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK);
27*91f16700Schasinglulu 
28*91f16700Schasinglulu 	/* A group register shows error status for 2^6 error records */
29*91f16700Schasinglulu 	num_group_regs = (num_records >> 6U) + 1U;
30*91f16700Schasinglulu 
31*91f16700Schasinglulu 	/* Iterate through group registers to find a record in error */
32*91f16700Schasinglulu 	for (i = 0; i < num_group_regs; i++) {
33*91f16700Schasinglulu 		gsr = mmio_read_64(ERR_GSR(base, size_num_k, i));
34*91f16700Schasinglulu 		if (gsr == 0ULL)
35*91f16700Schasinglulu 			continue;
36*91f16700Schasinglulu 
37*91f16700Schasinglulu 		/* Return the index of the record in error */
38*91f16700Schasinglulu 		if (probe_data != NULL)
39*91f16700Schasinglulu 			*probe_data = (((int) (i << 6U)) + __builtin_ctzll(gsr));
40*91f16700Schasinglulu 
41*91f16700Schasinglulu 		return 1;
42*91f16700Schasinglulu 	}
43*91f16700Schasinglulu 
44*91f16700Schasinglulu 	return 0;
45*91f16700Schasinglulu }
46*91f16700Schasinglulu 
47*91f16700Schasinglulu /*
48*91f16700Schasinglulu  * Probe for error in System Registers where error records are implemented in
49*91f16700Schasinglulu  * Standard Error Record format. Upon detecting an error, set probe data to the
50*91f16700Schasinglulu  * index of the record in error, and return 1; otherwise, return 0.
51*91f16700Schasinglulu  */
52*91f16700Schasinglulu int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data)
53*91f16700Schasinglulu {
54*91f16700Schasinglulu 	unsigned int i;
55*91f16700Schasinglulu 	uint64_t status;
56*91f16700Schasinglulu 	unsigned int max_idx __unused =
57*91f16700Schasinglulu 		((unsigned int) read_erridr_el1()) & ERRIDR_MASK;
58*91f16700Schasinglulu 
59*91f16700Schasinglulu 	assert(idx_start < max_idx);
60*91f16700Schasinglulu 	assert(check_u32_overflow(idx_start, num_idx) == 0);
61*91f16700Schasinglulu 	assert((idx_start + num_idx - 1U) < max_idx);
62*91f16700Schasinglulu 
63*91f16700Schasinglulu 	for (i = 0; i < num_idx; i++) {
64*91f16700Schasinglulu 		/* Select the error record */
65*91f16700Schasinglulu 		ser_sys_select_record(idx_start + i);
66*91f16700Schasinglulu 
67*91f16700Schasinglulu 		/* Retrieve status register from the error record */
68*91f16700Schasinglulu 		status = read_erxstatus_el1();
69*91f16700Schasinglulu 
70*91f16700Schasinglulu 		/* Check for valid field in status */
71*91f16700Schasinglulu 		if (ERR_STATUS_GET_FIELD(status, V) != 0U) {
72*91f16700Schasinglulu 			if (probe_data != NULL)
73*91f16700Schasinglulu 				*probe_data = (int) i;
74*91f16700Schasinglulu 			return 1;
75*91f16700Schasinglulu 		}
76*91f16700Schasinglulu 	}
77*91f16700Schasinglulu 
78*91f16700Schasinglulu 	return 0;
79*91f16700Schasinglulu }
80