This is the 4.9.310 stable release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmJVE50ACgkQONu9yGCS aT4mRQ/9FdAGtRk9Q4Rp8EcNqHBx8LxJaAoBHZdcRZnOp09SXYuigNlunxetcK8w ndHpz9oq/JRumuO7gsm9t46rkmiQahjVPVlmMY1PwoBzoKzyOfqGWy6ui//cxvG3 WAheQCLIbI5xCho+rpJc2zRgEdnLx3FIbmuQ+rcMb/SrreDo+U7FXJUVUmMDzLQX uMzaQrrBltNzETg/ScmUBsFAJjcGFnA3PjDZfMJdKexhfOFyn2m3ViSesdn/qWl/ uTcRuqc7li+rRbVQKMaFktPQduGwKZnr/C4Z3quAh0JRHxDplWaNuyabf33i7etv xGBcqz10dG6aRzTtVhrjkpflTosCWiT+cCW51Fgfz80qB2KXAniykGhGb6KKaAzf 6frlB66gVc3NOEp1ECBUu/8uzsMppdWPAcWHiyGXLhv4NrmCBvPGqcLPSc4o1ZLG h3f78+aFDOxH7YD2+J1zxHi/voy8ZwqEoZUfc/HEfVjm6LSDAmVJHzggCQ1CZ2vr Cj0YJ9mqGxm7UFT0Itfy4l5btoJ0x8+v8pzq7yFRHn1AimoWSrYyYJkFKIgSpKrE OxRGvixPGV8kNiA3/Xh8BNVRWH8ciZZGcL2ihi25rNGQoxAK/vrfhBkasxqgbyMv 1XUjUhqiDCkTWs623aNHirvl8dApoT1LDR5IEtCp1UzaVfjY9wk= =paQa -----END PGP SIGNATURE----- Merge 4.9.310 into android-4.9-q Changes in 4.9.310 arm64: errata: Provide macro for major and minor cpu revisions arm64: Remove useless UAO IPI and describe how this gets enabled arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35 arm64: capabilities: Update prototype for enable call back arm64: capabilities: Move errata work around check on boot CPU arm64: capabilities: Move errata processing code arm64: capabilities: Prepare for fine grained capabilities arm64: capabilities: Add flags to handle the conflicts on late CPU arm64: capabilities: Clean up midr range helpers arm64: Add helpers for checking CPU MIDR against a range arm64: capabilities: Add support for checks based on a list of MIDRs clocksource/drivers/arm_arch_timer: Remove fsl-a008585 parameter clocksource/drivers/arm_arch_timer: Introduce generic errata handling infrastructure arm64: arch_timer: Add infrastructure for multiple erratum detection methods arm64: arch_timer: Add erratum handler for CPU-specific capability arm64: arch_timer: Add workaround for ARM erratum 1188873 arm64: arch_timer: avoid unused function warning arm64: Add silicon-errata.txt entry for ARM erratum 1188873 arm64: Make ARM64_ERRATUM_1188873 depend on COMPAT arm64: Add part number for Neoverse N1 arm64: Add part number for Arm Cortex-A77 arm64: Add Neoverse-N2, Cortex-A710 CPU part definition arm64: Add Cortex-X2 CPU part definition arm64: Add helper to decode register from instruction arm64: entry.S: Add ventry overflow sanity checks arm64: entry: Make the trampoline cleanup optional arm64: entry: Free up another register on kpti's tramp_exit path arm64: entry: Move the trampoline data page before the text page arm64: entry: Allow tramp_alias to access symbols after the 4K boundary arm64: entry: Don't assume tramp_vectors is the start of the vectors arm64: entry: Move trampoline macros out of ifdef'd section arm64: entry: Make the kpti trampoline's kpti sequence optional arm64: entry: Allow the trampoline text to occupy multiple pages arm64: entry: Add non-kpti __bp_harden_el1_vectors for mitigations arm64: Move arm64_update_smccc_conduit() out of SSBD ifdef arm64: entry: Add vectors that have the bhb mitigation sequences arm64: entry: Add macro for reading symbol addresses from the trampoline arm64: Add percpu vectors for EL1 KVM: arm64: Add templates for BHB mitigation sequences arm64: Mitigate spectre style branch history side channels KVM: arm64: Allow SMCCC_ARCH_WORKAROUND_3 to be discovered and migrated arm64: add ID_AA64ISAR2_EL1 sys register arm64: Use the clearbhb instruction in mitigations Linux 4.9.310 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I689d7634aebe9d9ffba8d72d1d76bb237ca228a4
This commit is contained in:
commit
28d1339505
38 changed files with 1510 additions and 332 deletions
|
|
@ -55,6 +55,7 @@ stable kernels.
|
|||
| ARM | Cortex-A57 | #834220 | ARM64_ERRATUM_834220 |
|
||||
| ARM | Cortex-A72 | #853709 | N/A |
|
||||
| ARM | Cortex-A55 | #1024718 | ARM64_ERRATUM_1024718 |
|
||||
| ARM | Cortex-A76 | #1188873 | ARM64_ERRATUM_1188873 |
|
||||
| ARM | MMU-500 | #841119,#826419 | N/A |
|
||||
| | | | |
|
||||
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
|
||||
|
|
|
|||
|
|
@ -752,15 +752,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
loops can be debugged more effectively on production
|
||||
systems.
|
||||
|
||||
clocksource.arm_arch_timer.fsl-a008585=
|
||||
[ARM64]
|
||||
Format: <bool>
|
||||
Enable/disable the workaround of Freescale/NXP
|
||||
erratum A-008585. This can be useful for KVM
|
||||
guests, if the guest device tree doesn't show the
|
||||
erratum. If unspecified, the workaround is
|
||||
enabled based on the device tree.
|
||||
|
||||
clearcpuid=BITNUM [X86]
|
||||
Disable CPUID feature X for the kernel. See
|
||||
arch/x86/include/asm/cpufeatures.h for the valid bit
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 309
|
||||
SUBLEVEL = 310
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
|
|
|||
|
|
@ -349,4 +349,9 @@ static inline int kvm_arm_have_ssbd(void)
|
|||
return KVM_SSBD_UNKNOWN;
|
||||
}
|
||||
|
||||
static inline bool kvm_arm_spectre_bhb_mitigated(void)
|
||||
{
|
||||
/* 32bit guests don't need firmware for this */
|
||||
return false;
|
||||
}
|
||||
#endif /* __ARM_KVM_HOST_H__ */
|
||||
|
|
|
|||
|
|
@ -431,6 +431,10 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case ARM_SMCCC_ARCH_WORKAROUND_3:
|
||||
if (kvm_arm_spectre_bhb_mitigated())
|
||||
val = SMCCC_RET_SUCCESS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -443,6 +443,20 @@ config ARM64_ERRATUM_1024718
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_ERRATUM_1188873
|
||||
bool "Cortex-A76: MRC read following MRRC read of specific Generic Timer in AArch32 might give incorrect result"
|
||||
default y
|
||||
depends on COMPAT
|
||||
select ARM_ARCH_TIMER_OOL_WORKAROUND
|
||||
help
|
||||
This option adds work arounds for ARM Cortex-A76 erratum 1188873
|
||||
|
||||
Affected Cortex-A76 cores (r0p0, r1p0, r2p0) could cause
|
||||
register corruption when accessing the timer registers from
|
||||
AArch32 userspace.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config CAVIUM_ERRATUM_22375
|
||||
bool "Cavium erratum 22375, 24313"
|
||||
default y
|
||||
|
|
@ -787,6 +801,16 @@ config ARM64_SSBD
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config MITIGATE_SPECTRE_BRANCH_HISTORY
|
||||
bool "Mitigate Spectre style attacks against branch history" if EXPERT
|
||||
default y
|
||||
depends on HARDEN_BRANCH_PREDICTOR || !KVM
|
||||
help
|
||||
Speculation attacks against some high-performance processors can
|
||||
make use of branch history to influence future speculation.
|
||||
When taking an exception from user-space, a sequence of branches
|
||||
or a firmware call overwrites the branch history.
|
||||
|
||||
menuconfig ARMV8_DEPRECATED
|
||||
bool "Emulate deprecated/obsolete ARMv8 instructions"
|
||||
depends on COMPAT
|
||||
|
|
|
|||
|
|
@ -29,41 +29,35 @@
|
|||
|
||||
#include <clocksource/arm_arch_timer.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
|
||||
#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
|
||||
extern struct static_key_false arch_timer_read_ool_enabled;
|
||||
#define needs_fsl_a008585_workaround() \
|
||||
#define needs_unstable_timer_counter_workaround() \
|
||||
static_branch_unlikely(&arch_timer_read_ool_enabled)
|
||||
#else
|
||||
#define needs_fsl_a008585_workaround() false
|
||||
#define needs_unstable_timer_counter_workaround() false
|
||||
#endif
|
||||
|
||||
u32 __fsl_a008585_read_cntp_tval_el0(void);
|
||||
u32 __fsl_a008585_read_cntv_tval_el0(void);
|
||||
u64 __fsl_a008585_read_cntvct_el0(void);
|
||||
enum arch_timer_erratum_match_type {
|
||||
ate_match_dt,
|
||||
ate_match_local_cap_id,
|
||||
};
|
||||
|
||||
/*
|
||||
* The number of retries is an arbitrary value well beyond the highest number
|
||||
* of iterations the loop has been observed to take.
|
||||
*/
|
||||
#define __fsl_a008585_read_reg(reg) ({ \
|
||||
u64 _old, _new; \
|
||||
int _retries = 200; \
|
||||
\
|
||||
do { \
|
||||
_old = read_sysreg(reg); \
|
||||
_new = read_sysreg(reg); \
|
||||
_retries--; \
|
||||
} while (unlikely(_old != _new) && _retries); \
|
||||
\
|
||||
WARN_ON_ONCE(!_retries); \
|
||||
_new; \
|
||||
})
|
||||
struct arch_timer_erratum_workaround {
|
||||
enum arch_timer_erratum_match_type match_type;
|
||||
const void *id;
|
||||
const char *desc;
|
||||
u32 (*read_cntp_tval_el0)(void);
|
||||
u32 (*read_cntv_tval_el0)(void);
|
||||
u64 (*read_cntvct_el0)(void);
|
||||
};
|
||||
|
||||
extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround;
|
||||
|
||||
#define arch_timer_reg_read_stable(reg) \
|
||||
({ \
|
||||
u64 _val; \
|
||||
if (needs_fsl_a008585_workaround()) \
|
||||
_val = __fsl_a008585_read_##reg(); \
|
||||
if (needs_unstable_timer_counter_workaround()) \
|
||||
_val = timer_unstable_counter_workaround->read_##reg();\
|
||||
else \
|
||||
_val = read_sysreg(reg); \
|
||||
_val; \
|
||||
|
|
|
|||
|
|
@ -103,6 +103,13 @@
|
|||
hint #20
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Clear Branch History instruction
|
||||
*/
|
||||
.macro clearbhb
|
||||
hint #22
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Sanitise a 64-bit bounded index wrt speculation, returning zero if out
|
||||
* of bounds.
|
||||
|
|
@ -510,4 +517,31 @@ alternative_endif
|
|||
.Ldone\@:
|
||||
.endm
|
||||
|
||||
.macro __mitigate_spectre_bhb_loop tmp
|
||||
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
|
||||
alternative_cb spectre_bhb_patch_loop_iter
|
||||
mov \tmp, #32 // Patched to correct the immediate
|
||||
alternative_cb_end
|
||||
.Lspectre_bhb_loop\@:
|
||||
b . + 4
|
||||
subs \tmp, \tmp, #1
|
||||
b.ne .Lspectre_bhb_loop\@
|
||||
dsb nsh
|
||||
isb
|
||||
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
|
||||
.endm
|
||||
|
||||
/* Save/restores x0-x3 to the stack */
|
||||
.macro __mitigate_spectre_bhb_fw
|
||||
#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
|
||||
stp x0, x1, [sp, #-16]!
|
||||
stp x2, x3, [sp, #-16]!
|
||||
mov w0, #ARM_SMCCC_ARCH_WORKAROUND_3
|
||||
alternative_cb arm64_update_smccc_conduit
|
||||
nop // Patched to SMC/HVC #0
|
||||
alternative_cb_end
|
||||
ldp x2, x3, [sp], #16
|
||||
ldp x0, x1, [sp], #16
|
||||
#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
|
||||
.endm
|
||||
#endif /* __ASM_ASSEMBLER_H */
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ struct cpuinfo_arm64 {
|
|||
u64 reg_id_aa64dfr1;
|
||||
u64 reg_id_aa64isar0;
|
||||
u64 reg_id_aa64isar1;
|
||||
u64 reg_id_aa64isar2;
|
||||
u64 reg_id_aa64mmfr0;
|
||||
u64 reg_id_aa64mmfr1;
|
||||
u64 reg_id_aa64mmfr2;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@
|
|||
#define ARM64_HARDEN_BRANCH_PREDICTOR 17
|
||||
#define ARM64_SSBD 18
|
||||
#define ARM64_MISMATCHED_CACHE_TYPE 19
|
||||
#define ARM64_WORKAROUND_1188873 20
|
||||
#define ARM64_SPECTRE_BHB 21
|
||||
|
||||
#define ARM64_NCAPS 20
|
||||
#define ARM64_NCAPS 22
|
||||
|
||||
#endif /* __ASM_CPUCAPS_H */
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#define __ASM_CPUFEATURE_H
|
||||
|
||||
#include <asm/cpucaps.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
|
|
@ -66,24 +67,173 @@ struct arm64_ftr_reg {
|
|||
|
||||
extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
|
||||
|
||||
/* scope of capability check */
|
||||
enum {
|
||||
SCOPE_SYSTEM,
|
||||
SCOPE_LOCAL_CPU,
|
||||
};
|
||||
/*
|
||||
* CPU capabilities:
|
||||
*
|
||||
* We use arm64_cpu_capabilities to represent system features, errata work
|
||||
* arounds (both used internally by kernel and tracked in cpu_hwcaps) and
|
||||
* ELF HWCAPs (which are exposed to user).
|
||||
*
|
||||
* To support systems with heterogeneous CPUs, we need to make sure that we
|
||||
* detect the capabilities correctly on the system and take appropriate
|
||||
* measures to ensure there are no incompatibilities.
|
||||
*
|
||||
* This comment tries to explain how we treat the capabilities.
|
||||
* Each capability has the following list of attributes :
|
||||
*
|
||||
* 1) Scope of Detection : The system detects a given capability by
|
||||
* performing some checks at runtime. This could be, e.g, checking the
|
||||
* value of a field in CPU ID feature register or checking the cpu
|
||||
* model. The capability provides a call back ( @matches() ) to
|
||||
* perform the check. Scope defines how the checks should be performed.
|
||||
* There are two cases:
|
||||
*
|
||||
* a) SCOPE_LOCAL_CPU: check all the CPUs and "detect" if at least one
|
||||
* matches. This implies, we have to run the check on all the
|
||||
* booting CPUs, until the system decides that state of the
|
||||
* capability is finalised. (See section 2 below)
|
||||
* Or
|
||||
* b) SCOPE_SYSTEM: check all the CPUs and "detect" if all the CPUs
|
||||
* matches. This implies, we run the check only once, when the
|
||||
* system decides to finalise the state of the capability. If the
|
||||
* capability relies on a field in one of the CPU ID feature
|
||||
* registers, we use the sanitised value of the register from the
|
||||
* CPU feature infrastructure to make the decision.
|
||||
*
|
||||
* The process of detection is usually denoted by "update" capability
|
||||
* state in the code.
|
||||
*
|
||||
* 2) Finalise the state : The kernel should finalise the state of a
|
||||
* capability at some point during its execution and take necessary
|
||||
* actions if any. Usually, this is done, after all the boot-time
|
||||
* enabled CPUs are brought up by the kernel, so that it can make
|
||||
* better decision based on the available set of CPUs. However, there
|
||||
* are some special cases, where the action is taken during the early
|
||||
* boot by the primary boot CPU. (e.g, running the kernel at EL2 with
|
||||
* Virtualisation Host Extensions). The kernel usually disallows any
|
||||
* changes to the state of a capability once it finalises the capability
|
||||
* and takes any action, as it may be impossible to execute the actions
|
||||
* safely. A CPU brought up after a capability is "finalised" is
|
||||
* referred to as "Late CPU" w.r.t the capability. e.g, all secondary
|
||||
* CPUs are treated "late CPUs" for capabilities determined by the boot
|
||||
* CPU.
|
||||
*
|
||||
* 3) Verification: When a CPU is brought online (e.g, by user or by the
|
||||
* kernel), the kernel should make sure that it is safe to use the CPU,
|
||||
* by verifying that the CPU is compliant with the state of the
|
||||
* capabilities finalised already. This happens via :
|
||||
*
|
||||
* secondary_start_kernel()-> check_local_cpu_capabilities()
|
||||
*
|
||||
* As explained in (2) above, capabilities could be finalised at
|
||||
* different points in the execution. Each CPU is verified against the
|
||||
* "finalised" capabilities and if there is a conflict, the kernel takes
|
||||
* an action, based on the severity (e.g, a CPU could be prevented from
|
||||
* booting or cause a kernel panic). The CPU is allowed to "affect" the
|
||||
* state of the capability, if it has not been finalised already.
|
||||
* See section 5 for more details on conflicts.
|
||||
*
|
||||
* 4) Action: As mentioned in (2), the kernel can take an action for each
|
||||
* detected capability, on all CPUs on the system. Appropriate actions
|
||||
* include, turning on an architectural feature, modifying the control
|
||||
* registers (e.g, SCTLR, TCR etc.) or patching the kernel via
|
||||
* alternatives. The kernel patching is batched and performed at later
|
||||
* point. The actions are always initiated only after the capability
|
||||
* is finalised. This is usally denoted by "enabling" the capability.
|
||||
* The actions are initiated as follows :
|
||||
* a) Action is triggered on all online CPUs, after the capability is
|
||||
* finalised, invoked within the stop_machine() context from
|
||||
* enable_cpu_capabilitie().
|
||||
*
|
||||
* b) Any late CPU, brought up after (1), the action is triggered via:
|
||||
*
|
||||
* check_local_cpu_capabilities() -> verify_local_cpu_capabilities()
|
||||
*
|
||||
* 5) Conflicts: Based on the state of the capability on a late CPU vs.
|
||||
* the system state, we could have the following combinations :
|
||||
*
|
||||
* x-----------------------------x
|
||||
* | Type | System | Late CPU |
|
||||
* |-----------------------------|
|
||||
* | a | y | n |
|
||||
* |-----------------------------|
|
||||
* | b | n | y |
|
||||
* x-----------------------------x
|
||||
*
|
||||
* Two separate flag bits are defined to indicate whether each kind of
|
||||
* conflict can be allowed:
|
||||
* ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU - Case(a) is allowed
|
||||
* ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU - Case(b) is allowed
|
||||
*
|
||||
* Case (a) is not permitted for a capability that the system requires
|
||||
* all CPUs to have in order for the capability to be enabled. This is
|
||||
* typical for capabilities that represent enhanced functionality.
|
||||
*
|
||||
* Case (b) is not permitted for a capability that must be enabled
|
||||
* during boot if any CPU in the system requires it in order to run
|
||||
* safely. This is typical for erratum work arounds that cannot be
|
||||
* enabled after the corresponding capability is finalised.
|
||||
*
|
||||
* In some non-typical cases either both (a) and (b), or neither,
|
||||
* should be permitted. This can be described by including neither
|
||||
* or both flags in the capability's type field.
|
||||
*/
|
||||
|
||||
|
||||
/* Decide how the capability is detected. On a local CPU vs System wide */
|
||||
#define ARM64_CPUCAP_SCOPE_LOCAL_CPU ((u16)BIT(0))
|
||||
#define ARM64_CPUCAP_SCOPE_SYSTEM ((u16)BIT(1))
|
||||
#define ARM64_CPUCAP_SCOPE_MASK \
|
||||
(ARM64_CPUCAP_SCOPE_SYSTEM | \
|
||||
ARM64_CPUCAP_SCOPE_LOCAL_CPU)
|
||||
|
||||
#define SCOPE_SYSTEM ARM64_CPUCAP_SCOPE_SYSTEM
|
||||
#define SCOPE_LOCAL_CPU ARM64_CPUCAP_SCOPE_LOCAL_CPU
|
||||
|
||||
/*
|
||||
* Is it permitted for a late CPU to have this capability when system
|
||||
* hasn't already enabled it ?
|
||||
*/
|
||||
#define ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU ((u16)BIT(4))
|
||||
/* Is it safe for a late CPU to miss this capability when system has it */
|
||||
#define ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU ((u16)BIT(5))
|
||||
|
||||
/*
|
||||
* CPU errata workarounds that need to be enabled at boot time if one or
|
||||
* more CPUs in the system requires it. When one of these capabilities
|
||||
* has been enabled, it is safe to allow any CPU to boot that doesn't
|
||||
* require the workaround. However, it is not safe if a "late" CPU
|
||||
* requires a workaround and the system hasn't enabled it already.
|
||||
*/
|
||||
#define ARM64_CPUCAP_LOCAL_CPU_ERRATUM \
|
||||
(ARM64_CPUCAP_SCOPE_LOCAL_CPU | ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
|
||||
/*
|
||||
* CPU feature detected at boot time based on system-wide value of a
|
||||
* feature. It is safe for a late CPU to have this feature even though
|
||||
* the system hasn't enabled it, although the featuer will not be used
|
||||
* by Linux in this case. If the system has enabled this feature already,
|
||||
* then every late CPU must have it.
|
||||
*/
|
||||
#define ARM64_CPUCAP_SYSTEM_FEATURE \
|
||||
(ARM64_CPUCAP_SCOPE_SYSTEM | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
|
||||
|
||||
struct arm64_cpu_capabilities {
|
||||
const char *desc;
|
||||
u16 capability;
|
||||
int def_scope; /* default scope */
|
||||
u16 type;
|
||||
bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
|
||||
int (*enable)(void *); /* Called on all active CPUs */
|
||||
/*
|
||||
* Take the appropriate actions to enable this capability for this CPU.
|
||||
* For each successfully booted CPU, this method is called for each
|
||||
* globally detected capability.
|
||||
*/
|
||||
void (*cpu_enable)(const struct arm64_cpu_capabilities *cap);
|
||||
union {
|
||||
struct { /* To be used for erratum handling only */
|
||||
u32 midr_model;
|
||||
u32 midr_range_min, midr_range_max;
|
||||
struct midr_range midr_range;
|
||||
};
|
||||
|
||||
const struct midr_range *midr_range_list;
|
||||
struct { /* Feature register checking */
|
||||
u32 sys_reg;
|
||||
u8 field_pos;
|
||||
|
|
@ -95,6 +245,23 @@ struct arm64_cpu_capabilities {
|
|||
};
|
||||
};
|
||||
|
||||
static inline int cpucap_default_scope(const struct arm64_cpu_capabilities *cap)
|
||||
{
|
||||
return cap->type & ARM64_CPUCAP_SCOPE_MASK;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap)
|
||||
{
|
||||
return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap)
|
||||
{
|
||||
return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU);
|
||||
}
|
||||
|
||||
extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
|
||||
extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
|
||||
extern struct static_key_false arm64_const_caps_ready;
|
||||
|
|
@ -195,15 +362,8 @@ static inline bool id_aa64pfr0_32bit_el0(u64 pfr0)
|
|||
}
|
||||
|
||||
void __init setup_cpu_features(void);
|
||||
|
||||
void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
|
||||
const char *info);
|
||||
void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps);
|
||||
void check_local_cpu_capabilities(void);
|
||||
|
||||
void update_cpu_errata_workarounds(void);
|
||||
void __init enable_errata_workarounds(void);
|
||||
void verify_local_cpu_errata_workarounds(void);
|
||||
|
||||
u64 read_system_reg(u32 id);
|
||||
|
||||
|
|
@ -212,6 +372,34 @@ static inline bool cpu_supports_mixed_endian_el0(void)
|
|||
return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
|
||||
}
|
||||
|
||||
static inline bool supports_csv2p3(int scope)
|
||||
{
|
||||
u64 pfr0;
|
||||
u8 csv2_val;
|
||||
|
||||
if (scope == SCOPE_LOCAL_CPU)
|
||||
pfr0 = read_sysreg_s(SYS_ID_AA64PFR0_EL1);
|
||||
else
|
||||
pfr0 = read_system_reg(SYS_ID_AA64PFR0_EL1);
|
||||
|
||||
csv2_val = cpuid_feature_extract_unsigned_field(pfr0,
|
||||
ID_AA64PFR0_CSV2_SHIFT);
|
||||
return csv2_val == 3;
|
||||
}
|
||||
|
||||
static inline bool supports_clearbhb(int scope)
|
||||
{
|
||||
u64 isar2;
|
||||
|
||||
if (scope == SCOPE_LOCAL_CPU)
|
||||
isar2 = read_sysreg_s(SYS_ID_AA64ISAR2_EL1);
|
||||
else
|
||||
isar2 = read_system_reg(SYS_ID_AA64ISAR2_EL1);
|
||||
|
||||
return cpuid_feature_extract_unsigned_field(isar2,
|
||||
ID_AA64ISAR2_CLEARBHB_SHIFT);
|
||||
}
|
||||
|
||||
static inline bool system_supports_32bit_el0(void)
|
||||
{
|
||||
return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);
|
||||
|
|
@ -250,6 +438,18 @@ void arm64_set_ssbd_mitigation(bool state);
|
|||
static inline void arm64_set_ssbd_mitigation(bool state) {}
|
||||
#endif
|
||||
|
||||
/* Watch out, ordering is important here. */
|
||||
enum mitigation_state {
|
||||
SPECTRE_UNAFFECTED,
|
||||
SPECTRE_MITIGATED,
|
||||
SPECTRE_VULNERABLE,
|
||||
};
|
||||
|
||||
enum mitigation_state arm64_get_spectre_bhb_state(void);
|
||||
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
|
||||
u8 spectre_bhb_loop_affected(int scope);
|
||||
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -83,6 +83,18 @@
|
|||
#define ARM_CPU_PART_CORTEX_A53 0xD03
|
||||
#define ARM_CPU_PART_CORTEX_A73 0xD09
|
||||
#define ARM_CPU_PART_CORTEX_A75 0xD0A
|
||||
#define ARM_CPU_PART_CORTEX_A35 0xD04
|
||||
#define ARM_CPU_PART_CORTEX_A55 0xD05
|
||||
#define ARM_CPU_PART_CORTEX_A76 0xD0B
|
||||
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
|
||||
#define ARM_CPU_PART_CORTEX_A77 0xD0D
|
||||
#define ARM_CPU_PART_NEOVERSE_V1 0xD40
|
||||
#define ARM_CPU_PART_CORTEX_A78 0xD41
|
||||
#define ARM_CPU_PART_CORTEX_X1 0xD44
|
||||
#define ARM_CPU_PART_CORTEX_A710 0xD47
|
||||
#define ARM_CPU_PART_CORTEX_X2 0xD48
|
||||
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
|
||||
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
|
||||
|
||||
#define APM_CPU_PART_POTENZA 0x000
|
||||
|
||||
|
|
@ -98,6 +110,18 @@
|
|||
#define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
|
||||
#define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
|
||||
#define MIDR_CORTEX_A75 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75)
|
||||
#define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35)
|
||||
#define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
|
||||
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
|
||||
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
|
||||
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
|
||||
#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
|
||||
#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
|
||||
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
|
||||
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
|
||||
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
|
||||
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
|
||||
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
|
||||
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
|
||||
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
|
||||
#define MIDR_CAVIUM_THUNDERX2 MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX2)
|
||||
|
|
@ -109,6 +133,45 @@
|
|||
|
||||
#define read_cpuid(reg) read_sysreg_s(SYS_ ## reg)
|
||||
|
||||
/*
|
||||
* Represent a range of MIDR values for a given CPU model and a
|
||||
* range of variant/revision values.
|
||||
*
|
||||
* @model - CPU model as defined by MIDR_CPU_MODEL
|
||||
* @rv_min - Minimum value for the revision/variant as defined by
|
||||
* MIDR_CPU_VAR_REV
|
||||
* @rv_max - Maximum value for the variant/revision for the range.
|
||||
*/
|
||||
struct midr_range {
|
||||
u32 model;
|
||||
u32 rv_min;
|
||||
u32 rv_max;
|
||||
};
|
||||
|
||||
#define MIDR_RANGE(m, v_min, r_min, v_max, r_max) \
|
||||
{ \
|
||||
.model = m, \
|
||||
.rv_min = MIDR_CPU_VAR_REV(v_min, r_min), \
|
||||
.rv_max = MIDR_CPU_VAR_REV(v_max, r_max), \
|
||||
}
|
||||
|
||||
#define MIDR_ALL_VERSIONS(m) MIDR_RANGE(m, 0, 0, 0xf, 0xf)
|
||||
|
||||
static inline bool is_midr_in_range(u32 midr, struct midr_range const *range)
|
||||
{
|
||||
return MIDR_IS_CPU_MODEL_RANGE(midr, range->model,
|
||||
range->rv_min, range->rv_max);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_midr_in_range_list(u32 midr, struct midr_range const *ranges)
|
||||
{
|
||||
while (ranges->model)
|
||||
if (is_midr_in_range(midr, ranges++))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The CPU ID never changes at run time, so we might as well tell the
|
||||
* compiler that it's constant. Use this function to read the CPU ID
|
||||
|
|
|
|||
|
|
@ -53,9 +53,11 @@ enum fixed_addresses {
|
|||
FIX_TEXT_POKE0,
|
||||
|
||||
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
||||
FIX_ENTRY_TRAMP_TEXT3,
|
||||
FIX_ENTRY_TRAMP_TEXT2,
|
||||
FIX_ENTRY_TRAMP_TEXT1,
|
||||
FIX_ENTRY_TRAMP_DATA,
|
||||
FIX_ENTRY_TRAMP_TEXT,
|
||||
#define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT))
|
||||
#define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT1))
|
||||
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
|
||||
__end_of_permanent_fixed_addresses,
|
||||
|
||||
|
|
|
|||
|
|
@ -332,6 +332,8 @@ bool aarch64_insn_is_branch(u32 insn);
|
|||
u64 aarch64_insn_decode_immediate(enum aarch64_insn_imm_type type, u32 insn);
|
||||
u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
|
||||
u32 insn, u64 imm);
|
||||
u32 aarch64_insn_decode_register(enum aarch64_insn_register_type type,
|
||||
u32 insn);
|
||||
u32 aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
|
||||
enum aarch64_insn_branch_type type);
|
||||
u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
|
||||
|
|
|
|||
|
|
@ -452,4 +452,8 @@ static inline int kvm_arm_have_ssbd(void)
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool kvm_arm_spectre_bhb_mitigated(void)
|
||||
{
|
||||
return arm64_get_spectre_bhb_state() == SPECTRE_MITIGATED;
|
||||
}
|
||||
#endif /* __ARM64_KVM_HOST_H__ */
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ static inline void *kvm_get_hyp_vector(void)
|
|||
struct bp_hardening_data *data = arm64_get_bp_hardening_data();
|
||||
void *vect = kvm_ksym_ref(__kvm_hyp_vector);
|
||||
|
||||
if (data->fn) {
|
||||
if (data->template_start) {
|
||||
vect = __bp_harden_hyp_vecs_start +
|
||||
data->hyp_vectors_slot * SZ_2K;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ typedef struct {
|
|||
*/
|
||||
#define ASID(mm) ((mm)->context.id.counter & 0xffff)
|
||||
|
||||
static inline bool arm64_kernel_unmapped_at_el0(void)
|
||||
static __always_inline bool arm64_kernel_unmapped_at_el0(void)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) &&
|
||||
cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0);
|
||||
|
|
@ -47,6 +47,12 @@ typedef void (*bp_hardening_cb_t)(void);
|
|||
struct bp_hardening_data {
|
||||
int hyp_vectors_slot;
|
||||
bp_hardening_cb_t fn;
|
||||
|
||||
/*
|
||||
* template_start is only used by the BHB mitigation to identify the
|
||||
* hyp_vectors_slot sequence.
|
||||
*/
|
||||
const char *template_start;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/string.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/fpsimd.h>
|
||||
#include <asm/hw_breakpoint.h>
|
||||
#include <asm/lse.h>
|
||||
|
|
@ -219,9 +220,8 @@ static inline void spin_lock_prefetch(const void *ptr)
|
|||
|
||||
#endif
|
||||
|
||||
int cpu_enable_pan(void *__unused);
|
||||
int cpu_enable_uao(void *__unused);
|
||||
int cpu_enable_cache_maint_trap(void *__unused);
|
||||
void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
|
||||
void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_PROCESSOR_H */
|
||||
|
|
|
|||
|
|
@ -26,5 +26,11 @@ extern char __hyp_text_start[], __hyp_text_end[];
|
|||
extern char __idmap_text_start[], __idmap_text_end[];
|
||||
extern char __irqentry_text_start[], __irqentry_text_end[];
|
||||
extern char __mmuoff_data_start[], __mmuoff_data_end[];
|
||||
extern char __entry_tramp_text_start[], __entry_tramp_text_end[];
|
||||
|
||||
static inline size_t entry_tramp_text_size(void)
|
||||
{
|
||||
return __entry_tramp_text_end - __entry_tramp_text_start;
|
||||
}
|
||||
|
||||
#endif /* __ASM_SECTIONS_H */
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
|
||||
#define SYS_ID_AA64ISAR0_EL1 sys_reg(3, 0, 0, 6, 0)
|
||||
#define SYS_ID_AA64ISAR1_EL1 sys_reg(3, 0, 0, 6, 1)
|
||||
#define SYS_ID_AA64ISAR2_EL1 sys_reg(3, 0, 0, 6, 2)
|
||||
|
||||
#define SYS_ID_AA64MMFR0_EL1 sys_reg(3, 0, 0, 7, 0)
|
||||
#define SYS_ID_AA64MMFR1_EL1 sys_reg(3, 0, 0, 7, 1)
|
||||
|
|
@ -177,6 +178,9 @@
|
|||
#define ID_AA64ISAR0_SHA1_SHIFT 8
|
||||
#define ID_AA64ISAR0_AES_SHIFT 4
|
||||
|
||||
/* id_aa64isar2 */
|
||||
#define ID_AA64ISAR2_CLEARBHB_SHIFT 28
|
||||
|
||||
/* id_aa64pfr0 */
|
||||
#define ID_AA64PFR0_CSV3_SHIFT 60
|
||||
#define ID_AA64PFR0_CSV2_SHIFT 56
|
||||
|
|
@ -215,6 +219,7 @@
|
|||
#define ID_AA64MMFR0_TGRAN16_SUPPORTED 0x1
|
||||
|
||||
/* id_aa64mmfr1 */
|
||||
#define ID_AA64MMFR1_ECBHB_SHIFT 60
|
||||
#define ID_AA64MMFR1_PAN_SHIFT 20
|
||||
#define ID_AA64MMFR1_LOR_SHIFT 16
|
||||
#define ID_AA64MMFR1_HPD_SHIFT 12
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue