2014-11-14 23:54:09 +08:00
|
|
|
/*
|
|
|
|
* 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>
|
|
|
|
|
2014-11-14 23:54:10 +08:00
|
|
|
static bool __maybe_unused
|
2016-04-22 19:25:31 +08:00
|
|
|
is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
|
2014-11-14 23:54:10 +08:00
|
|
|
{
|
2018-03-07 01:15:34 +08:00
|
|
|
const struct arm64_midr_revidr *fix;
|
|
|
|
u32 midr = read_cpuid_id(), revidr;
|
|
|
|
|
2016-04-22 19:25:31 +08:00
|
|
|
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
|
2018-03-07 01:15:34 +08:00
|
|
|
if (!MIDR_IS_CPU_MODEL_RANGE(midr, entry->midr_model,
|
|
|
|
entry->midr_range_min,
|
|
|
|
entry->midr_range_max))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
midr &= MIDR_REVISION_MASK | MIDR_VARIANT_MASK;
|
|
|
|
revidr = read_cpuid(REVIDR_EL1);
|
|
|
|
for (fix = entry->fixed_revs; fix && fix->revidr_mask; fix++)
|
|
|
|
if (midr == fix->midr_rv && (revidr & fix->revidr_mask))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
2014-11-14 23:54:10 +08:00
|
|
|
}
|
|
|
|
|
2017-12-14 06:19:37 +08:00
|
|
|
static bool __maybe_unused
|
|
|
|
is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
|
|
|
|
{
|
|
|
|
u32 model;
|
|
|
|
|
|
|
|
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
|
|
|
|
|
|
|
|
model = read_cpuid_id();
|
|
|
|
model &= MIDR_IMPLEMENTOR_MASK | (0xf00 << MIDR_PARTNUM_SHIFT) |
|
|
|
|
MIDR_ARCHITECTURE_MASK;
|
|
|
|
|
|
|
|
return model == entry->midr_model;
|
|
|
|
}
|
|
|
|
|
2016-09-09 21:07:16 +08:00
|
|
|
static bool
|
|
|
|
has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry,
|
|
|
|
int scope)
|
|
|
|
{
|
|
|
|
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
|
|
|
|
return (read_cpuid_cachetype() & arm64_ftr_reg_ctrel0.strict_mask) !=
|
|
|
|
(arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask);
|
|
|
|
}
|
|
|
|
|
2018-03-26 22:12:28 +08:00
|
|
|
static void
|
|
|
|
cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *__unused)
|
2016-09-09 21:07:16 +08:00
|
|
|
{
|
|
|
|
/* Clear SCTLR_EL1.UCT */
|
|
|
|
config_sctlr_el1(SCTLR_EL1_UCT, 0);
|
|
|
|
}
|
|
|
|
|
2018-01-03 19:17:58 +08:00
|
|
|
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
|
|
|
|
#include <asm/mmu_context.h>
|
|
|
|
#include <asm/cacheflush.h>
|
|
|
|
|
|
|
|
DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
|
|
|
|
|
|
|
|
#ifdef CONFIG_KVM
|
2018-01-06 04:28:59 +08:00
|
|
|
extern char __qcom_hyp_sanitize_link_stack_start[];
|
|
|
|
extern char __qcom_hyp_sanitize_link_stack_end[];
|
2018-02-07 01:56:20 +08:00
|
|
|
extern char __smccc_workaround_1_smc_start[];
|
|
|
|
extern char __smccc_workaround_1_smc_end[];
|
|
|
|
extern char __smccc_workaround_1_hvc_start[];
|
|
|
|
extern char __smccc_workaround_1_hvc_end[];
|
2018-01-03 20:46:21 +08:00
|
|
|
|
2018-01-03 19:17:58 +08:00
|
|
|
static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
|
|
|
|
const char *hyp_vecs_end)
|
|
|
|
{
|
|
|
|
void *dst = lm_alias(__bp_harden_hyp_vecs_start + slot * SZ_2K);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < SZ_2K; i += 0x80)
|
|
|
|
memcpy(dst + i, hyp_vecs_start, hyp_vecs_end - hyp_vecs_start);
|
|
|
|
|
|
|
|
flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
|
|
|
|
const char *hyp_vecs_start,
|
|
|
|
const char *hyp_vecs_end)
|
|
|
|
{
|
|
|
|
static int last_slot = -1;
|
|
|
|
static DEFINE_SPINLOCK(bp_lock);
|
|
|
|
int cpu, slot = -1;
|
|
|
|
|
|
|
|
spin_lock(&bp_lock);
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
|
|
if (per_cpu(bp_hardening_data.fn, cpu) == fn) {
|
|
|
|
slot = per_cpu(bp_hardening_data.hyp_vectors_slot, cpu);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slot == -1) {
|
|
|
|
last_slot++;
|
|
|
|
BUG_ON(((__bp_harden_hyp_vecs_end - __bp_harden_hyp_vecs_start)
|
|
|
|
/ SZ_2K) <= last_slot);
|
|
|
|
slot = last_slot;
|
|
|
|
__copy_hyp_vect_bpi(slot, hyp_vecs_start, hyp_vecs_end);
|
|
|
|
}
|
|
|
|
|
|
|
|
__this_cpu_write(bp_hardening_data.hyp_vectors_slot, slot);
|
|
|
|
__this_cpu_write(bp_hardening_data.fn, fn);
|
|
|
|
spin_unlock(&bp_lock);
|
|
|
|
}
|
|
|
|
#else
|
2018-01-06 04:28:59 +08:00
|
|
|
#define __qcom_hyp_sanitize_link_stack_start NULL
|
|
|
|
#define __qcom_hyp_sanitize_link_stack_end NULL
|
2018-02-07 01:56:20 +08:00
|
|
|
#define __smccc_workaround_1_smc_start NULL
|
|
|
|
#define __smccc_workaround_1_smc_end NULL
|
|
|
|
#define __smccc_workaround_1_hvc_start NULL
|
|
|
|
#define __smccc_workaround_1_hvc_end NULL
|
2018-01-03 20:46:21 +08:00
|
|
|
|
2018-01-03 19:17:58 +08:00
|
|
|
static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
|
|
|
|
const char *hyp_vecs_start,
|
|
|
|
const char *hyp_vecs_end)
|
|
|
|
{
|
|
|
|
__this_cpu_write(bp_hardening_data.fn, fn);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_KVM */
|
|
|
|
|
|
|
|
static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
|
|
|
|
bp_hardening_cb_t fn,
|
|
|
|
const char *hyp_vecs_start,
|
|
|
|
const char *hyp_vecs_end)
|
|
|
|
{
|
|
|
|
u64 pfr0;
|
|
|
|
|
|
|
|
if (!entry->matches(entry, SCOPE_LOCAL_CPU))
|
|
|
|
return;
|
|
|
|
|
|
|
|
pfr0 = read_cpuid(ID_AA64PFR0_EL1);
|
|
|
|
if (cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_CSV2_SHIFT))
|
|
|
|
return;
|
|
|
|
|
|
|
|
__install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
|
|
|
|
}
|
2018-01-03 20:46:21 +08:00
|
|
|
|
2018-02-07 01:56:20 +08:00
|
|
|
#include <uapi/linux/psci.h>
|
|
|
|
#include <linux/arm-smccc.h>
|
2018-01-03 20:46:21 +08:00
|
|
|
#include <linux/psci.h>
|
|
|
|
|
2018-02-07 01:56:20 +08:00
|
|
|
static void call_smc_arch_workaround_1(void)
|
|
|
|
{
|
|
|
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void call_hvc_arch_workaround_1(void)
|
|
|
|
{
|
|
|
|
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
|
|
|
}
|
|
|
|
|
2018-03-26 22:12:28 +08:00
|
|
|
static void
|
|
|
|
enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
|
2018-02-07 01:56:20 +08:00
|
|
|
{
|
|
|
|
bp_hardening_cb_t cb;
|
|
|
|
void *smccc_start, *smccc_end;
|
|
|
|
struct arm_smccc_res res;
|
|
|
|
|
|
|
|
if (!entry->matches(entry, SCOPE_LOCAL_CPU))
|
2018-03-26 22:12:28 +08:00
|
|
|
return;
|
2018-02-07 01:56:20 +08:00
|
|
|
|
|
|
|
if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
|
2018-03-26 22:12:28 +08:00
|
|
|
return;
|
2018-02-07 01:56:20 +08:00
|
|
|
|
|
|
|
switch (psci_ops.conduit) {
|
|
|
|
case PSCI_CONDUIT_HVC:
|
|
|
|
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
|
|
|
|
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
|
|
|
if (res.a0)
|
2018-03-26 22:12:28 +08:00
|
|
|
return;
|
2018-02-07 01:56:20 +08:00
|
|
|
cb = call_hvc_arch_workaround_1;
|
|
|
|
smccc_start = __smccc_workaround_1_hvc_start;
|
|
|
|
smccc_end = __smccc_workaround_1_hvc_end;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PSCI_CONDUIT_SMC:
|
|
|
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
|
|
|
|
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
|
|
|
if (res.a0)
|
2018-03-26 22:12:28 +08:00
|
|
|
return;
|
2018-02-07 01:56:20 +08:00
|
|
|
cb = call_smc_arch_workaround_1;
|
|
|
|
smccc_start = __smccc_workaround_1_smc_start;
|
|
|
|
smccc_end = __smccc_workaround_1_smc_end;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2018-03-26 22:12:28 +08:00
|
|
|
return;
|
2018-02-07 01:56:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
|
|
|
|
|
2018-03-26 22:12:28 +08:00
|
|
|
return;
|
2018-01-03 20:46:21 +08:00
|
|
|
}
|
2018-01-06 04:28:59 +08:00
|
|
|
|
|
|
|
static void qcom_link_stack_sanitization(void)
|
|
|
|
{
|
|
|
|
u64 tmp;
|
|
|
|
|
|
|
|
asm volatile("mov %0, x30 \n"
|
|
|
|
".rept 16 \n"
|
|
|
|
"bl . + 4 \n"
|
|
|
|
".endr \n"
|
|
|
|
"mov x30, %0 \n"
|
|
|
|
: "=&r" (tmp));
|
|
|
|
}
|
|
|
|
|
2018-03-26 22:12:28 +08:00
|
|
|
static void
|
|
|
|
qcom_enable_link_stack_sanitization(const struct arm64_cpu_capabilities *entry)
|
2018-01-06 04:28:59 +08:00
|
|
|
{
|
|
|
|
install_bp_hardening_cb(entry, qcom_link_stack_sanitization,
|
|
|
|
__qcom_hyp_sanitize_link_stack_start,
|
|
|
|
__qcom_hyp_sanitize_link_stack_end);
|
|
|
|
}
|
2018-01-03 19:17:58 +08:00
|
|
|
#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */
|
|
|
|
|
2014-11-14 23:54:10 +08:00
|
|
|
#define MIDR_RANGE(model, min, max) \
|
arm64: capabilities: Prepare for fine grained capabilities
We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
to the userspace and the CPU hwcaps used by the kernel, which
include cpu features and CPU errata work arounds. Capabilities
have some properties that decide how they should be treated :
1) Detection, i.e scope : A cap could be "detected" either :
- if it is present on at least one CPU (SCOPE_LOCAL_CPU)
Or
- if it is present on all the CPUs (SCOPE_SYSTEM)
2) When is it enabled ? - A cap is treated as "enabled" when the
system takes some action based on whether the capability is detected or
not. e.g, setting some control register, patching the kernel code.
Right now, we treat all caps are enabled at boot-time, after all
the CPUs are brought up by the kernel. But there are certain caps,
which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
and kernel starts using them, even before the secondary CPUs are brought
up. We would need a way to describe this for each capability.
3) Conflict on a late CPU - When a CPU is brought up, it is checked
against the caps that are known to be enabled on the system (via
verify_local_cpu_capabilities()). Based on the state of the capability
on the CPU vs. that of System we could have the following combinations
of conflict.
x-----------------------------x
| Type | System | Late CPU |
------------------------------|
| a | y | n |
------------------------------|
| b | n | y |
x-----------------------------x
Case (a) is not permitted for caps which are system features, which the
system expects all the CPUs to have (e.g VHE). While (a) is ignored for
all errata work arounds. However, there could be exceptions to the plain
filtering approach. e.g, KPTI is an optional feature for a late CPU as
long as the system already enables it.
Case (b) is not permitted for errata work arounds which requires some
work around, which cannot be delayed. And we ignore (b) for features.
Here, yet again, KPTI is an exception, where if a late CPU needs KPTI we
are too late to enable it (because we change the allocation of ASIDs
etc).
So this calls for a lot more fine grained behavior for each capability.
And if we define all the attributes to control their behavior properly,
we may be able to use a single table for the CPU hwcaps (which cover
errata and features, not the ELF HWCAPs). This is a prepartory step
to get there. More bits would be added for the properties listed above.
We are going to use a bit-mask to encode all the properties of a
capabilities. This patch encodes the "SCOPE" of the capability.
As such there is no change in how the capabilities are treated.
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2018-03-26 22:12:31 +08:00
|
|
|
.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
|
2015-03-27 21:09:23 +08:00
|
|
|
.matches = is_affected_midr_range, \
|
2014-11-14 23:54:10 +08:00
|
|
|
.midr_model = model, \
|
|
|
|
.midr_range_min = min, \
|
|
|
|
.midr_range_max = max
|
|
|
|
|
2017-02-01 22:38:46 +08:00
|
|
|
#define MIDR_ALL_VERSIONS(model) \
|
arm64: capabilities: Prepare for fine grained capabilities
We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
to the userspace and the CPU hwcaps used by the kernel, which
include cpu features and CPU errata work arounds. Capabilities
have some properties that decide how they should be treated :
1) Detection, i.e scope : A cap could be "detected" either :
- if it is present on at least one CPU (SCOPE_LOCAL_CPU)
Or
- if it is present on all the CPUs (SCOPE_SYSTEM)
2) When is it enabled ? - A cap is treated as "enabled" when the
system takes some action based on whether the capability is detected or
not. e.g, setting some control register, patching the kernel code.
Right now, we treat all caps are enabled at boot-time, after all
the CPUs are brought up by the kernel. But there are certain caps,
which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
and kernel starts using them, even before the secondary CPUs are brought
up. We would need a way to describe this for each capability.
3) Conflict on a late CPU - When a CPU is brought up, it is checked
against the caps that are known to be enabled on the system (via
verify_local_cpu_capabilities()). Based on the state of the capability
on the CPU vs. that of System we could have the following combinations
of conflict.
x-----------------------------x
| Type | System | Late CPU |
------------------------------|
| a | y | n |
------------------------------|
| b | n | y |
x-----------------------------x
Case (a) is not permitted for caps which are system features, which the
system expects all the CPUs to have (e.g VHE). While (a) is ignored for
all errata work arounds. However, there could be exceptions to the plain
filtering approach. e.g, KPTI is an optional feature for a late CPU as
long as the system already enables it.
Case (b) is not permitted for errata work arounds which requires some
work around, which cannot be delayed. And we ignore (b) for features.
Here, yet again, KPTI is an exception, where if a late CPU needs KPTI we
are too late to enable it (because we change the allocation of ASIDs
etc).
So this calls for a lot more fine grained behavior for each capability.
And if we define all the attributes to control their behavior properly,
we may be able to use a single table for the CPU hwcaps (which cover
errata and features, not the ELF HWCAPs). This is a prepartory step
to get there. More bits would be added for the properties listed above.
We are going to use a bit-mask to encode all the properties of a
capabilities. This patch encodes the "SCOPE" of the capability.
As such there is no change in how the capabilities are treated.
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2018-03-26 22:12:31 +08:00
|
|
|
.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU, \
|
2017-02-01 22:38:46 +08:00
|
|
|
.matches = is_affected_midr_range, \
|
|
|
|
.midr_model = model, \
|
|
|
|
.midr_range_min = 0, \
|
|
|
|
.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
|
|
|
|
|
2018-03-07 01:15:34 +08:00
|
|
|
#define MIDR_FIXED(rev, revidr_mask) \
|
|
|
|
.fixed_revs = (struct arm64_midr_revidr[]){{ (rev), (revidr_mask) }, {}}
|
|
|
|
|
2015-03-27 21:09:23 +08:00
|
|
|
const struct arm64_cpu_capabilities arm64_errata[] = {
|
2014-11-14 23:54:12 +08:00
|
|
|
#if defined(CONFIG_ARM64_ERRATUM_826319) || \
|
|
|
|
defined(CONFIG_ARM64_ERRATUM_827319) || \
|
|
|
|
defined(CONFIG_ARM64_ERRATUM_824069)
|
2014-11-14 23:54:10 +08:00
|
|
|
{
|
|
|
|
/* Cortex-A53 r0p[012] */
|
|
|
|
.desc = "ARM errata 826319, 827319, 824069",
|
|
|
|
.capability = ARM64_WORKAROUND_CLEAN_CACHE,
|
|
|
|
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = cpu_enable_cache_maint_trap,
|
2014-11-14 23:54:10 +08:00
|
|
|
},
|
2014-11-14 23:54:12 +08:00
|
|
|
#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),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = cpu_enable_cache_maint_trap,
|
2014-11-14 23:54:12 +08:00
|
|
|
},
|
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_ARM64_ERRATUM_832075
|
2014-11-14 23:54:10 +08:00
|
|
|
{
|
2014-11-14 23:54:11 +08:00
|
|
|
/* Cortex-A57 r0p0 - r1p2 */
|
|
|
|
.desc = "ARM erratum 832075",
|
|
|
|
.capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
|
2017-01-13 21:12:09 +08:00
|
|
|
MIDR_RANGE(MIDR_CORTEX_A57,
|
|
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
|
|
MIDR_CPU_VAR_REV(1, 2)),
|
2014-11-14 23:54:11 +08:00
|
|
|
},
|
2015-03-24 03:07:02 +08:00
|
|
|
#endif
|
2015-11-16 18:28:18 +08:00
|
|
|
#ifdef CONFIG_ARM64_ERRATUM_834220
|
|
|
|
{
|
|
|
|
/* Cortex-A57 r0p0 - r1p2 */
|
|
|
|
.desc = "ARM erratum 834220",
|
|
|
|
.capability = ARM64_WORKAROUND_834220,
|
2017-01-13 21:12:09 +08:00
|
|
|
MIDR_RANGE(MIDR_CORTEX_A57,
|
|
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
|
|
MIDR_CPU_VAR_REV(1, 2)),
|
2015-11-16 18:28:18 +08:00
|
|
|
},
|
|
|
|
#endif
|
2018-03-07 01:15:35 +08:00
|
|
|
#ifdef CONFIG_ARM64_ERRATUM_843419
|
|
|
|
{
|
|
|
|
/* Cortex-A53 r0p[01234] */
|
|
|
|
.desc = "ARM erratum 843419",
|
|
|
|
.capability = ARM64_WORKAROUND_843419,
|
|
|
|
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04),
|
|
|
|
MIDR_FIXED(0x4, BIT(8)),
|
|
|
|
},
|
|
|
|
#endif
|
2015-03-24 03:07:02 +08:00
|
|
|
#ifdef CONFIG_ARM64_ERRATUM_845719
|
|
|
|
{
|
|
|
|
/* Cortex-A53 r0p[01234] */
|
|
|
|
.desc = "ARM erratum 845719",
|
|
|
|
.capability = ARM64_WORKAROUND_845719,
|
|
|
|
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04),
|
|
|
|
},
|
2015-09-22 04:58:35 +08:00
|
|
|
#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),
|
|
|
|
},
|
2016-02-25 09:44:57 +08:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_CAVIUM_ERRATUM_27456
|
|
|
|
{
|
|
|
|
/* Cavium ThunderX, T88 pass 1.x - 2.1 */
|
|
|
|
.desc = "Cavium erratum 27456",
|
|
|
|
.capability = ARM64_WORKAROUND_CAVIUM_27456,
|
2017-01-13 21:12:09 +08:00
|
|
|
MIDR_RANGE(MIDR_THUNDERX,
|
|
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
|
|
MIDR_CPU_VAR_REV(1, 1)),
|
2016-02-25 09:44:57 +08:00
|
|
|
},
|
2016-07-07 12:48:17 +08:00
|
|
|
{
|
|
|
|
/* Cavium ThunderX, T81 pass 1.0 */
|
|
|
|
.desc = "Cavium erratum 27456",
|
|
|
|
.capability = ARM64_WORKAROUND_CAVIUM_27456,
|
|
|
|
MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
|
|
|
|
},
|
2017-06-09 19:49:48 +08:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_CAVIUM_ERRATUM_30115
|
|
|
|
{
|
|
|
|
/* Cavium ThunderX, T88 pass 1.x - 2.2 */
|
|
|
|
.desc = "Cavium erratum 30115",
|
|
|
|
.capability = ARM64_WORKAROUND_CAVIUM_30115,
|
|
|
|
MIDR_RANGE(MIDR_THUNDERX, 0x00,
|
|
|
|
(1 << MIDR_VARIANT_SHIFT) | 2),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Cavium ThunderX, T81 pass 1.0 - 1.2 */
|
|
|
|
.desc = "Cavium erratum 30115",
|
|
|
|
.capability = ARM64_WORKAROUND_CAVIUM_30115,
|
|
|
|
MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* Cavium ThunderX, T83 pass 1.0 */
|
|
|
|
.desc = "Cavium erratum 30115",
|
|
|
|
.capability = ARM64_WORKAROUND_CAVIUM_30115,
|
|
|
|
MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
|
|
|
|
},
|
2014-11-14 23:54:12 +08:00
|
|
|
#endif
|
2016-09-09 21:07:16 +08:00
|
|
|
{
|
|
|
|
.desc = "Mismatched cache line size",
|
|
|
|
.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
|
|
|
|
.matches = has_mismatched_cache_line_size,
|
arm64: capabilities: Prepare for fine grained capabilities
We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
to the userspace and the CPU hwcaps used by the kernel, which
include cpu features and CPU errata work arounds. Capabilities
have some properties that decide how they should be treated :
1) Detection, i.e scope : A cap could be "detected" either :
- if it is present on at least one CPU (SCOPE_LOCAL_CPU)
Or
- if it is present on all the CPUs (SCOPE_SYSTEM)
2) When is it enabled ? - A cap is treated as "enabled" when the
system takes some action based on whether the capability is detected or
not. e.g, setting some control register, patching the kernel code.
Right now, we treat all caps are enabled at boot-time, after all
the CPUs are brought up by the kernel. But there are certain caps,
which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
and kernel starts using them, even before the secondary CPUs are brought
up. We would need a way to describe this for each capability.
3) Conflict on a late CPU - When a CPU is brought up, it is checked
against the caps that are known to be enabled on the system (via
verify_local_cpu_capabilities()). Based on the state of the capability
on the CPU vs. that of System we could have the following combinations
of conflict.
x-----------------------------x
| Type | System | Late CPU |
------------------------------|
| a | y | n |
------------------------------|
| b | n | y |
x-----------------------------x
Case (a) is not permitted for caps which are system features, which the
system expects all the CPUs to have (e.g VHE). While (a) is ignored for
all errata work arounds. However, there could be exceptions to the plain
filtering approach. e.g, KPTI is an optional feature for a late CPU as
long as the system already enables it.
Case (b) is not permitted for errata work arounds which requires some
work around, which cannot be delayed. And we ignore (b) for features.
Here, yet again, KPTI is an exception, where if a late CPU needs KPTI we
are too late to enable it (because we change the allocation of ASIDs
etc).
So this calls for a lot more fine grained behavior for each capability.
And if we define all the attributes to control their behavior properly,
we may be able to use a single table for the CPU hwcaps (which cover
errata and features, not the ELF HWCAPs). This is a prepartory step
to get there. More bits would be added for the properties listed above.
We are going to use a bit-mask to encode all the properties of a
capabilities. This patch encodes the "SCOPE" of the capability.
As such there is no change in how the capabilities are treated.
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2018-03-26 22:12:31 +08:00
|
|
|
.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = cpu_enable_trap_ctr_access,
|
2016-09-09 21:07:16 +08:00
|
|
|
},
|
2017-02-09 04:08:37 +08:00
|
|
|
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
|
|
|
|
{
|
|
|
|
.desc = "Qualcomm Technologies Falkor erratum 1003",
|
|
|
|
.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
|
|
|
|
MIDR_RANGE(MIDR_QCOM_FALKOR_V1,
|
|
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
|
|
MIDR_CPU_VAR_REV(0, 0)),
|
|
|
|
},
|
2017-12-14 06:19:37 +08:00
|
|
|
{
|
|
|
|
.desc = "Qualcomm Technologies Kryo erratum 1003",
|
|
|
|
.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
|
arm64: capabilities: Prepare for fine grained capabilities
We use arm64_cpu_capabilities to represent CPU ELF HWCAPs exposed
to the userspace and the CPU hwcaps used by the kernel, which
include cpu features and CPU errata work arounds. Capabilities
have some properties that decide how they should be treated :
1) Detection, i.e scope : A cap could be "detected" either :
- if it is present on at least one CPU (SCOPE_LOCAL_CPU)
Or
- if it is present on all the CPUs (SCOPE_SYSTEM)
2) When is it enabled ? - A cap is treated as "enabled" when the
system takes some action based on whether the capability is detected or
not. e.g, setting some control register, patching the kernel code.
Right now, we treat all caps are enabled at boot-time, after all
the CPUs are brought up by the kernel. But there are certain caps,
which are enabled early during the boot (e.g, VHE, GIC_CPUIF for NMI)
and kernel starts using them, even before the secondary CPUs are brought
up. We would need a way to describe this for each capability.
3) Conflict on a late CPU - When a CPU is brought up, it is checked
against the caps that are known to be enabled on the system (via
verify_local_cpu_capabilities()). Based on the state of the capability
on the CPU vs. that of System we could have the following combinations
of conflict.
x-----------------------------x
| Type | System | Late CPU |
------------------------------|
| a | y | n |
------------------------------|
| b | n | y |
x-----------------------------x
Case (a) is not permitted for caps which are system features, which the
system expects all the CPUs to have (e.g VHE). While (a) is ignored for
all errata work arounds. However, there could be exceptions to the plain
filtering approach. e.g, KPTI is an optional feature for a late CPU as
long as the system already enables it.
Case (b) is not permitted for errata work arounds which requires some
work around, which cannot be delayed. And we ignore (b) for features.
Here, yet again, KPTI is an exception, where if a late CPU needs KPTI we
are too late to enable it (because we change the allocation of ASIDs
etc).
So this calls for a lot more fine grained behavior for each capability.
And if we define all the attributes to control their behavior properly,
we may be able to use a single table for the CPU hwcaps (which cover
errata and features, not the ELF HWCAPs). This is a prepartory step
to get there. More bits would be added for the properties listed above.
We are going to use a bit-mask to encode all the properties of a
capabilities. This patch encodes the "SCOPE" of the capability.
As such there is no change in how the capabilities are treated.
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <dave.martin@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2018-03-26 22:12:31 +08:00
|
|
|
.type = ARM64_CPUCAP_SCOPE_LOCAL_CPU,
|
2017-12-14 06:19:37 +08:00
|
|
|
.midr_model = MIDR_QCOM_KRYO,
|
|
|
|
.matches = is_kryo_midr,
|
|
|
|
},
|
2017-02-09 04:08:37 +08:00
|
|
|
#endif
|
2017-02-01 01:50:19 +08:00
|
|
|
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
|
|
|
|
{
|
|
|
|
.desc = "Qualcomm Technologies Falkor erratum 1009",
|
|
|
|
.capability = ARM64_WORKAROUND_REPEAT_TLBI,
|
|
|
|
MIDR_RANGE(MIDR_QCOM_FALKOR_V1,
|
|
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
|
|
MIDR_CPU_VAR_REV(0, 0)),
|
|
|
|
},
|
2017-03-21 01:18:06 +08:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_ARM64_ERRATUM_858921
|
|
|
|
{
|
|
|
|
/* Cortex-A73 all versions */
|
|
|
|
.desc = "ARM erratum 858921",
|
|
|
|
.capability = ARM64_WORKAROUND_858921,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
|
|
|
|
},
|
2018-01-03 20:46:21 +08:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
|
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = enable_smccc_arch_workaround_1,
|
2018-01-03 20:46:21 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = enable_smccc_arch_workaround_1,
|
2018-01-03 20:46:21 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = enable_smccc_arch_workaround_1,
|
2018-01-03 20:46:21 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = enable_smccc_arch_workaround_1,
|
2018-01-03 20:46:21 +08:00
|
|
|
},
|
2018-01-06 04:28:59 +08:00
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = qcom_enable_link_stack_sanitization,
|
2018-01-06 04:28:59 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
|
|
|
|
},
|
2018-02-12 09:16:15 +08:00
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = qcom_enable_link_stack_sanitization,
|
2018-02-12 09:16:15 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
|
|
|
|
},
|
2018-01-19 20:22:47 +08:00
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = enable_smccc_arch_workaround_1,
|
2018-01-19 20:22:47 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
|
|
MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
|
2018-03-26 22:12:28 +08:00
|
|
|
.cpu_enable = enable_smccc_arch_workaround_1,
|
2018-01-19 20:22:47 +08:00
|
|
|
},
|
2017-02-01 01:50:19 +08:00
|
|
|
#endif
|
2014-11-14 23:54:11 +08:00
|
|
|
{
|
2014-11-14 23:54:10 +08:00
|
|
|
}
|
2014-11-14 23:54:09 +08:00
|
|
|
};
|