blob: 9fdfd6b60f20b15b3799d56396bced1a04d255bf [file] [log] [blame]
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +00001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <ras_arch.h>
7#include <utils_def.h>
8
9/*
10 * Probe for error in memory-mapped registers containing error records
11 * implemented Standard Error Record format. Upon detecting an error, set probe
12 * data to the index of the record in error, and return 1; otherwise, return 0.
13 */
14int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data)
15{
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010016 unsigned int num_records, num_group_regs, i;
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000017 uint64_t gsr;
18
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010019 assert(base != 0UL);
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000020
21 /* Only 4K supported for now */
22 assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K);
23
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010024 num_records = (unsigned int)
25 (mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK);
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000026
27 /* A group register shows error status for 2^6 error records */
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010028 num_group_regs = (num_records >> 6U) + 1U;
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000029
30 /* Iterate through group registers to find a record in error */
31 for (i = 0; i < num_group_regs; i++) {
32 gsr = mmio_read_64(ERR_GSR(base, size_num_k, i));
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010033 if (gsr == 0ULL)
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000034 continue;
35
36 /* Return the index of the record in error */
37 if (probe_data != NULL)
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010038 *probe_data = (((int) (i << 6U)) + __builtin_ctzll(gsr));
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000039
40 return 1;
41 }
42
43 return 0;
44}
45
46/*
47 * Probe for error in System Registers where error records are implemented in
48 * Standard Error Record format. Upon detecting an error, set probe data to the
49 * index of the record in error, and return 1; otherwise, return 0.
50 */
51int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data)
52{
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010053 unsigned int i;
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000054 uint64_t status;
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010055 unsigned int max_idx __unused =
56 ((unsigned int) read_erridr_el1()) & ERRIDR_MASK;
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000057
58 assert(idx_start < max_idx);
Jeenu Viswambharan067a3572018-09-07 16:30:58 +010059 assert(check_u32_overflow(idx_start, num_idx) == 0);
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010060 assert((idx_start + num_idx - 1U) < max_idx);
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000061
62 for (i = 0; i < num_idx; i++) {
63 /* Select the error record */
64 ser_sys_select_record(idx_start + i);
65
66 /* Retrieve status register from the error record */
67 status = read_erxstatus_el1();
68
69 /* Check for valid field in status */
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010070 if (ERR_STATUS_GET_FIELD(status, V) != 0U) {
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000071 if (probe_data != NULL)
Jeenu Viswambharan31ac01e2018-08-02 10:14:12 +010072 *probe_data = (int) i;
Jeenu Viswambharan19f6cf22017-12-07 08:43:05 +000073 return 1;
74 }
75 }
76
77 return 0;
78}