mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-07 14:24:18 +08:00
7dd01aef05
The ARM errata 819472, 826319, 827319 and 824069 for affected Cortex-A53 cores demand to promote "dc cvau" instructions to "dc civac". Since we allow userspace to also emit those instructions, we should make sure that "dc cvau" gets promoted there too. So lets grasp the nettle here and actually trap every userland cache maintenance instruction once we detect at least one affected core in the system. We then emulate the instruction by executing it on behalf of userland, promoting "dc cvau" to "dc civac" on the way and injecting access fault back into userspace. Signed-off-by: Andre Przywara <andre.przywara@arm.com> [catalin.marinas@arm.com: s/set_segfault/arm64_notify_segfault/] Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
137 lines
3.7 KiB
C
137 lines
3.7 KiB
C
/*
|
|
* Contains CPU specific errata definitions
|
|
*
|
|
* Copyright (C) 2014 ARM Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <asm/cpu.h>
|
|
#include <asm/cputype.h>
|
|
#include <asm/cpufeature.h>
|
|
|
|
static bool __maybe_unused
|
|
is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
|
|
{
|
|
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
|
|
return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model,
|
|
entry->midr_range_min,
|
|
entry->midr_range_max);
|
|
}
|
|
|
|
#define MIDR_RANGE(model, min, max) \
|
|
.def_scope = SCOPE_LOCAL_CPU, \
|
|
.matches = is_affected_midr_range, \
|
|
.midr_model = model, \
|
|
.midr_range_min = min, \
|
|
.midr_range_max = max
|
|
|
|
const struct arm64_cpu_capabilities arm64_errata[] = {
|
|
#if defined(CONFIG_ARM64_ERRATUM_826319) || \
|
|
defined(CONFIG_ARM64_ERRATUM_827319) || \
|
|
defined(CONFIG_ARM64_ERRATUM_824069)
|
|
{
|
|
/* Cortex-A53 r0p[012] */
|
|
.desc = "ARM errata 826319, 827319, 824069",
|
|
.capability = ARM64_WORKAROUND_CLEAN_CACHE,
|
|
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
|
|
.enable = cpu_enable_cache_maint_trap,
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_ARM64_ERRATUM_819472
|
|
{
|
|
/* Cortex-A53 r0p[01] */
|
|
.desc = "ARM errata 819472",
|
|
.capability = ARM64_WORKAROUND_CLEAN_CACHE,
|
|
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
|
|
.enable = cpu_enable_cache_maint_trap,
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_ARM64_ERRATUM_832075
|
|
{
|
|
/* Cortex-A57 r0p0 - r1p2 */
|
|
.desc = "ARM erratum 832075",
|
|
.capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
|
|
MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
|
|
(1 << MIDR_VARIANT_SHIFT) | 2),
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_ARM64_ERRATUM_834220
|
|
{
|
|
/* Cortex-A57 r0p0 - r1p2 */
|
|
.desc = "ARM erratum 834220",
|
|
.capability = ARM64_WORKAROUND_834220,
|
|
MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
|
|
(1 << MIDR_VARIANT_SHIFT) | 2),
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_ARM64_ERRATUM_845719
|
|
{
|
|
/* Cortex-A53 r0p[01234] */
|
|
.desc = "ARM erratum 845719",
|
|
.capability = ARM64_WORKAROUND_845719,
|
|
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04),
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_CAVIUM_ERRATUM_23154
|
|
{
|
|
/* Cavium ThunderX, pass 1.x */
|
|
.desc = "Cavium erratum 23154",
|
|
.capability = ARM64_WORKAROUND_CAVIUM_23154,
|
|
MIDR_RANGE(MIDR_THUNDERX, 0x00, 0x01),
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_CAVIUM_ERRATUM_27456
|
|
{
|
|
/* Cavium ThunderX, T88 pass 1.x - 2.1 */
|
|
.desc = "Cavium erratum 27456",
|
|
.capability = ARM64_WORKAROUND_CAVIUM_27456,
|
|
MIDR_RANGE(MIDR_THUNDERX, 0x00,
|
|
(1 << MIDR_VARIANT_SHIFT) | 1),
|
|
},
|
|
#endif
|
|
{
|
|
}
|
|
};
|
|
|
|
/*
|
|
* The CPU Errata work arounds are detected and applied at boot time
|
|
* and the related information is freed soon after. If the new CPU requires
|
|
* an errata not detected at boot, fail this CPU.
|
|
*/
|
|
void verify_local_cpu_errata(void)
|
|
{
|
|
const struct arm64_cpu_capabilities *caps = arm64_errata;
|
|
|
|
for (; caps->matches; caps++)
|
|
if (!cpus_have_cap(caps->capability) &&
|
|
caps->matches(caps, SCOPE_LOCAL_CPU)) {
|
|
pr_crit("CPU%d: Requires work around for %s, not detected"
|
|
" at boot time\n",
|
|
smp_processor_id(),
|
|
caps->desc ? : "an erratum");
|
|
cpu_die_early();
|
|
}
|
|
}
|
|
|
|
void check_local_cpu_errata(void)
|
|
{
|
|
update_cpu_capabilities(arm64_errata, "enabling workaround for");
|
|
}
|
|
|
|
void __init enable_errata_workarounds(void)
|
|
{
|
|
enable_cpu_capabilities(arm64_errata);
|
|
}
|