130d81c36SJeenu Viswambharan /*
2*4c700c15SGovindraj Raja * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
330d81c36SJeenu Viswambharan *
430d81c36SJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause
530d81c36SJeenu Viswambharan */
609d40e0eSAntonio Nino Diaz
709d40e0eSAntonio Nino Diaz #include <lib/extensions/ras_arch.h>
809d40e0eSAntonio Nino Diaz #include <lib/utils_def.h>
930d81c36SJeenu Viswambharan
1030d81c36SJeenu Viswambharan /*
1130d81c36SJeenu Viswambharan * Probe for error in memory-mapped registers containing error records
1230d81c36SJeenu Viswambharan * implemented Standard Error Record format. Upon detecting an error, set probe
1330d81c36SJeenu Viswambharan * data to the index of the record in error, and return 1; otherwise, return 0.
1430d81c36SJeenu Viswambharan */
ser_probe_memmap(uintptr_t base,unsigned int size_num_k,int * probe_data)1530d81c36SJeenu Viswambharan int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data)
1630d81c36SJeenu Viswambharan {
1730a8d96eSJeenu Viswambharan unsigned int num_records, num_group_regs, i;
1830d81c36SJeenu Viswambharan uint64_t gsr;
1930d81c36SJeenu Viswambharan
2030a8d96eSJeenu Viswambharan assert(base != 0UL);
2130d81c36SJeenu Viswambharan
2230d81c36SJeenu Viswambharan /* Only 4K supported for now */
2330d81c36SJeenu Viswambharan assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K);
2430d81c36SJeenu Viswambharan
2530a8d96eSJeenu Viswambharan num_records = (unsigned int)
2630a8d96eSJeenu Viswambharan (mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK);
2730d81c36SJeenu Viswambharan
2830d81c36SJeenu Viswambharan /* A group register shows error status for 2^6 error records */
2930a8d96eSJeenu Viswambharan num_group_regs = (num_records >> 6U) + 1U;
3030d81c36SJeenu Viswambharan
3130d81c36SJeenu Viswambharan /* Iterate through group registers to find a record in error */
3230d81c36SJeenu Viswambharan for (i = 0; i < num_group_regs; i++) {
3330d81c36SJeenu Viswambharan gsr = mmio_read_64(ERR_GSR(base, size_num_k, i));
3430a8d96eSJeenu Viswambharan if (gsr == 0ULL)
3530d81c36SJeenu Viswambharan continue;
3630d81c36SJeenu Viswambharan
3730d81c36SJeenu Viswambharan /* Return the index of the record in error */
3830d81c36SJeenu Viswambharan if (probe_data != NULL)
3930a8d96eSJeenu Viswambharan *probe_data = (((int) (i << 6U)) + __builtin_ctzll(gsr));
4030d81c36SJeenu Viswambharan
4130d81c36SJeenu Viswambharan return 1;
4230d81c36SJeenu Viswambharan }
4330d81c36SJeenu Viswambharan
4430d81c36SJeenu Viswambharan return 0;
4530d81c36SJeenu Viswambharan }
4630d81c36SJeenu Viswambharan
4730d81c36SJeenu Viswambharan /*
4830d81c36SJeenu Viswambharan * Probe for error in System Registers where error records are implemented in
4930d81c36SJeenu Viswambharan * Standard Error Record format. Upon detecting an error, set probe data to the
5030d81c36SJeenu Viswambharan * index of the record in error, and return 1; otherwise, return 0.
5130d81c36SJeenu Viswambharan */
ser_probe_sysreg(unsigned int idx_start,unsigned int num_idx,int * probe_data)5230d81c36SJeenu Viswambharan int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data)
5330d81c36SJeenu Viswambharan {
5430a8d96eSJeenu Viswambharan unsigned int i;
5530d81c36SJeenu Viswambharan uint64_t status;
5630a8d96eSJeenu Viswambharan unsigned int max_idx __unused =
5730a8d96eSJeenu Viswambharan ((unsigned int) read_erridr_el1()) & ERRIDR_MASK;
5830d81c36SJeenu Viswambharan
5930d81c36SJeenu Viswambharan assert(idx_start < max_idx);
60ca9ffc79SJeenu Viswambharan assert(check_u32_overflow(idx_start, num_idx) == 0);
6130a8d96eSJeenu Viswambharan assert((idx_start + num_idx - 1U) < max_idx);
6230d81c36SJeenu Viswambharan
6330d81c36SJeenu Viswambharan for (i = 0; i < num_idx; i++) {
6430d81c36SJeenu Viswambharan /* Select the error record */
6530d81c36SJeenu Viswambharan ser_sys_select_record(idx_start + i);
6630d81c36SJeenu Viswambharan
6730d81c36SJeenu Viswambharan /* Retrieve status register from the error record */
6830d81c36SJeenu Viswambharan status = read_erxstatus_el1();
6930d81c36SJeenu Viswambharan
7030d81c36SJeenu Viswambharan /* Check for valid field in status */
7130a8d96eSJeenu Viswambharan if (ERR_STATUS_GET_FIELD(status, V) != 0U) {
7230d81c36SJeenu Viswambharan if (probe_data != NULL)
7330a8d96eSJeenu Viswambharan *probe_data = (int) i;
7430d81c36SJeenu Viswambharan return 1;
7530d81c36SJeenu Viswambharan }
7630d81c36SJeenu Viswambharan }
7730d81c36SJeenu Viswambharan
7830d81c36SJeenu Viswambharan return 0;
7930d81c36SJeenu Viswambharan }
80