mirror of
https://github.com/commaai/agnos-kernel-sdm845.git
synced 2026-06-12 21:34:52 +08:00
* refs/heads/tmp-b4c14c2:
Linux 4.9.95
Revert "net: phy: micrel: Restore led_mode and clk_sel on resume"
arm64: futex: Mask __user pointers prior to dereference
lan78xx: Correctly indicate invalid OTP
vhost: fix vhost_vq_access_ok() log check
slip: Check if rstate is initialized before uncompressing
rds: MP-RDS may use an invalid c_path
cdc_ether: flag the Cinterion AHS8 modem by gemalto as WWAN
hwmon: (ina2xx) Fix access to uninitialized mutex
rtl8187: Fix NULL pointer dereference in priv->conf_mutex
Bluetooth: Fix connection if directed advertising and privacy is used
getname_kernel() needs to make sure that ->name != ->iname in long case
s390/ipl: ensure loadparm valid flag is set
s390/qdio: don't merge ERROR output buffers
s390/qdio: don't retry EQBS after CCQ 96
nfit: fix region registration vs block-data-window ranges
block/loop: fix deadlock after loop_set_status
Revert "perf tests: Decompress kernel module before objdump"
sunrpc: remove incorrect HMAC request initialization
arm64: Kill PSCI_GET_VERSION as a variant-2 workaround
arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support
arm/arm64: smccc: Implement SMCCC v1.1 inline primitive
arm/arm64: smccc: Make function identifiers an unsigned quantity
firmware/psci: Expose SMCCC version through psci_ops
firmware/psci: Expose PSCI conduit
arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support
arm/arm64: KVM: Turn kvm_psci_version into a static inline
arm64: KVM: Make PSCI_VERSION a fast path
arm/arm64: KVM: Advertise SMCCC v1.1
arm/arm64: KVM: Implement PSCI 1.0 support
arm/arm64: KVM: Add smccc accessors to PSCI code
arm/arm64: KVM: Add PSCI_VERSION helper
arm/arm64: KVM: Consolidate the PSCI include files
arm64: KVM: Increment PC after handling an SMC trap
arm64: Branch predictor hardening for Cavium ThunderX2
arm64: Implement branch predictor hardening for affected Cortex-A CPUs
arm64: cpu_errata: Allow an erratum to be match for all revisions of a core
arm64: cputype: Add missing MIDR values for Cortex-A72 and Cortex-A75
arm64: entry: Apply BP hardening for suspicious interrupts from EL0
arm64: entry: Apply BP hardening for high-priority synchronous exceptions
arm64: KVM: Use per-CPU vector when BP hardening is enabled
mm: Introduce lm_alias
arm64: Move BP hardening to check_and_switch_context
arm64: Add skeleton to harden the branch predictor against aliasing attacks
arm64: Move post_ttbr_update_workaround to C code
arm64: Factor out TTBR0_EL1 post-update workaround into a specific asm macro
drivers/firmware: Expose psci_get_version through psci_ops structure
arm64: cpufeature: Pass capability structure to ->enable callback
arm64: Run enable method for errata work arounds on late CPUs
arm64: cpufeature: __this_cpu_has_cap() shouldn't stop early
arm64: uaccess: Mask __user pointers for __arch_{clear, copy_*}_user
arm64: uaccess: Don't bother eliding access_ok checks in __{get, put}_user
arm64: uaccess: Prevent speculative use of the current addr_limit
arm64: entry: Ensure branch through syscall table is bounded under speculation
arm64: Use pointer masking to limit uaccess speculation
arm64: Make USER_DS an inclusive limit
arm64: move TASK_* definitions to <asm/processor.h>
arm64: Implement array_index_mask_nospec()
arm64: barrier: Add CSDB macros to control data-value prediction
radeon: hide pointless #warning when compile testing
perf/core: Fix use-after-free in uprobe_perf_close()
perf intel-pt: Fix timestamp following overflow
perf intel-pt: Fix error recovery from missing TIP packet
perf intel-pt: Fix sync_switch
perf intel-pt: Fix overlap detection to identify consecutive buffers correctly
Drivers: hv: vmbus: do not mark HV_PCIE as perf_device
parisc: Fix out of array access in match_pci_device()
media: v4l2-compat-ioctl32: don't oops on overlay
Conflicts:
arch/arm64/Kconfig
arch/arm64/include/asm/cpucaps.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/mmu.h
arch/arm64/include/asm/uaccess.h
arch/arm64/kernel/bpi.S
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/entry.S
arch/arm64/kvm/hyp/switch.c
arch/arm64/mm/fault.c
Change-Id: I4a68c54bcaba175a58046d59ccb589cda16ec6db
Signed-off-by: Blagovest Kolenichev <bkolenichev@codeaurora.org>
387 lines
10 KiB
C
387 lines
10 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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static int cpu_enable_trap_ctr_access(void *__unused)
|
|
{
|
|
/* Clear SCTLR_EL1.UCT */
|
|
config_sctlr_el1(SCTLR_EL1_UCT, 0);
|
|
return 0;
|
|
}
|
|
|
|
#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
|
|
extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[];
|
|
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[];
|
|
|
|
static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
|
|
const char *hyp_vecs_end)
|
|
{
|
|
void *dst = __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
|
|
#define __psci_hyp_bp_inval_start NULL
|
|
#define __psci_hyp_bp_inval_end NULL
|
|
#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
|
|
|
|
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);
|
|
}
|
|
|
|
#include <uapi/linux/psci.h>
|
|
#include <linux/arm-smccc.h>
|
|
#include <linux/psci.h>
|
|
|
|
#ifdef CONFIG_PSCI_BP_HARDENING
|
|
static int enable_psci_bp_hardening(void *data)
|
|
{
|
|
const struct arm64_cpu_capabilities *entry = data;
|
|
|
|
if (psci_ops.get_version)
|
|
install_bp_hardening_cb(entry,
|
|
(bp_hardening_cb_t)psci_ops.get_version,
|
|
__psci_hyp_bp_inval_start,
|
|
__psci_hyp_bp_inval_end);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
static int enable_smccc_arch_workaround_1(void *data)
|
|
{
|
|
const struct arm64_cpu_capabilities *entry = data;
|
|
bp_hardening_cb_t cb;
|
|
void *smccc_start, *smccc_end;
|
|
struct arm_smccc_res res;
|
|
|
|
if (!entry->matches(entry, SCOPE_LOCAL_CPU))
|
|
return 0;
|
|
|
|
if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
|
|
return 0;
|
|
|
|
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)
|
|
return 0;
|
|
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)
|
|
return 0;
|
|
cb = call_smc_arch_workaround_1;
|
|
smccc_start = __smccc_workaround_1_smc_start;
|
|
smccc_end = __smccc_workaround_1_smc_end;
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
install_bp_hardening_cb(entry, cb, smccc_start, smccc_end);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */
|
|
|
|
#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
|
|
|
|
#define MIDR_ALL_VERSIONS(model) \
|
|
.def_scope = SCOPE_LOCAL_CPU, \
|
|
.matches = is_affected_midr_range, \
|
|
.midr_model = model, \
|
|
.midr_range_min = 0, \
|
|
.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
|
|
|
|
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,
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
MIDR_CPU_VAR_REV(1, 2)),
|
|
},
|
|
#endif
|
|
#ifdef CONFIG_ARM64_ERRATUM_834220
|
|
{
|
|
/* Cortex-A57 r0p0 - r1p2 */
|
|
.desc = "ARM erratum 834220",
|
|
.capability = ARM64_WORKAROUND_834220,
|
|
MIDR_RANGE(MIDR_CORTEX_A57,
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
MIDR_CPU_VAR_REV(1, 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,
|
|
MIDR_CPU_VAR_REV(0, 0),
|
|
MIDR_CPU_VAR_REV(1, 1)),
|
|
},
|
|
{
|
|
/* Cavium ThunderX, T81 pass 1.0 */
|
|
.desc = "Cavium erratum 27456",
|
|
.capability = ARM64_WORKAROUND_CAVIUM_27456,
|
|
MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
|
|
},
|
|
#endif
|
|
{
|
|
.desc = "Mismatched cache line size",
|
|
.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
|
|
.matches = has_mismatched_cache_line_size,
|
|
.def_scope = SCOPE_LOCAL_CPU,
|
|
.enable = cpu_enable_trap_ctr_access,
|
|
},
|
|
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
|
|
.enable = enable_smccc_arch_workaround_1,
|
|
},
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
|
|
.enable = enable_smccc_arch_workaround_1,
|
|
},
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
|
|
.enable = enable_smccc_arch_workaround_1,
|
|
},
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
|
|
.enable = enable_smccc_arch_workaround_1,
|
|
},
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_KRYO3G),
|
|
#ifdef CONFIG_PSCI_BP_HARDENING
|
|
.enable = enable_psci_bp_hardening,
|
|
#else
|
|
.enable = enable_smccc_arch_workaround_1,
|
|
#endif
|
|
},
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_KRYO2XX_GOLD),
|
|
#ifdef CONFIG_PSCI_BP_HARDENING
|
|
.enable = enable_psci_bp_hardening,
|
|
#else
|
|
.enable = enable_smccc_arch_workaround_1,
|
|
#endif
|
|
},
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
|
|
.enable = enable_smccc_arch_workaround_1,
|
|
},
|
|
{
|
|
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
|
MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
|
|
.enable = enable_smccc_arch_workaround_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_workarounds(void)
|
|
{
|
|
const struct arm64_cpu_capabilities *caps = arm64_errata;
|
|
|
|
for (; caps->matches; caps++) {
|
|
if (cpus_have_cap(caps->capability)) {
|
|
if (caps->enable)
|
|
caps->enable((void *)caps);
|
|
} else if (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 update_cpu_errata_workarounds(void)
|
|
{
|
|
update_cpu_capabilities(arm64_errata, "enabling workaround for");
|
|
}
|
|
|
|
void __init enable_errata_workarounds(void)
|
|
{
|
|
enable_cpu_capabilities(arm64_errata);
|
|
}
|