Browse Source
This patch adds the errata management firmware interface for lower ELs to discover details about CPU erratum. Based on the CPU erratum identifier the interface enables the OS to find the mitigation of an erratum in EL3. The ABI can only be present in a system that is compliant with SMCCCv1.1 or higher. This implements v1.0 of the errata ABI spec. For details on all possible return values, refer the design documentation below: ABI design documentation: https://developer.arm.com/documentation/den0100/1-0?lang=en Signed-off-by: Sona Mathew <SonaRebecca.Mathew@arm.com> Change-Id: I70f0e2569cf92e6e02ad82e3e77874546232b89apull/1982/merge
Sona Mathew
2 years ago
10 changed files with 669 additions and 2 deletions
@ -0,0 +1,48 @@ |
|||
/*
|
|||
* Copyright (c) 2023, Arm Limited. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef ERRATA_ABI_SVC_H |
|||
#define ERRATA_ABI_SVC_H |
|||
|
|||
#include <lib/smccc.h> |
|||
|
|||
#define ARM_EM_VERSION U(0x840000F0) |
|||
#define ARM_EM_FEATURES U(0x840000F1) |
|||
#define ARM_EM_CPU_ERRATUM_FEATURES U(0x840000F2) |
|||
|
|||
/* EM version numbers */ |
|||
#define EM_VERSION_MAJOR (0x1) |
|||
#define EM_VERSION_MINOR (0x0) |
|||
|
|||
/* EM CPU_ERRATUM_FEATURES return codes */ |
|||
#define EM_HIGHER_EL_MITIGATION (3) |
|||
#define EM_NOT_AFFECTED (2) |
|||
#define EM_AFFECTED (1) |
|||
#define EM_SUCCESS (0) |
|||
#define EM_NOT_SUPPORTED (-1) |
|||
#define EM_INVALID_PARAMETERS (-2) |
|||
#define EM_UNKNOWN_ERRATUM (-3) |
|||
|
|||
#if ERRATA_ABI_SUPPORT |
|||
bool is_errata_fid(uint32_t smc_fid); |
|||
#else |
|||
static inline bool is_errata_fid(uint32_t smc_fid) |
|||
{ |
|||
return false; |
|||
} |
|||
#endif /* ERRATA_ABI_SUPPORT */ |
|||
uintptr_t errata_abi_smc_handler( |
|||
uint32_t smc_fid, |
|||
u_register_t x1, |
|||
u_register_t x2, |
|||
u_register_t x3, |
|||
u_register_t x4, |
|||
void *cookie, |
|||
void *handle, |
|||
u_register_t flags |
|||
); |
|||
#endif /* ERRATA_ABI_SVC_H */ |
|||
|
@ -0,0 +1,70 @@ |
|||
/*
|
|||
* Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef ERRATA_CPUSPEC_H |
|||
#define ERRATA_CPUSPEC_H |
|||
|
|||
#include <stdint.h> |
|||
#include <arch_helpers.h> |
|||
|
|||
#if __aarch64__ |
|||
#include <cortex_a35.h> |
|||
#include <cortex_a510.h> |
|||
#include <cortex_a53.h> |
|||
#include <cortex_a57.h> |
|||
#include <cortex_a55.h> |
|||
#include <cortex_a710.h> |
|||
#include <cortex_a72.h> |
|||
#include <cortex_a73.h> |
|||
#include <cortex_a75.h> |
|||
#include <cortex_a76.h> |
|||
#include <cortex_a77.h> |
|||
#include <cortex_a78.h> |
|||
#include <cortex_a78_ae.h> |
|||
#include <cortex_a78c.h> |
|||
#include <cortex_makalu.h> |
|||
#include <cortex_x1.h> |
|||
#include <cortex_x2.h> |
|||
#include <neoverse_n1.h> |
|||
#include <neoverse_n2.h> |
|||
#include <neoverse_v1.h> |
|||
#include <neoverse_v2.h> |
|||
#else |
|||
#include <cortex_a15.h> |
|||
#include <cortex_a17.h> |
|||
#include <cortex_a57.h> |
|||
#include <cortex_a9.h> |
|||
#endif |
|||
|
|||
#define MAX_ERRATA_ENTRIES 15 |
|||
|
|||
#define ERRATA_LIST_END (MAX_ERRATA_ENTRIES - 1) |
|||
|
|||
#define UNDEF_ERRATA {UINT_MAX, UCHAR_MAX, UCHAR_MAX, false} |
|||
|
|||
#define EXTRACT_PARTNUM(x) ((x >> MIDR_PN_SHIFT) & MIDR_PN_MASK) |
|||
|
|||
#define RXPX_RANGE(x, y, z) (((x >= y) && (x <= z)) ? true : false) |
|||
|
|||
/*
|
|||
* CPU specific values for errata handling |
|||
*/ |
|||
|
|||
struct em_cpu{ |
|||
unsigned int em_errata_id; |
|||
unsigned char em_rxpx_lo; /* lowest revision of errata applicable for the cpu */ |
|||
unsigned char em_rxpx_hi; /* highest revision of errata applicable for the cpu */ |
|||
bool errata_enabled; /* indicate if errata enabled */ |
|||
}; |
|||
|
|||
struct em_cpu_list{ |
|||
/* field to hold cpu specific part number defined in midr reg */ |
|||
unsigned long cpu_partnumber; |
|||
struct em_cpu cpu_errata_list[MAX_ERRATA_ENTRIES]; |
|||
}; |
|||
|
|||
int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag); |
|||
#endif /* ERRATA_CPUSPEC_H */ |
@ -0,0 +1,523 @@ |
|||
/*
|
|||
* Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <assert.h> |
|||
#include "cpu_errata_info.h" |
|||
#include <lib/smccc.h> |
|||
#include <lib/utils_def.h> |
|||
#include <services/errata_abi_svc.h> |
|||
#include <smccc_helpers.h> |
|||
|
|||
/*
|
|||
* Global pointer that points to the specific |
|||
* structure based on the MIDR part number |
|||
*/ |
|||
struct em_cpu_list *cpu_ptr; |
|||
|
|||
extern uint8_t cpu_get_rev_var(void); |
|||
|
|||
/* Structure array that holds CPU specific errata information */ |
|||
struct em_cpu_list cpu_list[] = { |
|||
#if CORTEX_A9_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A9_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {794073, 0x00, 0xFF, ERRATA_A9_794073}, |
|||
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A9_H_INC */ |
|||
|
|||
#if CORTEX_A15_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A15_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {816470, 0x30, 0xFF, ERRATA_A15_816470}, |
|||
[1] = {827671, 0x30, 0xFF, ERRATA_A15_827671}, |
|||
[2 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A15_H_INC */ |
|||
|
|||
#if CORTEX_A17_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A17_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {852421, 0x00, 0x12, ERRATA_A17_852421}, |
|||
[1] = {852423, 0x00, 0x12, ERRATA_A17_852423}, |
|||
[2 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A17_H_INC */ |
|||
|
|||
#if CORTEX_A35_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A35_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {855472, 0x00, 0x00, ERRATA_A35_855472}, |
|||
[1 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A35_H_INC */ |
|||
|
|||
#if CORTEX_A53_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A53_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {819472, 0x00, 0x01, ERRATA_A53_819472}, |
|||
[1] = {824069, 0x00, 0x02, ERRATA_A53_824069}, |
|||
[2] = {826319, 0x00, 0x02, ERRATA_A53_826319}, |
|||
[3] = {827319, 0x00, 0x02, ERRATA_A53_827319}, |
|||
[4] = {835769, 0x00, 0x04, ERRATA_A53_835769}, |
|||
[5] = {836870, 0x00, 0x03, ERRATA_A53_836870}, |
|||
[6] = {843419, 0x00, 0x04, ERRATA_A53_843419}, |
|||
[7] = {855873, 0x03, 0xFF, ERRATA_A53_855873}, |
|||
[8] = {1530924, 0x00, 0xFF, ERRATA_A53_1530924}, |
|||
[9 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A53_H_INC */ |
|||
|
|||
#if CORTEX_A55_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A55_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {768277, 0x00, 0x00, ERRATA_A55_768277}, |
|||
[1] = {778703, 0x00, 0x00, ERRATA_A55_778703}, |
|||
[2] = {798797, 0x00, 0x00, ERRATA_A55_798797}, |
|||
[3] = {846532, 0x00, 0x01, ERRATA_A55_846532}, |
|||
[4] = {903758, 0x00, 0x01, ERRATA_A55_903758}, |
|||
[5] = {1221012, 0x00, 0x10, ERRATA_A55_1221012}, |
|||
[6] = {1530923, 0x00, 0xFF, ERRATA_A55_1530923}, |
|||
[7 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A55_H_INC */ |
|||
|
|||
#if CORTEX_A57_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A57_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {806969, 0x00, 0x00, ERRATA_A57_806969}, |
|||
[1] = {813419, 0x00, 0x00, ERRATA_A57_813419}, |
|||
[2] = {813420, 0x00, 0x00, ERRATA_A57_813420}, |
|||
[3] = {814670, 0x00, 0x00, ERRATA_A57_814670}, |
|||
[4] = {817169, 0x00, 0x01, ERRATA_A57_817169}, |
|||
[5] = {826974, 0x00, 0x11, ERRATA_A57_826974}, |
|||
[6] = {826977, 0x00, 0x11, ERRATA_A57_826977}, |
|||
[7] = {828024, 0x00, 0x11, ERRATA_A57_828024}, |
|||
[8] = {829520, 0x00, 0x12, ERRATA_A57_829520}, |
|||
[9] = {833471, 0x00, 0x12, ERRATA_A57_833471}, |
|||
[10] = {859972, 0x00, 0x13, ERRATA_A57_859972}, |
|||
[11] = {1319537, 0x00, 0xFF, ERRATA_A57_1319537}, |
|||
[12 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A57_H_INC */ |
|||
|
|||
#if CORTEX_A72_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A72_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {859971, 0x00, 0x03, ERRATA_A72_859971}, |
|||
[1] = {1319367, 0x00, 0xFF, ERRATA_A72_1319367}, |
|||
[2 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A72_H_INC */ |
|||
|
|||
#if CORTEX_A73_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A73_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {852427, 0x00, 0x00, ERRATA_A73_852427}, |
|||
[1] = {855423, 0x00, 0x01, ERRATA_A73_855423}, |
|||
[2 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A73_H_INC */ |
|||
|
|||
#if CORTEX_A75_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A75_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {764081, 0x00, 0x00, ERRATA_A75_764081}, |
|||
[1] = {790748, 0x00, 0x00, ERRATA_A75_790748}, |
|||
[2 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A75_H_INC */ |
|||
|
|||
#if CORTEX_A76_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A76_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1073348, 0x00, 0x10, ERRATA_A76_1073348}, |
|||
[1] = {1130799, 0x00, 0x20, ERRATA_A76_1130799}, |
|||
[2] = {1165522, 0x00, 0xFF, ERRATA_A76_1165522}, |
|||
[3] = {1220197, 0x00, 0x20, ERRATA_A76_1220197}, |
|||
[4] = {1257314, 0x00, 0x30, ERRATA_A76_1257314}, |
|||
[5] = {1262606, 0x00, 0x30, ERRATA_A76_1262606}, |
|||
[6] = {1262888, 0x00, 0x30, ERRATA_A76_1262888}, |
|||
[7] = {1275112, 0x00, 0x30, ERRATA_A76_1275112}, |
|||
[8] = {1791580, 0x00, 0x40, ERRATA_A76_1791580}, |
|||
[9] = {1868343, 0x00, 0x40, ERRATA_A76_1868343}, |
|||
[10] = {1946160, 0x30, 0x41, ERRATA_A76_1946160}, |
|||
[11 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A76_H_INC */ |
|||
|
|||
#if CORTEX_A77_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A77_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1508412, 0x00, 0x10, ERRATA_A77_1508412}, |
|||
[1] = {1791578, 0x00, 0x11, ERRATA_A77_1791578}, |
|||
[2] = {1800714, 0x00, 0x11, ERRATA_A77_1800714}, |
|||
[3] = {1925769, 0x00, 0x11, ERRATA_A77_1925769}, |
|||
[4] = {1946167, 0x00, 0x11, ERRATA_A77_1946167}, |
|||
[5] = {2356587, 0x00, 0x11, ERRATA_A77_2356587}, |
|||
[6] = {2743100, 0x00, 0x11, ERRATA_A77_2743100}, |
|||
[7 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A77_H_INC */ |
|||
|
|||
#if CORTEX_A78_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A78_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1688305, 0x00, 0x10, ERRATA_A78_1688305}, |
|||
[1] = {1821534, 0x00, 0x10, ERRATA_A78_1821534}, |
|||
[2] = {1941498, 0x00, 0x11, ERRATA_A78_1941498}, |
|||
[3] = {1951500, 0x10, 0x11, ERRATA_A78_1951500}, |
|||
[4] = {1952683, 0x00, 0x00, ERRATA_A78_1952683}, |
|||
[5] = {2132060, 0x00, 0x12, ERRATA_A78_2132060}, |
|||
[6] = {2242635, 0x10, 0x12, ERRATA_A78_2242635}, |
|||
[7] = {2376745, 0x00, 0x12, ERRATA_A78_2376745}, |
|||
[8] = {2395406, 0x00, 0x12, ERRATA_A78_2395406}, |
|||
[9] = {2742426, 0x00, 0x12, ERRATA_A78_2742426}, |
|||
[10] = {2772019, 0x00, 0x12, ERRATA_A78_2772019}, |
|||
[11] = {2779479, 0x00, 0x12, ERRATA_A78_2779479}, |
|||
[12 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A78_H_INC */ |
|||
|
|||
#if CORTEX_A78_AE_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A78_AE_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1941500, 0x00, 0x01, ERRATA_A78_AE_1941500}, |
|||
[1] = {1951502, 0x00, 0x01, ERRATA_A78_AE_1951502}, |
|||
[2] = {2376748, 0x00, 0x01, ERRATA_A78_AE_2376748}, |
|||
[3] = {2395408, 0x00, 0x01, ERRATA_A78_AE_2395408}, |
|||
[4 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A78_AE_H_INC */ |
|||
|
|||
#if CORTEX_A78C_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A78C_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {2132064, 0x01, 0x02, ERRATA_A78C_2132064}, |
|||
[1] = {2242638, 0x01, 0x02, ERRATA_A78C_2242638}, |
|||
[2] = {2376749, 0x01, 0x02, ERRATA_A78C_2376749}, |
|||
[3] = {2395411, 0x01, 0x02, ERRATA_A78C_2395411}, |
|||
[4] = {2772121, 0x00, 0x02, ERRATA_A78C_2772121}, |
|||
[5] = {2779484, 0x01, 0x02, ERRATA_A78C_2779484}, |
|||
[6 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A78C_H_INC */ |
|||
|
|||
#if CORTEX_X1_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_X1_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1688305, 0x00, 0x10, ERRATA_X1_1688305}, |
|||
[1] = {1821534, 0x00, 0x10, ERRATA_X1_1821534}, |
|||
[2] = {1827429, 0x00, 0x10, ERRATA_X1_1827429}, |
|||
[3 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_X1_H_INC */ |
|||
|
|||
#if NEOVERSE_N1_H_INC |
|||
{ |
|||
.cpu_partnumber = NEOVERSE_N1_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1073348, 0x00, 0x10, ERRATA_N1_1073348}, |
|||
[1] = {1130799, 0x00, 0x20, ERRATA_N1_1130799}, |
|||
[2] = {1165347, 0x00, 0x20, ERRATA_N1_1165347}, |
|||
[3] = {1207823, 0x00, 0x20, ERRATA_N1_1207823}, |
|||
[4] = {1220197, 0x00, 0x20, ERRATA_N1_1220197}, |
|||
[5] = {1257314, 0x00, 0x30, ERRATA_N1_1257314}, |
|||
[6] = {1262606, 0x00, 0x30, ERRATA_N1_1262606}, |
|||
[7] = {1262888, 0x00, 0x30, ERRATA_N1_1262888}, |
|||
[8] = {1275112, 0x00, 0x30, ERRATA_N1_1275112}, |
|||
[9] = {1315703, 0x00, 0x30, ERRATA_N1_1315703}, |
|||
[10] = {1542419, 0x30, 0x40, ERRATA_N1_1542419}, |
|||
[11] = {1868343, 0x00, 0x40, ERRATA_N1_1868343}, |
|||
[12] = {1946160, 0x30, 0x41, ERRATA_N1_1946160}, |
|||
[13] = {2743102, 0x00, 0x41, ERRATA_N1_2743102}, |
|||
[14 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* NEOVERSE_N1_H_INC */ |
|||
|
|||
#if NEOVERSE_V1_H_INC |
|||
{ |
|||
.cpu_partnumber = NEOVERSE_V1_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1618635, 0x00, 0x0F, ERRATA_V1_1618635}, |
|||
[1] = {1774420, 0x00, 0x10, ERRATA_V1_1774420}, |
|||
[2] = {1791573, 0x00, 0x10, ERRATA_V1_1791573}, |
|||
[3] = {1852267, 0x00, 0x10, ERRATA_V1_1852267}, |
|||
[4] = {1925756, 0x00, 0x11, ERRATA_V1_1925756}, |
|||
[5] = {1940577, 0x10, 0x11, ERRATA_V1_1940577}, |
|||
[6] = {1966096, 0x10, 0x11, ERRATA_V1_1966096}, |
|||
[7] = {2108267, 0x00, 0x11, ERRATA_V1_2108267}, |
|||
[8] = {2139242, 0x00, 0x11, ERRATA_V1_2139242}, |
|||
[9] = {2216392, 0x10, 0x11, ERRATA_V1_2216392}, |
|||
[10] = {2294912, 0x00, 0x11, ERRATA_V1_2294912}, |
|||
[11] = {2372203, 0x00, 0x11, ERRATA_V1_2372203}, |
|||
[12] = {2743093, 0x00, 0x12, ERRATA_V1_2743093}, |
|||
[13] = {2779461, 0x00, 0x12, ERRATA_V1_2779461}, |
|||
[14 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* NEOVERSE_V1_H_INC */ |
|||
|
|||
#if CORTEX_A710_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A710_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1987031, 0x00, 0x20, ERRATA_A710_1987031}, |
|||
[1] = {2008768, 0x00, 0x20, ERRATA_A710_2008768}, |
|||
[2] = {2017096, 0x00, 0x20, ERRATA_A710_2017096}, |
|||
[3] = {2055002, 0x10, 0x20, ERRATA_A710_2055002}, |
|||
[4] = {2058056, 0x00, 0x10, ERRATA_A710_2058056}, |
|||
[5] = {2081180, 0x00, 0x20, ERRATA_A710_2081180}, |
|||
[6] = {2083908, 0x20, 0x20, ERRATA_A710_2083908}, |
|||
[7] = {2136059, 0x00, 0x20, ERRATA_A710_2136059}, |
|||
[8] = {2147715, 0x20, 0x20, ERRATA_A710_2147715}, |
|||
[9] = {2216384, 0x00, 0x20, ERRATA_A710_2216384}, |
|||
[10] = {2267065, 0x00, 0x20, ERRATA_A710_2267065}, |
|||
[11] = {2282622, 0x00, 0x21, ERRATA_A710_2282622}, |
|||
[12] = {2291219, 0x00, 0x20, ERRATA_A710_2291219}, |
|||
[13] = {2371105, 0x00, 0x20, ERRATA_A710_2371105}, |
|||
[14] = {2768515, 0x00, 0x21, ERRATA_A710_2768515} |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A710_H_INC */ |
|||
|
|||
#if NEOVERSE_N2_H_INC |
|||
{ |
|||
.cpu_partnumber = NEOVERSE_N2_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {2002655, 0x00, 0x00, ERRATA_N2_2002655}, |
|||
[1] = {2025414, 0x00, 0x00, ERRATA_N2_2025414}, |
|||
[2] = {2067956, 0x00, 0x00, ERRATA_N2_2067956}, |
|||
[3] = {2138953, 0x00, 0x00, ERRATA_N2_2138953}, |
|||
[4] = {2138956, 0x00, 0x00, ERRATA_N2_2138956}, |
|||
[5] = {2138958, 0x00, 0x00, ERRATA_N2_2138958}, |
|||
[6] = {2189731, 0x00, 0x00, ERRATA_N2_2189731}, |
|||
[7] = {2242400, 0x00, 0x00, ERRATA_N2_2242400}, |
|||
[8] = {2242415, 0x00, 0x00, ERRATA_N2_2242415}, |
|||
[9] = {2280757, 0x00, 0x00, ERRATA_N2_2280757}, |
|||
[10] = {2326639, 0x00, 0x00, ERRATA_N2_2326639}, |
|||
[11] = {2376738, 0x00, 0x00, ERRATA_N2_2376738}, |
|||
[12] = {2388450, 0x00, 0x00, ERRATA_N2_2388450}, |
|||
[13] = {2743089, 0x00, 0x02, ERRATA_N2_2743089}, |
|||
[14 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* NEOVERSE_N2_H_INC */ |
|||
|
|||
#if CORTEX_X2_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_X2_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {2002765, 0x00, 0x20, ERRATA_X2_2002765}, |
|||
[1] = {2017096, 0x00, 0x20, ERRATA_X2_2017096}, |
|||
[2] = {2058056, 0x00, 0x20, ERRATA_X2_2058056}, |
|||
[3] = {2081180, 0x00, 0x20, ERRATA_X2_2081180}, |
|||
[4] = {2083908, 0x00, 0x20, ERRATA_X2_2083908}, |
|||
[5] = {2147715, 0x20, 0x20, ERRATA_X2_2147715}, |
|||
[6] = {2216384, 0x00, 0x20, ERRATA_X2_2216384}, |
|||
[7] = {2282622, 0x00, 0x21, ERRATA_X2_2282622}, |
|||
[8] = {2371105, 0x00, 0x21, ERRATA_X2_2371105}, |
|||
[9] = {2768515, 0x00, 0x21, ERRATA_X2_2768515}, |
|||
[10 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_X2_H_INC */ |
|||
|
|||
#if CORTEX_A510_H_INC |
|||
{ |
|||
.cpu_partnumber = CORTEX_A510_MIDR, |
|||
.cpu_errata_list = { |
|||
[0] = {1922240, 0x00, 0x00, ERRATA_A510_1922240}, |
|||
[1] = {2041909, 0x02, 0x02, ERRATA_A510_2041909}, |
|||
[2] = {2042739, 0x00, 0x02, ERRATA_A510_2042739}, |
|||
[3] = {2172148, 0x00, 0x10, ERRATA_A510_2172148}, |
|||
[4] = {2218950, 0x00, 0x10, ERRATA_A510_2218950}, |
|||
[5] = {2250311, 0x00, 0x10, ERRATA_A510_2250311}, |
|||
[6] = {2288014, 0x00, 0x10, ERRATA_A510_2288014}, |
|||
[7] = {2347730, 0x00, 0x11, ERRATA_A510_2347730}, |
|||
[8] = {2371937, 0x00, 0x11, ERRATA_A510_2371937}, |
|||
[9] = {2666669, 0x00, 0x11, ERRATA_A510_2666669}, |
|||
[10] = {2684597, 0x00, 0x12, ERRATA_A510_2684597}, |
|||
[11 ... ERRATA_LIST_END] = UNDEF_ERRATA, |
|||
} |
|||
}, |
|||
#endif /* CORTEX_A510_H_INC */ |
|||
}; |
|||
|
|||
/*
|
|||
* Function to do binary search and check for the specific errata ID |
|||
* in the array of structures specific to the cpu identified. |
|||
*/ |
|||
int32_t binary_search(struct em_cpu_list *ptr, uint32_t erratum_id, |
|||
uint8_t rxpx_val) |
|||
{ |
|||
int low_index = 0U, mid_index = 0U; |
|||
|
|||
int high_index = MAX_ERRATA_ENTRIES - 1; |
|||
|
|||
while (low_index <= high_index) { |
|||
mid_index = (low_index + high_index) / 2; |
|||
if (erratum_id < ptr->cpu_errata_list[mid_index].em_errata_id) { |
|||
high_index = mid_index - 1; |
|||
} else if (erratum_id > ptr->cpu_errata_list[mid_index].em_errata_id) { |
|||
low_index = mid_index + 1; |
|||
} else if (erratum_id == ptr->cpu_errata_list[mid_index].em_errata_id) { |
|||
|
|||
if (RXPX_RANGE(rxpx_val, ptr->cpu_errata_list[mid_index].em_rxpx_lo, \ |
|||
ptr->cpu_errata_list[mid_index].em_rxpx_hi)) { |
|||
if (ptr->cpu_errata_list[mid_index].errata_enabled) { |
|||
return EM_HIGHER_EL_MITIGATION; |
|||
} |
|||
return EM_AFFECTED; |
|||
} |
|||
return EM_NOT_AFFECTED; |
|||
} |
|||
} |
|||
/* no matching errata ID */ |
|||
return EM_UNKNOWN_ERRATUM; |
|||
} |
|||
|
|||
/* Function to check if the errata exists for the specific CPU and rxpx */ |
|||
int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag) |
|||
{ |
|||
/*
|
|||
* Read MIDR value and extract the revision, variant and partnumber |
|||
*/ |
|||
static uint32_t midr_val, cpu_partnum; |
|||
static uint8_t cpu_rxpx_val; |
|||
int32_t ret_val = EM_UNKNOWN_ERRATUM; |
|||
|
|||
/* Determine the number of cpu listed in the cpu list */ |
|||
uint8_t size_cpulist = ARRAY_SIZE(cpu_list); |
|||
|
|||
/* Read the midr reg to extract cpu, revision and variant info */ |
|||
midr_val = read_midr(); |
|||
|
|||
/* Extract revision and variant from the MIDR register */ |
|||
cpu_rxpx_val = cpu_get_rev_var(); |
|||
|
|||
/* Extract the cpu partnumber and check if the cpu is in the cpu list */ |
|||
cpu_partnum = EXTRACT_PARTNUM(midr_val); |
|||
|
|||
for (uint8_t i = 0; i < size_cpulist; i++) { |
|||
cpu_ptr = &cpu_list[i]; |
|||
uint16_t partnum_extracted = EXTRACT_PARTNUM(cpu_ptr->cpu_partnumber); |
|||
|
|||
if (partnum_extracted == cpu_partnum) { |
|||
/*
|
|||
* If the midr value is in the cpu list, binary search |
|||
* for the errata ID and specific revision in the list. |
|||
*/ |
|||
ret_val = binary_search(cpu_ptr, errata_id, cpu_rxpx_val); |
|||
break; |
|||
} |
|||
} |
|||
return ret_val; |
|||
} |
|||
|
|||
/* Predicate indicating that a function id is part of EM_ABI */ |
|||
bool is_errata_fid(uint32_t smc_fid) |
|||
{ |
|||
return ((smc_fid == ARM_EM_VERSION) || |
|||
(smc_fid == ARM_EM_FEATURES) || |
|||
(smc_fid == ARM_EM_CPU_ERRATUM_FEATURES)); |
|||
|
|||
} |
|||
|
|||
bool validate_spsr_mode(void) |
|||
{ |
|||
/* In AArch64, if the caller is EL1, return true */ |
|||
|
|||
#if __aarch64__ |
|||
if (GET_EL(read_spsr_el3()) == MODE_EL1) { |
|||
return true; |
|||
} |
|||
return false; |
|||
#else |
|||
|
|||
/* In AArch32, if in system/svc mode, return true */ |
|||
uint8_t read_el_state = GET_M32(read_spsr()); |
|||
|
|||
if ((read_el_state == (MODE32_svc)) || (read_el_state == MODE32_sys)) { |
|||
return true; |
|||
} |
|||
return false; |
|||
#endif /* __aarch64__ */ |
|||
} |
|||
|
|||
uintptr_t errata_abi_smc_handler(uint32_t smc_fid, u_register_t x1, |
|||
u_register_t x2, u_register_t x3, u_register_t x4, |
|||
void *cookie, void *handle, u_register_t flags) |
|||
{ |
|||
int32_t ret_id = EM_UNKNOWN_ERRATUM; |
|||
|
|||
switch (smc_fid) { |
|||
case ARM_EM_VERSION: |
|||
SMC_RET1(handle, MAKE_SMCCC_VERSION( |
|||
EM_VERSION_MAJOR, EM_VERSION_MINOR |
|||
)); |
|||
break; /* unreachable */ |
|||
case ARM_EM_FEATURES: |
|||
if (is_errata_fid((uint32_t)x1)) { |
|||
SMC_RET1(handle, EM_SUCCESS); |
|||
} |
|||
|
|||
SMC_RET1(handle, EM_NOT_SUPPORTED); |
|||
break; /* unreachable */ |
|||
case ARM_EM_CPU_ERRATUM_FEATURES: |
|||
|
|||
/*
|
|||
* If the forward flag is greater than zero and the calling EL |
|||
* is EL1 in AArch64 or in system mode or svc mode in case of AArch32, |
|||
* return Invalid Parameters. |
|||
*/ |
|||
if (((uint32_t)x2 != 0) && (validate_spsr_mode())) { |
|||
SMC_RET1(handle, EM_INVALID_PARAMETERS); |
|||
} |
|||
ret_id = verify_errata_implemented((uint32_t)x1, (uint32_t)x2); |
|||
SMC_RET1(handle, ret_id); |
|||
break; /* unreachable */ |
|||
default: |
|||
{ |
|||
WARN("Unimplemented Errata ABI Service Call: 0x%x\n", smc_fid); |
|||
SMC_RET1(handle, EM_UNKNOWN_ERRATUM); |
|||
break; /* unreachable */ |
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue