aboutsummaryrefslogtreecommitdiffstats
path: root/include/lib/extensions
diff options
context:
space:
mode:
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>2017-12-07 08:43:05 +0000
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>2018-05-04 08:33:17 +0100
commit30d81c36da441bcd0fbccbc3ac1a7268d2cc5ad2 (patch)
tree4834b91958ace9dfd61d7776de15f6bd737ba6a3 /include/lib/extensions
parent14c6016ad5ff4ac22861dff03129a646ad02c6dd (diff)
downloadplatform_external_arm-trusted-firmware-30d81c36da441bcd0fbccbc3ac1a7268d2cc5ad2.tar.gz
platform_external_arm-trusted-firmware-30d81c36da441bcd0fbccbc3ac1a7268d2cc5ad2.tar.bz2
platform_external_arm-trusted-firmware-30d81c36da441bcd0fbccbc3ac1a7268d2cc5ad2.zip
RAS: Add helpers to access Standard Error Records
The ARMv8 RAS Extensions introduced Standard Error Records which are a set of standard registers through which: - Platform can configure RAS node policy; e.g., notification mechanism; - RAS nodes can record and expose error information for error handling agents. Standard Error Records can either be accessed via. memory-mapped or System registers. This patch adds helper functions to access registers and fields within an error record. Change-Id: I6594ba799f4a1789d7b1e45b3e17fd40e7e0ba5c Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Diffstat (limited to 'include/lib/extensions')
-rw-r--r--include/lib/extensions/ras_arch.h225
1 files changed, 225 insertions, 0 deletions
diff --git a/include/lib/extensions/ras_arch.h b/include/lib/extensions/ras_arch.h
new file mode 100644
index 000000000..7d210531b
--- /dev/null
+++ b/include/lib/extensions/ras_arch.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __RAS_H__
+#define __RAS_H__
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <context.h>
+#include <mmio.h>
+#include <stdint.h>
+
+/*
+ * Size of nodes implementing Standard Error Records - currently only 4k is
+ * supported.
+ */
+#define STD_ERR_NODE_SIZE_NUM_K 4
+
+/*
+ * Individual register offsets within an error record in Standard Error Record
+ * format when error records are accessed through memory-mapped registers.
+ */
+#define ERR_FR(n) (0x0 + (64 * (n)))
+#define ERR_CTLR(n) (0x8 + (64 * (n)))
+#define ERR_STATUS(n) (0x10 + (64 * (n)))
+#define ERR_ADDR(n) (0x18 + (64 * (n)))
+#define ERR_MISC0(n) (0x20 + (64 * (n)))
+#define ERR_MISC1(n) (0x28 + (64 * (n)))
+
+/* Group Status Register (ERR_STATUS) offset */
+#define ERR_GSR(base, size_num_k, n) \
+ ((base) + (0x380 * (size_num_k)) + (8 * (n)))
+
+/* Management register offsets */
+#define ERR_DEVID(base, size_num_k) \
+ ((base) + ((0x400 * (size_num_k)) - 0x100) + 0xc8)
+
+#define ERR_DEVID_MASK 0xffff
+
+/* Standard Error Record status register fields */
+#define ERR_STATUS_AV_SHIFT 31
+#define ERR_STATUS_AV_MASK U(0x1)
+
+#define ERR_STATUS_V_SHIFT 30
+#define ERR_STATUS_V_MASK U(0x1)
+
+#define ERR_STATUS_UE_SHIFT 29
+#define ERR_STATUS_UE_MASK U(0x1)
+
+#define ERR_STATUS_ER_SHIFT 28
+#define ERR_STATUS_ER_MASK U(0x1)
+
+#define ERR_STATUS_OF_SHIFT 27
+#define ERR_STATUS_OF_MASK U(0x1)
+
+#define ERR_STATUS_MV_SHIFT 26
+#define ERR_STATUS_MV_MASK U(0x1)
+
+#define ERR_STATUS_CE_SHIFT 24
+#define ERR_STATUS_CE_MASK U(0x3)
+
+#define ERR_STATUS_DE_SHIFT 23
+#define ERR_STATUS_DE_MASK U(0x1)
+
+#define ERR_STATUS_PN_SHIFT 22
+#define ERR_STATUS_PN_MASK U(0x1)
+
+#define ERR_STATUS_UET_SHIFT 20
+#define ERR_STATUS_UET_MASK U(0x3)
+
+#define ERR_STATUS_IERR_SHIFT 8
+#define ERR_STATUS_IERR_MASK U(0xff)
+
+#define ERR_STATUS_SERR_SHIFT 0
+#define ERR_STATUS_SERR_MASK U(0xff)
+
+#define ERR_STATUS_GET_FIELD(_status, _field) \
+ (((_status) >> ERR_STATUS_ ##_field ##_SHIFT) & ERR_STATUS_ ##_field ##_MASK)
+
+#define ERR_STATUS_CLR_FIELD(_status, _field) \
+ (_status) &= ~(ERR_STATUS_ ##_field ##_MASK << ERR_STATUS_ ##_field ##_SHIFT)
+
+#define ERR_STATUS_SET_FIELD(_status, _field, _value) \
+ (_status) |= (((_value) & ERR_STATUS_ ##_field ##_MASK) << ERR_STATUS_ ##_field ##_SHIFT)
+
+#define ERR_STATUS_WRITE_FIELD(_status, _field, _value) do { \
+ ERR_STATUS_CLR_FIELD(_status, _field, _value); \
+ ERR_STATUS_SET_FIELD(_status, _field, _value); \
+ } while (0)
+
+
+/* Standard Error Record control register fields */
+#define ERR_CTLR_WDUI_SHIFT 11
+#define ERR_CTLR_WDUI_MASK 0x1
+
+#define ERR_CTLR_RDUI_SHIFT 10
+#define ERR_CTLR_RDUI_MASK 0x1
+#define ERR_CTLR_DUI_SHIFT ERR_CTLR_RDUI_SHIFT
+#define ERR_CTLR_DUI_MASK ERR_CTLR_RDUI_MASK
+
+#define ERR_CTLR_WCFI_SHIFT 9
+#define ERR_CTLR_WCFI_MASK 0x1
+
+#define ERR_CTLR_RCFI_SHIFT 8
+#define ERR_CTLR_RCFI_MASK 0x1
+#define ERR_CTLR_CFI_SHIFT ERR_CTLR_RCFI_SHIFT
+#define ERR_CTLR_CFI_MASK ERR_CTLR_RCFI_MASK
+
+#define ERR_CTLR_WUE_SHIFT 7
+#define ERR_CTLR_WUE_MASK 0x1
+
+#define ERR_CTLR_WFI_SHIFT 6
+#define ERR_CTLR_WFI_MASK 0x1
+
+#define ERR_CTLR_WUI_SHIFT 5
+#define ERR_CTLR_WUI_MASK 0x1
+
+#define ERR_CTLR_RUE_SHIFT 4
+#define ERR_CTLR_RUE_MASK 0x1
+#define ERR_CTLR_UE_SHIFT ERR_CTLR_RUE_SHIFT
+#define ERR_CTLR_UE_MASK ERR_CTLR_RUE_MASK
+
+#define ERR_CTLR_RFI_SHIFT 3
+#define ERR_CTLR_RFI_MASK 0x1
+#define ERR_CTLR_FI_SHIFT ERR_CTLR_RFI_SHIFT
+#define ERR_CTLR_FI_MASK ERR_CTLR_RFI_MASK
+
+#define ERR_CTLR_RUI_SHIFT 2
+#define ERR_CTLR_RUI_MASK 0x1
+#define ERR_CTLR_UI_SHIFT ERR_CTLR_RUI_SHIFT
+#define ERR_CTLR_UI_MASK ERR_CTLR_RUI_MASK
+
+#define ERR_CTLR_ED_SHIFT 0
+#define ERR_CTLR_ED_MASK 0x1
+
+#define ERR_CTLR_CLR_FIELD(_ctlr, _field) \
+ (_ctlr) &= ~(ERR_CTLR_ ##_field _MASK << ERR_CTLR_ ##_field ##_SHIFT)
+
+#define ERR_CTLR_SET_FIELD(_ctlr, _field, _value) \
+ (_ctlr) |= (((_value) & ERR_CTLR_ ##_field ##_MASK) << ERR_CTLR_ ##_field ##_SHIFT)
+
+#define ERR_CTLR_ENABLE_FIELD(_ctlr, _field) \
+ ERR_CTLR_SET_FIELD(_ctlr, _field, ERR_CTLR_ ##_field ##_MASK)
+
+/* Uncorrected error types */
+#define ERROR_STATUS_UET_UC 0x0 /* Uncontainable */
+#define ERROR_STATUS_UET_UEU 0x1 /* Unrecoverable */
+#define ERROR_STATUS_UET_UEO 0x2 /* Restable */
+#define ERROR_STATUS_UET_UER 0x3 /* Recoverable */
+
+
+/*
+ * Standard Error Record accessors for memory-mapped registers.
+ */
+
+static inline uint64_t ser_get_feature(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_FR(idx));
+}
+
+static inline uint64_t ser_get_control(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_CTLR(idx));
+}
+
+static inline uint64_t ser_get_status(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_STATUS(idx));
+}
+
+/*
+ * Error handling agent would write to the status register to clear an
+ * identified/handled error. Most fields in the status register are
+ * conditional write-one-to-clear.
+ *
+ * Typically, to clear the status, it suffices to write back the same value
+ * previously read. However, if there were new, higher-priority errors recorded
+ * on the node since status was last read, writing read value won't clear the
+ * status. Therefore, an error handling agent must wait on and verify the status
+ * has indeed been cleared.
+ */
+static inline void ser_set_status(uintptr_t base, unsigned int idx,
+ uint64_t status)
+{
+ mmio_write_64(base + ERR_STATUS(idx), status);
+}
+
+static inline uint64_t ser_get_addr(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_ADDR(idx));
+}
+
+static inline uint64_t ser_get_misc0(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_MISC0(idx));
+}
+
+static inline uint64_t ser_get_misc1(uintptr_t base, unsigned int idx)
+{
+ return mmio_read_64(base + ERR_MISC1(idx));
+}
+
+
+/*
+ * Standard Error Record helpers for System registers.
+ */
+static inline void ser_sys_select_record(unsigned int idx)
+{
+ unsigned int max_idx __unused = read_erridr_el1() & ERRIDR_MASK;
+
+ assert(idx < max_idx);
+
+ write_errselr_el1(idx);
+ isb();
+}
+
+/* Library functions to probe Standard Error Record */
+int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data);
+int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data);
+
+#endif /* __RAS_H__ */