Merge 4.14.151 into android-4.14-q
Changes in 4.14.151
scsi: ufs: skip shutdown if hba is not powered
scsi: megaraid: disable device when probe failed after enabled device
scsi: qla2xxx: Fix unbound sleep in fcport delete path.
ARM: OMAP2+: Fix missing reset done flag for am3 and am43
ieee802154: ca8210: prevent memory leak
ARM: dts: am4372: Set memory bandwidth limit for DISPC
net: dsa: qca8k: Use up to 7 ports for all operations
MIPS: dts: ar9331: fix interrupt-controller size
xen/efi: Set nonblocking callbacks
nl80211: fix null pointer dereference
mac80211: fix txq null pointer dereference
mips: Loongson: Fix the link time qualifier of 'serial_exit()'
net: hisilicon: Fix usage of uninitialized variable in function mdio_sc_cfg_reg_write()
r8152: Set macpassthru in reset_resume callback
namespace: fix namespace.pl script to support relative paths
md/raid0: fix warning message for parameter default_layout
Revert "drm/radeon: Fix EEH during kexec"
ocfs2: fix panic due to ocfs2_wq is null
ipv4: Return -ENETUNREACH if we can't create route but saddr is valid
net: bcmgenet: Fix RGMII_MODE_EN value for GENET v1/2/3
net: bcmgenet: Set phydev->dev_flags only for internal PHYs
net: i82596: fix dma_alloc_attr for sni_82596
net: stmmac: disable/enable ptp_ref_clk in suspend/resume flow
sctp: change sctp_prot .no_autobind with true
net: avoid potential infinite loop in tc_ctl_action()
loop: Add LOOP_SET_DIRECT_IO to compat ioctl
memfd: Fix locking when tagging pins
USB: legousbtower: fix memleak on disconnect
ALSA: hda/realtek - Add support for ALC711
usb: udc: lpc32xx: fix bad bit shift operation
USB: serial: ti_usb_3410_5052: fix port-close races
USB: ldusb: fix memleak on disconnect
USB: usblp: fix use-after-free on disconnect
USB: ldusb: fix read info leaks
arm64: sysreg: Move to use definitions for all the SCTLR bits
arm64: Expose support for optional ARMv8-A features
arm64: Fix the feature type for ID register fields
arm64: v8.4: Support for new floating point multiplication instructions
arm64: Documentation: cpu-feature-registers: Remove RES0 fields
arm64: Expose Arm v8.4 features
arm64: move SCTLR_EL{1,2} assertions to <asm/sysreg.h>
arm64: add PSR_AA32_* definitions
arm64: Introduce sysreg_clear_set()
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: Unify the verification
arm64: capabilities: Filter the entries based on a given mask
arm64: capabilities: Prepare for grouping features and errata work arounds
arm64: capabilities: Split the processing of errata work arounds
arm64: capabilities: Allow features based on local CPU scope
arm64: capabilities: Group handling of features and errata workarounds
arm64: capabilities: Introduce weak features based on local CPU
arm64: capabilities: Restrict KPTI detection to boot-time CPUs
arm64: capabilities: Add support for features enabled early
arm64: capabilities: Change scope of VHE to Boot CPU feature
arm64: capabilities: Clean up midr range helpers
arm64: Add helpers for checking CPU MIDR against a range
arm64: Add MIDR encoding for Arm Cortex-A55 and Cortex-A35
arm64: capabilities: Add support for checks based on a list of MIDRs
arm64: KVM: Use SMCCC_ARCH_WORKAROUND_1 for Falkor BP hardening
arm64: don't zero DIT on signal return
arm64: Get rid of __smccc_workaround_1_hvc_*
arm64: cpufeature: Detect SSBS and advertise to userspace
arm64: ssbd: Add support for PSTATE.SSBS rather than trapping to EL3
KVM: arm64: Set SCTLR_EL2.DSSBS if SSBD is forcefully disabled and !vhe
arm64: fix SSBS sanitization
arm64: Add sysfs vulnerability show for spectre-v1
arm64: add sysfs vulnerability show for meltdown
arm64: enable generic CPU vulnerabilites support
arm64: Always enable ssb vulnerability detection
arm64: Provide a command line to disable spectre_v2 mitigation
arm64: Advertise mitigation of Spectre-v2, or lack thereof
arm64: Always enable spectre-v2 vulnerability detection
arm64: add sysfs vulnerability show for spectre-v2
arm64: add sysfs vulnerability show for speculative store bypass
arm64: ssbs: Don't treat CPUs with SSBS as unaffected by SSB
arm64: Force SSBS on context switch
arm64: Use firmware to detect CPUs that are not affected by Spectre-v2
arm64/speculation: Support 'mitigations=' cmdline option
MIPS: tlbex: Fix build_restore_pagemask KScratch restore
staging: wlan-ng: fix exit return when sme->key_idx >= NUM_WEPKEYS
scsi: sd: Ignore a failure to sync cache due to lack of authorization
scsi: core: save/restore command resid for error handling
scsi: core: try to get module before removing device
scsi: ch: Make it possible to open a ch device multiple times again
Input: da9063 - fix capability and drop KEY_SLEEP
Input: synaptics-rmi4 - avoid processing unknown IRQs
ASoC: rsnd: Reinitialize bit clock inversion flag for every format setting
cfg80211: wext: avoid copying malformed SSIDs
mac80211: Reject malformed SSID elements
drm/edid: Add 6 bpc quirk for SDC panel in Lenovo G50
drm/amdgpu: Bail earlier when amdgpu.cik_/si_support is not set to 1
drivers/base/memory.c: don't access uninitialized memmaps in soft_offline_page_store()
fs/proc/page.c: don't access uninitialized memmaps in fs/proc/page.c
scsi: zfcp: fix reaction on bit error threshold notification
mm/slub: fix a deadlock in show_slab_objects()
mm/page_owner: don't access uninitialized memmaps when reading /proc/pagetypeinfo
hugetlbfs: don't access uninitialized memmaps in pfn_range_valid_gigantic()
xtensa: drop EXPORT_SYMBOL for outs*/ins*
parisc: Fix vmap memory leak in ioremap()/iounmap()
CIFS: avoid using MID 0xFFFF
x86/boot/64: Make level2_kernel_pgt pages invalid outside kernel area
pinctrl: armada-37xx: fix control of pins 32 and up
pinctrl: armada-37xx: swap polarity on LED group
btrfs: block-group: Fix a memory leak due to missing btrfs_put_block_group()
memstick: jmb38x_ms: Fix an error handling path in 'jmb38x_ms_probe()'
cpufreq: Avoid cpufreq_suspend() deadlock on system shutdown
xen/netback: fix error path of xenvif_connect_data()
PCI: PM: Fix pci_power_up()
KVM: X86: introduce invalidate_gpa argument to tlb flush
kvm: vmx: Introduce lapic_mode enumeration
kvm: apic: Flush TLB after APIC mode/address change if VPIDs are in use
kvm: vmx: Basic APIC virtualization controls have three settings
RDMA/cxgb4: Do not dma memory off of the stack
Linux 4.14.151
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -2389,8 +2389,8 @@
|
||||
http://repo.or.cz/w/linux-2.6/mini2440.git
|
||||
|
||||
mitigations=
|
||||
[X86,PPC,S390] Control optional mitigations for CPU
|
||||
vulnerabilities. This is a set of curated,
|
||||
[X86,PPC,S390,ARM64] Control optional mitigations for
|
||||
CPU vulnerabilities. This is a set of curated,
|
||||
arch-independent options, each of which is an
|
||||
aggregation of existing arch-specific options.
|
||||
|
||||
@@ -2399,12 +2399,14 @@
|
||||
improves system performance, but it may also
|
||||
expose users to several CPU vulnerabilities.
|
||||
Equivalent to: nopti [X86,PPC]
|
||||
kpti=0 [ARM64]
|
||||
nospectre_v1 [PPC]
|
||||
nobp=0 [S390]
|
||||
nospectre_v1 [X86]
|
||||
nospectre_v2 [X86,PPC,S390]
|
||||
nospectre_v2 [X86,PPC,S390,ARM64]
|
||||
spectre_v2_user=off [X86]
|
||||
spec_store_bypass_disable=off [X86,PPC]
|
||||
ssbd=force-off [ARM64]
|
||||
l1tf=off [X86]
|
||||
mds=off [X86]
|
||||
|
||||
@@ -2745,10 +2747,10 @@
|
||||
(bounds check bypass). With this option data leaks
|
||||
are possible in the system.
|
||||
|
||||
nospectre_v2 [X86,PPC_FSL_BOOK3E] Disable all mitigations for the Spectre variant 2
|
||||
(indirect branch prediction) vulnerability. System may
|
||||
allow data leaks with this option, which is equivalent
|
||||
to spectre_v2=off.
|
||||
nospectre_v2 [X86,PPC_FSL_BOOK3E,ARM64] Disable all mitigations for
|
||||
the Spectre variant 2 (indirect branch prediction)
|
||||
vulnerability. System may allow data leaks with this
|
||||
option.
|
||||
|
||||
nospec_store_bypass_disable
|
||||
[HW] Disable all mitigations for the Speculative Store Bypass vulnerability
|
||||
|
||||
@@ -111,6 +111,9 @@ infrastructure:
|
||||
| Name | bits | visible |
|
||||
|--------------------------------------------------|
|
||||
| RES0 | [63-48] | n |
|
||||
| TS | [55-52] | y |
|
||||
|--------------------------------------------------|
|
||||
| FHM | [51-48] | y |
|
||||
|--------------------------------------------------|
|
||||
| DP | [47-44] | y |
|
||||
|--------------------------------------------------|
|
||||
@@ -133,8 +136,6 @@ infrastructure:
|
||||
| SHA1 | [11-8] | y |
|
||||
|--------------------------------------------------|
|
||||
| AES | [7-4] | y |
|
||||
|--------------------------------------------------|
|
||||
| RES0 | [3-0] | n |
|
||||
x--------------------------------------------------x
|
||||
|
||||
|
||||
@@ -142,7 +143,9 @@ infrastructure:
|
||||
x--------------------------------------------------x
|
||||
| Name | bits | visible |
|
||||
|--------------------------------------------------|
|
||||
| RES0 | [63-28] | n |
|
||||
| DIT | [51-48] | y |
|
||||
|--------------------------------------------------|
|
||||
| SVE | [35-32] | y |
|
||||
|--------------------------------------------------|
|
||||
| GIC | [27-24] | n |
|
||||
|--------------------------------------------------|
|
||||
@@ -193,6 +196,14 @@ infrastructure:
|
||||
| DPB | [3-0] | y |
|
||||
x--------------------------------------------------x
|
||||
|
||||
5) ID_AA64MMFR2_EL1 - Memory model feature register 2
|
||||
|
||||
x--------------------------------------------------x
|
||||
| Name | bits | visible |
|
||||
|--------------------------------------------------|
|
||||
| AT | [35-32] | y |
|
||||
x--------------------------------------------------x
|
||||
|
||||
Appendix I: Example
|
||||
---------------------------
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 14
|
||||
SUBLEVEL = 150
|
||||
SUBLEVEL = 151
|
||||
EXTRAVERSION =
|
||||
NAME = Petit Gorille
|
||||
|
||||
|
||||
@@ -1118,6 +1118,8 @@
|
||||
ti,hwmods = "dss_dispc";
|
||||
clocks = <&disp_clk>;
|
||||
clock-names = "fck";
|
||||
|
||||
max-memory-bandwidth = <230000000>;
|
||||
};
|
||||
|
||||
rfbi: rfbi@4832a800 {
|
||||
|
||||
@@ -966,7 +966,8 @@ static struct omap_hwmod_class_sysconfig am33xx_timer_sysc = {
|
||||
.rev_offs = 0x0000,
|
||||
.sysc_offs = 0x0010,
|
||||
.syss_offs = 0x0014,
|
||||
.sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
|
||||
.sysc_flags = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
|
||||
SYSC_HAS_RESET_STATUS,
|
||||
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
|
||||
SIDLE_SMART_WKUP),
|
||||
.sysc_fields = &omap_hwmod_sysc_type2,
|
||||
|
||||
@@ -31,7 +31,9 @@ void __init xen_efi_runtime_setup(void)
|
||||
efi.get_variable = xen_efi_get_variable;
|
||||
efi.get_next_variable = xen_efi_get_next_variable;
|
||||
efi.set_variable = xen_efi_set_variable;
|
||||
efi.set_variable_nonblocking = xen_efi_set_variable;
|
||||
efi.query_variable_info = xen_efi_query_variable_info;
|
||||
efi.query_variable_info_nonblocking = xen_efi_query_variable_info;
|
||||
efi.update_capsule = xen_efi_update_capsule;
|
||||
efi.query_capsule_caps = xen_efi_query_capsule_caps;
|
||||
efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count;
|
||||
|
||||
@@ -50,6 +50,7 @@ config ARM64
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select GENERIC_CPU_AUTOPROBE
|
||||
select GENERIC_CPU_VULNERABILITIES
|
||||
select GENERIC_EARLY_IOREMAP
|
||||
select GENERIC_IDLE_POLL_SETUP
|
||||
select GENERIC_IRQ_PROBE
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
#define ARM64_HAS_DCPOP 21
|
||||
#define ARM64_UNMAP_KERNEL_AT_EL0 23
|
||||
#define ARM64_HARDEN_BRANCH_PREDICTOR 24
|
||||
#define ARM64_HARDEN_BP_POST_GUEST_EXIT 25
|
||||
#define ARM64_SSBD 26
|
||||
#define ARM64_MISMATCHED_CACHE_TYPE 27
|
||||
#define ARM64_SSBD 25
|
||||
#define ARM64_MISMATCHED_CACHE_TYPE 26
|
||||
#define ARM64_SSBS 27
|
||||
|
||||
#define ARM64_NCAPS 28
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define __ASM_CPUFEATURE_H
|
||||
|
||||
#include <asm/cpucaps.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
@@ -85,24 +86,227 @@ 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 three 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.
|
||||
* Or
|
||||
* c) SCOPE_BOOT_CPU: Check only on the primary boot CPU to detect the
|
||||
* feature. This category is for features that are "finalised"
|
||||
* (or used) by the kernel very early even before the SMP cpus
|
||||
* are brought up.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* At the moment there are two passes of finalising the capabilities.
|
||||
* a) Boot CPU scope capabilities - Finalised by primary boot CPU via
|
||||
* setup_boot_cpu_capabilities().
|
||||
* b) Everything except (a) - Run via setup_system_capabilities().
|
||||
*
|
||||
* 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 newly booted CPU is verified
|
||||
* against the capabilities that have been finalised by the time it
|
||||
* boots.
|
||||
*
|
||||
* a) SCOPE_BOOT_CPU : All CPUs are verified against the capability
|
||||
* except for the primary boot CPU.
|
||||
*
|
||||
* b) SCOPE_LOCAL_CPU, SCOPE_SYSTEM: All CPUs hotplugged on by the
|
||||
* user after the kernel boot are verified against the capability.
|
||||
*
|
||||
* 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 any local CPU vs System wide vs the primary boot CPU
|
||||
*/
|
||||
#define ARM64_CPUCAP_SCOPE_LOCAL_CPU ((u16)BIT(0))
|
||||
#define ARM64_CPUCAP_SCOPE_SYSTEM ((u16)BIT(1))
|
||||
/*
|
||||
* The capabilitiy is detected on the Boot CPU and is used by kernel
|
||||
* during early boot. i.e, the capability should be "detected" and
|
||||
* "enabled" as early as possibly on all booting CPUs.
|
||||
*/
|
||||
#define ARM64_CPUCAP_SCOPE_BOOT_CPU ((u16)BIT(2))
|
||||
#define ARM64_CPUCAP_SCOPE_MASK \
|
||||
(ARM64_CPUCAP_SCOPE_SYSTEM | \
|
||||
ARM64_CPUCAP_SCOPE_LOCAL_CPU | \
|
||||
ARM64_CPUCAP_SCOPE_BOOT_CPU)
|
||||
|
||||
#define SCOPE_SYSTEM ARM64_CPUCAP_SCOPE_SYSTEM
|
||||
#define SCOPE_LOCAL_CPU ARM64_CPUCAP_SCOPE_LOCAL_CPU
|
||||
#define SCOPE_BOOT_CPU ARM64_CPUCAP_SCOPE_BOOT_CPU
|
||||
#define SCOPE_ALL ARM64_CPUCAP_SCOPE_MASK
|
||||
|
||||
/*
|
||||
* 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)
|
||||
/*
|
||||
* CPU feature detected at boot time based on feature of one or more CPUs.
|
||||
* All possible conflicts for a late CPU are ignored.
|
||||
*/
|
||||
#define ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE \
|
||||
(ARM64_CPUCAP_SCOPE_LOCAL_CPU | \
|
||||
ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU | \
|
||||
ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
|
||||
|
||||
/*
|
||||
* CPU feature detected at boot time, on one or more CPUs. A late CPU
|
||||
* is not allowed to have the capability when the system doesn't have it.
|
||||
* It is Ok for a late CPU to miss the feature.
|
||||
*/
|
||||
#define ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE \
|
||||
(ARM64_CPUCAP_SCOPE_LOCAL_CPU | \
|
||||
ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU)
|
||||
|
||||
/*
|
||||
* CPU feature used early in the boot based on the boot CPU. All secondary
|
||||
* CPUs must match the state of the capability as detected by the boot CPU.
|
||||
*/
|
||||
#define ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE ARM64_CPUCAP_SCOPE_BOOT_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;
|
||||
@@ -114,6 +318,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;
|
||||
@@ -225,15 +446,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_sanitised_ftr_reg(u32 id);
|
||||
|
||||
@@ -279,11 +493,7 @@ static inline int arm64_get_ssbd_state(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_SSBD
|
||||
void arm64_set_ssbd_mitigation(bool state);
|
||||
#else
|
||||
static inline void arm64_set_ssbd_mitigation(bool state) {}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
||||
@@ -85,6 +85,8 @@
|
||||
#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 APM_CPU_PART_POTENZA 0x000
|
||||
|
||||
@@ -108,6 +110,8 @@
|
||||
#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_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_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
|
||||
@@ -125,6 +129,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
|
||||
|
||||
@@ -70,8 +70,6 @@ extern u32 __kvm_get_mdcr_el2(void);
|
||||
|
||||
extern u32 __init_stage2_translation(void);
|
||||
|
||||
extern void __qcom_hyp_sanitize_btac_predictors(void);
|
||||
|
||||
/* Home-grown __this_cpu_{ptr,read} variants that always work at HYP */
|
||||
#define __hyp_this_cpu_ptr(sym) \
|
||||
({ \
|
||||
|
||||
@@ -356,6 +356,8 @@ struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
|
||||
void __kvm_set_tpidr_el2(u64 tpidr_el2);
|
||||
DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
|
||||
|
||||
void __kvm_enable_ssbs(void);
|
||||
|
||||
static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
|
||||
unsigned long hyp_stack_ptr,
|
||||
unsigned long vector_ptr)
|
||||
@@ -380,6 +382,15 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
|
||||
- (u64)kvm_ksym_ref(kvm_host_cpu_state);
|
||||
|
||||
kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2);
|
||||
|
||||
/*
|
||||
* Disabling SSBD on a non-VHE system requires us to enable SSBS
|
||||
* at EL2.
|
||||
*/
|
||||
if (!has_vhe() && this_cpu_has_cap(ARM64_SSBS) &&
|
||||
arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) {
|
||||
kvm_call_hyp(__kvm_enable_ssbs);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void kvm_arch_hardware_unsetup(void) {}
|
||||
|
||||
@@ -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>
|
||||
@@ -147,11 +148,25 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
|
||||
regs->pc = pc;
|
||||
}
|
||||
|
||||
static inline void set_ssbs_bit(struct pt_regs *regs)
|
||||
{
|
||||
regs->pstate |= PSR_SSBS_BIT;
|
||||
}
|
||||
|
||||
static inline void set_compat_ssbs_bit(struct pt_regs *regs)
|
||||
{
|
||||
regs->pstate |= PSR_AA32_SSBS_BIT;
|
||||
}
|
||||
|
||||
static inline void start_thread(struct pt_regs *regs, unsigned long pc,
|
||||
unsigned long sp)
|
||||
{
|
||||
start_thread_common(regs, pc);
|
||||
regs->pstate = PSR_MODE_EL0t;
|
||||
|
||||
if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
|
||||
set_ssbs_bit(regs);
|
||||
|
||||
regs->sp = sp;
|
||||
}
|
||||
|
||||
@@ -168,6 +183,9 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
|
||||
regs->pstate |= COMPAT_PSR_E_BIT;
|
||||
#endif
|
||||
|
||||
if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
|
||||
set_compat_ssbs_bit(regs);
|
||||
|
||||
regs->compat_sp = sp;
|
||||
}
|
||||
#endif
|
||||
@@ -222,8 +240,8 @@ static inline void spin_lock_prefetch(const void *ptr)
|
||||
|
||||
#endif
|
||||
|
||||
int cpu_enable_pan(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 */
|
||||
|
||||
@@ -35,7 +35,38 @@
|
||||
#define COMPAT_PTRACE_GETHBPREGS 29
|
||||
#define COMPAT_PTRACE_SETHBPREGS 30
|
||||
|
||||
/* AArch32 CPSR bits */
|
||||
/* SPSR_ELx bits for exceptions taken from AArch32 */
|
||||
#define PSR_AA32_MODE_MASK 0x0000001f
|
||||
#define PSR_AA32_MODE_USR 0x00000010
|
||||
#define PSR_AA32_MODE_FIQ 0x00000011
|
||||
#define PSR_AA32_MODE_IRQ 0x00000012
|
||||
#define PSR_AA32_MODE_SVC 0x00000013
|
||||
#define PSR_AA32_MODE_ABT 0x00000017
|
||||
#define PSR_AA32_MODE_HYP 0x0000001a
|
||||
#define PSR_AA32_MODE_UND 0x0000001b
|
||||
#define PSR_AA32_MODE_SYS 0x0000001f
|
||||
#define PSR_AA32_T_BIT 0x00000020
|
||||
#define PSR_AA32_F_BIT 0x00000040
|
||||
#define PSR_AA32_I_BIT 0x00000080
|
||||
#define PSR_AA32_A_BIT 0x00000100
|
||||
#define PSR_AA32_E_BIT 0x00000200
|
||||
#define PSR_AA32_SSBS_BIT 0x00800000
|
||||
#define PSR_AA32_DIT_BIT 0x01000000
|
||||
#define PSR_AA32_Q_BIT 0x08000000
|
||||
#define PSR_AA32_V_BIT 0x10000000
|
||||
#define PSR_AA32_C_BIT 0x20000000
|
||||
#define PSR_AA32_Z_BIT 0x40000000
|
||||
#define PSR_AA32_N_BIT 0x80000000
|
||||
#define PSR_AA32_IT_MASK 0x0600fc00 /* If-Then execution state mask */
|
||||
#define PSR_AA32_GE_MASK 0x000f0000
|
||||
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define PSR_AA32_ENDSTATE PSR_AA32_E_BIT
|
||||
#else
|
||||
#define PSR_AA32_ENDSTATE 0
|
||||
#endif
|
||||
|
||||
/* AArch32 CPSR bits, as seen in AArch32 */
|
||||
#define COMPAT_PSR_MODE_MASK 0x0000001f
|
||||
#define COMPAT_PSR_MODE_USR 0x00000010
|
||||
#define COMPAT_PSR_MODE_FIQ 0x00000011
|
||||
@@ -50,6 +81,7 @@
|
||||
#define COMPAT_PSR_I_BIT 0x00000080
|
||||
#define COMPAT_PSR_A_BIT 0x00000100
|
||||
#define COMPAT_PSR_E_BIT 0x00000200
|
||||
#define COMPAT_PSR_DIT_BIT 0x00200000
|
||||
#define COMPAT_PSR_J_BIT 0x01000000
|
||||
#define COMPAT_PSR_Q_BIT 0x08000000
|
||||
#define COMPAT_PSR_V_BIT 0x10000000
|
||||
@@ -111,6 +143,30 @@
|
||||
#define compat_sp_fiq regs[29]
|
||||
#define compat_lr_fiq regs[30]
|
||||
|
||||
static inline unsigned long compat_psr_to_pstate(const unsigned long psr)
|
||||
{
|
||||
unsigned long pstate;
|
||||
|
||||
pstate = psr & ~COMPAT_PSR_DIT_BIT;
|
||||
|
||||
if (psr & COMPAT_PSR_DIT_BIT)
|
||||
pstate |= PSR_AA32_DIT_BIT;
|
||||
|
||||
return pstate;
|
||||
}
|
||||
|
||||
static inline unsigned long pstate_to_compat_psr(const unsigned long pstate)
|
||||
{
|
||||
unsigned long psr;
|
||||
|
||||
psr = pstate & ~PSR_AA32_DIT_BIT;
|
||||
|
||||
if (pstate & PSR_AA32_DIT_BIT)
|
||||
psr |= COMPAT_PSR_DIT_BIT;
|
||||
|
||||
return psr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This struct defines the way the registers are stored on the stack during an
|
||||
* exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef __ASM_SYSREG_H
|
||||
#define __ASM_SYSREG_H
|
||||
|
||||
#include <asm/compiler.h>
|
||||
#include <linux/stringify.h>
|
||||
|
||||
/*
|
||||
@@ -85,11 +86,14 @@
|
||||
|
||||
#define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4)
|
||||
#define REG_PSTATE_UAO_IMM sys_reg(0, 0, 4, 0, 3)
|
||||
#define REG_PSTATE_SSBS_IMM sys_reg(0, 3, 4, 0, 1)
|
||||
|
||||
#define SET_PSTATE_PAN(x) __emit_inst(0xd5000000 | REG_PSTATE_PAN_IMM | \
|
||||
(!!x)<<8 | 0x1f)
|
||||
#define SET_PSTATE_UAO(x) __emit_inst(0xd5000000 | REG_PSTATE_UAO_IMM | \
|
||||
(!!x)<<8 | 0x1f)
|
||||
#define SET_PSTATE_SSBS(x) __emit_inst(0xd5000000 | REG_PSTATE_SSBS_IMM | \
|
||||
(!!x)<<8 | 0x1f)
|
||||
|
||||
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
|
||||
#define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2)
|
||||
@@ -296,28 +300,90 @@
|
||||
#define SYS_ICH_LR15_EL2 __SYS__LR8_EL2(7)
|
||||
|
||||
/* Common SCTLR_ELx flags. */
|
||||
#define SCTLR_ELx_DSSBS (1UL << 44)
|
||||
#define SCTLR_ELx_EE (1 << 25)
|
||||
#define SCTLR_ELx_WXN (1 << 19)
|
||||
#define SCTLR_ELx_I (1 << 12)
|
||||
#define SCTLR_ELx_SA (1 << 3)
|
||||
#define SCTLR_ELx_C (1 << 2)
|
||||
#define SCTLR_ELx_A (1 << 1)
|
||||
#define SCTLR_ELx_M 1
|
||||
|
||||
#define SCTLR_EL2_RES1 ((1 << 4) | (1 << 5) | (1 << 11) | (1 << 16) | \
|
||||
(1 << 18) | (1 << 22) | (1 << 23) | (1 << 28) | \
|
||||
(1 << 29))
|
||||
|
||||
#define SCTLR_ELx_FLAGS (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \
|
||||
SCTLR_ELx_SA | SCTLR_ELx_I)
|
||||
|
||||
/* SCTLR_EL2 specific flags. */
|
||||
#define SCTLR_EL2_RES1 ((1 << 4) | (1 << 5) | (1 << 11) | (1 << 16) | \
|
||||
(1 << 18) | (1 << 22) | (1 << 23) | (1 << 28) | \
|
||||
(1 << 29))
|
||||
#define SCTLR_EL2_RES0 ((1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | \
|
||||
(1 << 10) | (1 << 13) | (1 << 14) | (1 << 15) | \
|
||||
(1 << 17) | (1 << 20) | (1 << 21) | (1 << 24) | \
|
||||
(1 << 26) | (1 << 27) | (1 << 30) | (1 << 31) | \
|
||||
(0xffffefffUL << 32))
|
||||
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define ENDIAN_SET_EL2 SCTLR_ELx_EE
|
||||
#define ENDIAN_CLEAR_EL2 0
|
||||
#else
|
||||
#define ENDIAN_SET_EL2 0
|
||||
#define ENDIAN_CLEAR_EL2 SCTLR_ELx_EE
|
||||
#endif
|
||||
|
||||
/* SCTLR_EL2 value used for the hyp-stub */
|
||||
#define SCTLR_EL2_SET (ENDIAN_SET_EL2 | SCTLR_EL2_RES1)
|
||||
#define SCTLR_EL2_CLEAR (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \
|
||||
SCTLR_ELx_SA | SCTLR_ELx_I | SCTLR_ELx_WXN | \
|
||||
SCTLR_ELx_DSSBS | ENDIAN_CLEAR_EL2 | SCTLR_EL2_RES0)
|
||||
|
||||
#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffffffffffff
|
||||
#error "Inconsistent SCTLR_EL2 set/clear bits"
|
||||
#endif
|
||||
|
||||
/* SCTLR_EL1 specific flags. */
|
||||
#define SCTLR_EL1_UCI (1 << 26)
|
||||
#define SCTLR_EL1_E0E (1 << 24)
|
||||
#define SCTLR_EL1_SPAN (1 << 23)
|
||||
#define SCTLR_EL1_NTWE (1 << 18)
|
||||
#define SCTLR_EL1_NTWI (1 << 16)
|
||||
#define SCTLR_EL1_UCT (1 << 15)
|
||||
#define SCTLR_EL1_DZE (1 << 14)
|
||||
#define SCTLR_EL1_UMA (1 << 9)
|
||||
#define SCTLR_EL1_SED (1 << 8)
|
||||
#define SCTLR_EL1_ITD (1 << 7)
|
||||
#define SCTLR_EL1_CP15BEN (1 << 5)
|
||||
#define SCTLR_EL1_SA0 (1 << 4)
|
||||
|
||||
#define SCTLR_EL1_RES1 ((1 << 11) | (1 << 20) | (1 << 22) | (1 << 28) | \
|
||||
(1 << 29))
|
||||
#define SCTLR_EL1_RES0 ((1 << 6) | (1 << 10) | (1 << 13) | (1 << 17) | \
|
||||
(1 << 21) | (1 << 27) | (1 << 30) | (1 << 31) | \
|
||||
(0xffffefffUL << 32))
|
||||
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define ENDIAN_SET_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE)
|
||||
#define ENDIAN_CLEAR_EL1 0
|
||||
#else
|
||||
#define ENDIAN_SET_EL1 0
|
||||
#define ENDIAN_CLEAR_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE)
|
||||
#endif
|
||||
|
||||
#define SCTLR_EL1_SET (SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA |\
|
||||
SCTLR_EL1_SA0 | SCTLR_EL1_SED | SCTLR_ELx_I |\
|
||||
SCTLR_EL1_DZE | SCTLR_EL1_UCT | SCTLR_EL1_NTWI |\
|
||||
SCTLR_EL1_NTWE | SCTLR_EL1_SPAN | ENDIAN_SET_EL1 |\
|
||||
SCTLR_EL1_UCI | SCTLR_EL1_RES1)
|
||||
#define SCTLR_EL1_CLEAR (SCTLR_ELx_A | SCTLR_EL1_CP15BEN | SCTLR_EL1_ITD |\
|
||||
SCTLR_EL1_UMA | SCTLR_ELx_WXN | ENDIAN_CLEAR_EL1 |\
|
||||
SCTLR_ELx_DSSBS | SCTLR_EL1_RES0)
|
||||
|
||||
#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffffffffffff
|
||||
#error "Inconsistent SCTLR_EL1 set/clear bits"
|
||||
#endif
|
||||
|
||||
/* id_aa64isar0 */
|
||||
#define ID_AA64ISAR0_TS_SHIFT 52
|
||||
#define ID_AA64ISAR0_FHM_SHIFT 48
|
||||
#define ID_AA64ISAR0_DP_SHIFT 44
|
||||
#define ID_AA64ISAR0_SM4_SHIFT 40
|
||||
#define ID_AA64ISAR0_SM3_SHIFT 36
|
||||
@@ -338,6 +404,7 @@
|
||||
/* id_aa64pfr0 */
|
||||
#define ID_AA64PFR0_CSV3_SHIFT 60
|
||||
#define ID_AA64PFR0_CSV2_SHIFT 56
|
||||
#define ID_AA64PFR0_DIT_SHIFT 48
|
||||
#define ID_AA64PFR0_GIC_SHIFT 24
|
||||
#define ID_AA64PFR0_ASIMD_SHIFT 20
|
||||
#define ID_AA64PFR0_FP_SHIFT 16
|
||||
@@ -354,6 +421,13 @@
|
||||
#define ID_AA64PFR0_EL0_64BIT_ONLY 0x1
|
||||
#define ID_AA64PFR0_EL0_32BIT_64BIT 0x2
|
||||
|
||||
/* id_aa64pfr1 */
|
||||
#define ID_AA64PFR1_SSBS_SHIFT 4
|
||||
|
||||
#define ID_AA64PFR1_SSBS_PSTATE_NI 0
|
||||
#define ID_AA64PFR1_SSBS_PSTATE_ONLY 1
|
||||
#define ID_AA64PFR1_SSBS_PSTATE_INSNS 2
|
||||
|
||||
/* id_aa64mmfr0 */
|
||||
#define ID_AA64MMFR0_TGRAN4_SHIFT 28
|
||||
#define ID_AA64MMFR0_TGRAN64_SHIFT 24
|
||||
@@ -383,6 +457,7 @@
|
||||
#define ID_AA64MMFR1_VMIDBITS_16 2
|
||||
|
||||
/* id_aa64mmfr2 */
|
||||
#define ID_AA64MMFR2_AT_SHIFT 32
|
||||
#define ID_AA64MMFR2_LVA_SHIFT 16
|
||||
#define ID_AA64MMFR2_IESB_SHIFT 12
|
||||
#define ID_AA64MMFR2_LSM_SHIFT 8
|
||||
@@ -467,6 +542,7 @@
|
||||
|
||||
#else
|
||||
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define __DEFINE_MRS_MSR_S_REGNUM \
|
||||
@@ -538,6 +614,17 @@
|
||||
asm volatile(__msr_s(r, __val)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Modify bits in a sysreg. Bits in the clear mask are zeroed, then bits in the
|
||||
* set mask are set. Other bits are left as-is.
|
||||
*/
|
||||
#define sysreg_clear_set(sysreg, clear, set) do { \
|
||||
u64 __scs_val = read_sysreg(sysreg); \
|
||||
u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set); \
|
||||
if (__scs_new != __scs_val) \
|
||||
write_sysreg(__scs_new, sysreg); \
|
||||
} while (0)
|
||||
|
||||
static inline void config_sctlr_el1(u32 clear, u32 set)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -102,12 +102,6 @@ static inline bool has_vhe(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_VHE
|
||||
extern void verify_cpu_run_el(void);
|
||||
#else
|
||||
static inline void verify_cpu_run_el(void) {}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* ! __ASM__VIRT_H */
|
||||
|
||||
@@ -42,5 +42,12 @@
|
||||
#define HWCAP_SM4 (1 << 19)
|
||||
#define HWCAP_ASIMDDP (1 << 20)
|
||||
#define HWCAP_SHA512 (1 << 21)
|
||||
#define HWCAP_SVE (1 << 22)
|
||||
#define HWCAP_ASIMDFHM (1 << 23)
|
||||
#define HWCAP_DIT (1 << 24)
|
||||
#define HWCAP_USCAT (1 << 25)
|
||||
#define HWCAP_ILRCPC (1 << 26)
|
||||
#define HWCAP_FLAGM (1 << 27)
|
||||
#define HWCAP_SSBS (1 << 28)
|
||||
|
||||
#endif /* _UAPI__ASM_HWCAP_H */
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#define PSR_I_BIT 0x00000080
|
||||
#define PSR_A_BIT 0x00000100
|
||||
#define PSR_D_BIT 0x00000200
|
||||
#define PSR_SSBS_BIT 0x00001000
|
||||
#define PSR_PAN_BIT 0x00400000
|
||||
#define PSR_UAO_BIT 0x00800000
|
||||
#define PSR_Q_BIT 0x08000000
|
||||
|
||||
@@ -55,29 +55,14 @@ ENTRY(__bp_harden_hyp_vecs_start)
|
||||
.endr
|
||||
ENTRY(__bp_harden_hyp_vecs_end)
|
||||
|
||||
ENTRY(__qcom_hyp_sanitize_link_stack_start)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
.rept 16
|
||||
bl . + 4
|
||||
.endr
|
||||
ldp x29, x30, [sp], #16
|
||||
ENTRY(__qcom_hyp_sanitize_link_stack_end)
|
||||
|
||||
.macro smccc_workaround_1 inst
|
||||
ENTRY(__smccc_workaround_1_smc_start)
|
||||
sub sp, sp, #(8 * 4)
|
||||
stp x2, x3, [sp, #(8 * 0)]
|
||||
stp x0, x1, [sp, #(8 * 2)]
|
||||
mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1
|
||||
\inst #0
|
||||
smc #0
|
||||
ldp x2, x3, [sp, #(8 * 0)]
|
||||
ldp x0, x1, [sp, #(8 * 2)]
|
||||
add sp, sp, #(8 * 4)
|
||||
.endm
|
||||
|
||||
ENTRY(__smccc_workaround_1_smc_start)
|
||||
smccc_workaround_1 smc
|
||||
ENTRY(__smccc_workaround_1_smc_end)
|
||||
|
||||
ENTRY(__smccc_workaround_1_hvc_start)
|
||||
smccc_workaround_1 hvc
|
||||
ENTRY(__smccc_workaround_1_hvc_end)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/cpufeature.h>
|
||||
@@ -26,10 +27,18 @@
|
||||
static bool __maybe_unused
|
||||
is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
{
|
||||
u32 midr = read_cpuid_id();
|
||||
|
||||
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);
|
||||
return is_midr_in_range(midr, &entry->midr_range);
|
||||
}
|
||||
|
||||
static bool __maybe_unused
|
||||
is_affected_midr_range_list(const struct arm64_cpu_capabilities *entry,
|
||||
int scope)
|
||||
{
|
||||
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
|
||||
return is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list);
|
||||
}
|
||||
|
||||
static bool __maybe_unused
|
||||
@@ -43,7 +52,7 @@ is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
model &= MIDR_IMPLEMENTOR_MASK | (0xf00 << MIDR_PARTNUM_SHIFT) |
|
||||
MIDR_ARCHITECTURE_MASK;
|
||||
|
||||
return model == entry->midr_model;
|
||||
return model == entry->midr_range.model;
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -61,26 +70,21 @@ has_mismatched_cache_type(const struct arm64_cpu_capabilities *entry,
|
||||
(arm64_ftr_reg_ctrel0.sys_val & mask);
|
||||
}
|
||||
|
||||
static int cpu_enable_trap_ctr_access(void *__unused)
|
||||
static void
|
||||
cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *__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 __qcom_hyp_sanitize_link_stack_start[];
|
||||
extern char __qcom_hyp_sanitize_link_stack_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)
|
||||
@@ -94,9 +98,9 @@ static void __copy_hyp_vect_bpi(int slot, const char *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 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);
|
||||
@@ -123,14 +127,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
|
||||
spin_unlock(&bp_lock);
|
||||
}
|
||||
#else
|
||||
#define __qcom_hyp_sanitize_link_stack_start NULL
|
||||
#define __qcom_hyp_sanitize_link_stack_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,
|
||||
static void install_bp_hardening_cb(bp_hardening_cb_t fn,
|
||||
const char *hyp_vecs_start,
|
||||
const char *hyp_vecs_end)
|
||||
{
|
||||
@@ -138,23 +138,6 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t 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>
|
||||
@@ -169,49 +152,6 @@ 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 ((int)res.a0 < 0)
|
||||
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 ((int)res.a0 < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
static void qcom_link_stack_sanitization(void)
|
||||
{
|
||||
u64 tmp;
|
||||
@@ -224,22 +164,83 @@ static void qcom_link_stack_sanitization(void)
|
||||
: "=&r" (tmp));
|
||||
}
|
||||
|
||||
static int qcom_enable_link_stack_sanitization(void *data)
|
||||
static bool __nospectre_v2;
|
||||
static int __init parse_nospectre_v2(char *str)
|
||||
{
|
||||
const struct arm64_cpu_capabilities *entry = data;
|
||||
|
||||
install_bp_hardening_cb(entry, qcom_link_stack_sanitization,
|
||||
__qcom_hyp_sanitize_link_stack_start,
|
||||
__qcom_hyp_sanitize_link_stack_end);
|
||||
|
||||
__nospectre_v2 = true;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */
|
||||
early_param("nospectre_v2", parse_nospectre_v2);
|
||||
|
||||
/*
|
||||
* -1: No workaround
|
||||
* 0: No workaround required
|
||||
* 1: Workaround installed
|
||||
*/
|
||||
static int detect_harden_bp_fw(void)
|
||||
{
|
||||
bp_hardening_cb_t cb;
|
||||
void *smccc_start, *smccc_end;
|
||||
struct arm_smccc_res res;
|
||||
u32 midr = read_cpuid_id();
|
||||
|
||||
if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
|
||||
return -1;
|
||||
|
||||
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);
|
||||
switch ((int)res.a0) {
|
||||
case 1:
|
||||
/* Firmware says we're just fine */
|
||||
return 0;
|
||||
case 0:
|
||||
cb = call_hvc_arch_workaround_1;
|
||||
/* This is a guest, no need to patch KVM vectors */
|
||||
smccc_start = NULL;
|
||||
smccc_end = NULL;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSCI_CONDUIT_SMC:
|
||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
|
||||
ARM_SMCCC_ARCH_WORKAROUND_1, &res);
|
||||
switch ((int)res.a0) {
|
||||
case 1:
|
||||
/* Firmware says we're just fine */
|
||||
return 0;
|
||||
case 0:
|
||||
cb = call_smc_arch_workaround_1;
|
||||
smccc_start = __smccc_workaround_1_smc_start;
|
||||
smccc_end = __smccc_workaround_1_smc_end;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) ||
|
||||
((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1))
|
||||
cb = qcom_link_stack_sanitization;
|
||||
|
||||
if (IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR))
|
||||
install_bp_hardening_cb(cb, smccc_start, smccc_end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_SSBD
|
||||
DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required);
|
||||
|
||||
int ssbd_state __read_mostly = ARM64_SSBD_KERNEL;
|
||||
static bool __ssb_safe = true;
|
||||
|
||||
static const struct ssbd_options {
|
||||
const char *str;
|
||||
@@ -309,6 +310,19 @@ void __init arm64_enable_wa2_handling(struct alt_instr *alt,
|
||||
|
||||
void arm64_set_ssbd_mitigation(bool state)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_ARM64_SSBD)) {
|
||||
pr_info_once("SSBD disabled by kernel configuration\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this_cpu_has_cap(ARM64_SSBS)) {
|
||||
if (state)
|
||||
asm volatile(SET_PSTATE_SSBS(0));
|
||||
else
|
||||
asm volatile(SET_PSTATE_SSBS(1));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (psci_ops.conduit) {
|
||||
case PSCI_CONDUIT_HVC:
|
||||
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL);
|
||||
@@ -330,11 +344,28 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
|
||||
struct arm_smccc_res res;
|
||||
bool required = true;
|
||||
s32 val;
|
||||
bool this_cpu_safe = false;
|
||||
|
||||
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
|
||||
|
||||
if (cpu_mitigations_off())
|
||||
ssbd_state = ARM64_SSBD_FORCE_DISABLE;
|
||||
|
||||
/* delay setting __ssb_safe until we get a firmware response */
|
||||
if (is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list))
|
||||
this_cpu_safe = true;
|
||||
|
||||
if (this_cpu_has_cap(ARM64_SSBS)) {
|
||||
if (!this_cpu_safe)
|
||||
__ssb_safe = false;
|
||||
required = false;
|
||||
goto out_printmsg;
|
||||
}
|
||||
|
||||
if (psci_ops.smccc_version == SMCCC_VERSION_1_0) {
|
||||
ssbd_state = ARM64_SSBD_UNKNOWN;
|
||||
if (!this_cpu_safe)
|
||||
__ssb_safe = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -351,6 +382,8 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
|
||||
|
||||
default:
|
||||
ssbd_state = ARM64_SSBD_UNKNOWN;
|
||||
if (!this_cpu_safe)
|
||||
__ssb_safe = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -359,14 +392,18 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
|
||||
switch (val) {
|
||||
case SMCCC_RET_NOT_SUPPORTED:
|
||||
ssbd_state = ARM64_SSBD_UNKNOWN;
|
||||
if (!this_cpu_safe)
|
||||
__ssb_safe = false;
|
||||
return false;
|
||||
|
||||
/* machines with mixed mitigation requirements must not return this */
|
||||
case SMCCC_RET_NOT_REQUIRED:
|
||||
pr_info_once("%s mitigation not required\n", entry->desc);
|
||||
ssbd_state = ARM64_SSBD_MITIGATED;
|
||||
return false;
|
||||
|
||||
case SMCCC_RET_SUCCESS:
|
||||
__ssb_safe = false;
|
||||
required = true;
|
||||
break;
|
||||
|
||||
@@ -376,12 +413,13 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
|
||||
|
||||
default:
|
||||
WARN_ON(1);
|
||||
if (!this_cpu_safe)
|
||||
__ssb_safe = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ssbd_state) {
|
||||
case ARM64_SSBD_FORCE_DISABLE:
|
||||
pr_info_once("%s disabled from command-line\n", entry->desc);
|
||||
arm64_set_ssbd_mitigation(false);
|
||||
required = false;
|
||||
break;
|
||||
@@ -394,7 +432,6 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
|
||||
break;
|
||||
|
||||
case ARM64_SSBD_FORCE_ENABLE:
|
||||
pr_info_once("%s forced from command-line\n", entry->desc);
|
||||
arm64_set_ssbd_mitigation(true);
|
||||
required = true;
|
||||
break;
|
||||
@@ -404,23 +441,126 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
|
||||
break;
|
||||
}
|
||||
|
||||
out_printmsg:
|
||||
switch (ssbd_state) {
|
||||
case ARM64_SSBD_FORCE_DISABLE:
|
||||
pr_info_once("%s disabled from command-line\n", entry->desc);
|
||||
break;
|
||||
|
||||
case ARM64_SSBD_FORCE_ENABLE:
|
||||
pr_info_once("%s forced from command-line\n", entry->desc);
|
||||
break;
|
||||
}
|
||||
|
||||
return required;
|
||||
}
|
||||
#endif /* CONFIG_ARM64_SSBD */
|
||||
|
||||
#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
|
||||
/* known invulnerable cores */
|
||||
static const struct midr_range arm64_ssb_cpus[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
|
||||
{},
|
||||
};
|
||||
|
||||
#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)
|
||||
#define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
|
||||
.matches = is_affected_midr_range, \
|
||||
.midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max)
|
||||
|
||||
#define CAP_MIDR_ALL_VERSIONS(model) \
|
||||
.matches = is_affected_midr_range, \
|
||||
.midr_range = MIDR_ALL_VERSIONS(model)
|
||||
|
||||
#define MIDR_FIXED(rev, revidr_mask) \
|
||||
.fixed_revs = (struct arm64_midr_revidr[]){{ (rev), (revidr_mask) }, {}}
|
||||
|
||||
#define ERRATA_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
|
||||
CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)
|
||||
|
||||
#define CAP_MIDR_RANGE_LIST(list) \
|
||||
.matches = is_affected_midr_range_list, \
|
||||
.midr_range_list = list
|
||||
|
||||
/* Errata affecting a range of revisions of given model variant */
|
||||
#define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max) \
|
||||
ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
|
||||
|
||||
/* Errata affecting a single variant/revision of a model */
|
||||
#define ERRATA_MIDR_REV(model, var, rev) \
|
||||
ERRATA_MIDR_RANGE(model, var, rev, var, rev)
|
||||
|
||||
/* Errata affecting all variants/revisions of a given a model */
|
||||
#define ERRATA_MIDR_ALL_VERSIONS(model) \
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
|
||||
CAP_MIDR_ALL_VERSIONS(model)
|
||||
|
||||
/* Errata affecting a list of midr ranges, with same work around */
|
||||
#define ERRATA_MIDR_RANGE_LIST(midr_list) \
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
|
||||
CAP_MIDR_RANGE_LIST(midr_list)
|
||||
|
||||
/* Track overall mitigation state. We are only mitigated if all cores are ok */
|
||||
static bool __hardenbp_enab = true;
|
||||
static bool __spectrev2_safe = true;
|
||||
|
||||
/*
|
||||
* List of CPUs that do not need any Spectre-v2 mitigation at all.
|
||||
*/
|
||||
static const struct midr_range spectre_v2_safe_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Track overall bp hardening for all heterogeneous cores in the machine.
|
||||
* We are only considered "safe" if all booted cores are known safe.
|
||||
*/
|
||||
static bool __maybe_unused
|
||||
check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope)
|
||||
{
|
||||
int need_wa;
|
||||
|
||||
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
|
||||
|
||||
/* If the CPU has CSV2 set, we're safe */
|
||||
if (cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64PFR0_EL1),
|
||||
ID_AA64PFR0_CSV2_SHIFT))
|
||||
return false;
|
||||
|
||||
/* Alternatively, we have a list of unaffected CPUs */
|
||||
if (is_midr_in_range_list(read_cpuid_id(), spectre_v2_safe_list))
|
||||
return false;
|
||||
|
||||
/* Fallback to firmware detection */
|
||||
need_wa = detect_harden_bp_fw();
|
||||
if (!need_wa)
|
||||
return false;
|
||||
|
||||
__spectrev2_safe = false;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR)) {
|
||||
pr_warn_once("spectrev2 mitigation disabled by kernel configuration\n");
|
||||
__hardenbp_enab = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* forced off */
|
||||
if (__nospectre_v2 || cpu_mitigations_off()) {
|
||||
pr_info_once("spectrev2 mitigation disabled by command line option\n");
|
||||
__hardenbp_enab = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (need_wa < 0) {
|
||||
pr_warn_once("ARM_SMCCC_ARCH_WORKAROUND_1 missing from firmware\n");
|
||||
__hardenbp_enab = false;
|
||||
}
|
||||
|
||||
return (need_wa > 0);
|
||||
}
|
||||
|
||||
const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
#if defined(CONFIG_ARM64_ERRATUM_826319) || \
|
||||
@@ -430,8 +570,8 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* 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,
|
||||
ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 2),
|
||||
.cpu_enable = cpu_enable_cache_maint_trap,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_819472
|
||||
@@ -439,8 +579,8 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* 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,
|
||||
ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 1),
|
||||
.cpu_enable = cpu_enable_cache_maint_trap,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_832075
|
||||
@@ -448,9 +588,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* 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)),
|
||||
ERRATA_MIDR_RANGE(MIDR_CORTEX_A57,
|
||||
0, 0,
|
||||
1, 2),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_834220
|
||||
@@ -458,9 +598,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* 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)),
|
||||
ERRATA_MIDR_RANGE(MIDR_CORTEX_A57,
|
||||
0, 0,
|
||||
1, 2),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_845719
|
||||
@@ -468,7 +608,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* Cortex-A53 r0p[01234] */
|
||||
.desc = "ARM erratum 845719",
|
||||
.capability = ARM64_WORKAROUND_845719,
|
||||
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04),
|
||||
ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_23154
|
||||
@@ -476,7 +616,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* Cavium ThunderX, pass 1.x */
|
||||
.desc = "Cavium erratum 23154",
|
||||
.capability = ARM64_WORKAROUND_CAVIUM_23154,
|
||||
MIDR_RANGE(MIDR_THUNDERX, 0x00, 0x01),
|
||||
ERRATA_MIDR_REV_RANGE(MIDR_THUNDERX, 0, 0, 1),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_27456
|
||||
@@ -484,15 +624,15 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* 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)),
|
||||
ERRATA_MIDR_RANGE(MIDR_THUNDERX,
|
||||
0, 0,
|
||||
1, 1),
|
||||
},
|
||||
{
|
||||
/* Cavium ThunderX, T81 pass 1.0 */
|
||||
.desc = "Cavium erratum 27456",
|
||||
.capability = ARM64_WORKAROUND_CAVIUM_27456,
|
||||
MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
|
||||
ERRATA_MIDR_REV(MIDR_THUNDERX_81XX, 0, 0),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_30115
|
||||
@@ -500,49 +640,48 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* 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),
|
||||
ERRATA_MIDR_RANGE(MIDR_THUNDERX,
|
||||
0, 0,
|
||||
1, 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),
|
||||
ERRATA_MIDR_REV_RANGE(MIDR_THUNDERX_81XX, 0, 0, 2),
|
||||
},
|
||||
{
|
||||
/* Cavium ThunderX, T83 pass 1.0 */
|
||||
.desc = "Cavium erratum 30115",
|
||||
.capability = ARM64_WORKAROUND_CAVIUM_30115,
|
||||
MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
|
||||
ERRATA_MIDR_REV(MIDR_THUNDERX_83XX, 0, 0),
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.desc = "Mismatched cache line size",
|
||||
.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
|
||||
.matches = has_mismatched_cache_type,
|
||||
.def_scope = SCOPE_LOCAL_CPU,
|
||||
.enable = cpu_enable_trap_ctr_access,
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
.cpu_enable = cpu_enable_trap_ctr_access,
|
||||
},
|
||||
{
|
||||
.desc = "Mismatched cache type",
|
||||
.capability = ARM64_MISMATCHED_CACHE_TYPE,
|
||||
.matches = has_mismatched_cache_type,
|
||||
.def_scope = SCOPE_LOCAL_CPU,
|
||||
.enable = cpu_enable_trap_ctr_access,
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
.cpu_enable = cpu_enable_trap_ctr_access,
|
||||
},
|
||||
#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)),
|
||||
ERRATA_MIDR_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
|
||||
},
|
||||
{
|
||||
.desc = "Qualcomm Technologies Kryo erratum 1003",
|
||||
.capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
|
||||
.def_scope = SCOPE_LOCAL_CPU,
|
||||
.midr_model = MIDR_QCOM_KRYO,
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
.midr_range.model = MIDR_QCOM_KRYO,
|
||||
.matches = is_kryo_midr,
|
||||
},
|
||||
#endif
|
||||
@@ -550,9 +689,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
{
|
||||
.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)),
|
||||
ERRATA_MIDR_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_858921
|
||||
@@ -560,100 +697,56 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
||||
/* Cortex-A73 all versions */
|
||||
.desc = "ARM erratum 858921",
|
||||
.capability = ARM64_WORKAROUND_858921,
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
|
||||
ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
|
||||
{
|
||||
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
|
||||
.enable = enable_smccc_arch_workaround_1,
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
.matches = check_branch_predictor,
|
||||
},
|
||||
{
|
||||
.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_QCOM_FALKOR_V1),
|
||||
.enable = qcom_enable_link_stack_sanitization,
|
||||
},
|
||||
{
|
||||
.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
|
||||
},
|
||||
{
|
||||
.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
|
||||
.enable = qcom_enable_link_stack_sanitization,
|
||||
},
|
||||
{
|
||||
.capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
|
||||
MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
|
||||
},
|
||||
{
|
||||
.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
|
||||
#ifdef CONFIG_ARM64_SSBD
|
||||
{
|
||||
.desc = "Speculative Store Bypass Disable",
|
||||
.def_scope = SCOPE_LOCAL_CPU,
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
.capability = ARM64_SSBD,
|
||||
.matches = has_ssbd_mitigation,
|
||||
.midr_range_list = arm64_ssb_cpus,
|
||||
},
|
||||
#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)
|
||||
ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
const struct arm64_cpu_capabilities *caps = arm64_errata;
|
||||
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (__spectrev2_safe)
|
||||
return sprintf(buf, "Not affected\n");
|
||||
|
||||
if (__hardenbp_enab)
|
||||
return sprintf(buf, "Mitigation: Branch predictor hardening\n");
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spec_store_bypass(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (__ssb_safe)
|
||||
return sprintf(buf, "Not affected\n");
|
||||
|
||||
switch (ssbd_state) {
|
||||
case ARM64_SSBD_KERNEL:
|
||||
case ARM64_SSBD_FORCE_ENABLE:
|
||||
if (IS_ENABLED(CONFIG_ARM64_SSBD))
|
||||
return sprintf(buf,
|
||||
"Mitigation: Speculative Store Bypass disabled via prctl\n");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/cpu_ops.h>
|
||||
@@ -112,6 +113,13 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_SM3_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_SHA3_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_TS_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_FHM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_DP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM4_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM3_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA3_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_ATOMICS_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_CRC32_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA2_SHIFT, 4, 0),
|
||||
@@ -121,36 +129,42 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_DPB_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_DPB_SHIFT, 4, 0),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_DIT_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
|
||||
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
|
||||
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
|
||||
/* Linux doesn't care about the EL3 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64PFR0_EL3_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL2_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL3_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL2_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_SSBS_SHIFT, 4, ID_AA64PFR1_SSBS_PSTATE_NI),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
|
||||
/* Linux shouldn't care about secure memory */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_BIGENDEL_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_ASID_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_ASID_SHIFT, 4, 0),
|
||||
/*
|
||||
* Differing PARange is fine as long as all peripherals and memory are mapped
|
||||
* within the minimum PARange of all CPUs
|
||||
@@ -161,20 +175,21 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_PAN_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_LOR_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_HPD_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_VHE_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_VMIDBITS_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_HADBS_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_LOR_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_HPD_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_VHE_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_VMIDBITS_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_HADBS_SHIFT, 4, 0),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LSM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_UAO_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_CNP_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_AT_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LSM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_UAO_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_CNP_SHIFT, 4, 0),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
@@ -201,14 +216,14 @@ struct arm64_ftr_reg arm64_ftr_reg_ctrel0 = {
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_mmfr0[] = {
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 28, 4, 0xf), /* InnerShr */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 24, 4, 0), /* FCSE */
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0xf), /* InnerShr */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 24, 4, 0), /* FCSE */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, 20, 4, 0), /* AuxReg */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 16, 4, 0), /* TCM */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 12, 4, 0), /* ShareLvl */
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 8, 4, 0xf), /* OuterShr */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* PMSA */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 0, 4, 0), /* VMSA */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 0), /* TCM */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 12, 4, 0), /* ShareLvl */
|
||||
S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 8, 4, 0xf), /* OuterShr */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* PMSA */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* VMSA */
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
@@ -229,8 +244,8 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_mvfr2[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* FPMisc */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 0, 4, 0), /* SIMDMisc */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* FPMisc */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* SIMDMisc */
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
@@ -242,25 +257,25 @@ static const struct arm64_ftr_bits ftr_dczid[] = {
|
||||
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_isar5[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_RDM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_CRC32_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_SHA2_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_SHA1_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_AES_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_SEVL_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_RDM_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_mmfr4[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* ac2 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* ac2 */
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_pfr0[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 12, 4, 0), /* State3 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 8, 4, 0), /* State2 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* State1 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 0, 4, 0), /* State0 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 12, 4, 0), /* State3 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 8, 4, 0), /* State2 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* State1 */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* State0 */
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
|
||||
@@ -341,7 +356,7 @@ static const struct __ftr_reg_entry {
|
||||
|
||||
/* Op1 = 0, CRn = 0, CRm = 4 */
|
||||
ARM64_FTR_REG(SYS_ID_AA64PFR0_EL1, ftr_id_aa64pfr0),
|
||||
ARM64_FTR_REG(SYS_ID_AA64PFR1_EL1, ftr_raz),
|
||||
ARM64_FTR_REG(SYS_ID_AA64PFR1_EL1, ftr_id_aa64pfr1),
|
||||
|
||||
/* Op1 = 0, CRn = 0, CRm = 5 */
|
||||
ARM64_FTR_REG(SYS_ID_AA64DFR0_EL1, ftr_id_aa64dfr0),
|
||||
@@ -480,6 +495,9 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
|
||||
reg->user_mask = user_mask;
|
||||
}
|
||||
|
||||
extern const struct arm64_cpu_capabilities arm64_errata[];
|
||||
static void __init setup_boot_cpu_capabilities(void);
|
||||
|
||||
void __init init_cpu_features(struct cpuinfo_arm64 *info)
|
||||
{
|
||||
/* Before we start using the tables, make sure it is sorted */
|
||||
@@ -517,6 +535,11 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
|
||||
init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect and enable early CPU capabilities based on the boot CPU,
|
||||
* after we have initialised the CPU feature infrastructure.
|
||||
*/
|
||||
setup_boot_cpu_capabilities();
|
||||
}
|
||||
|
||||
static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
|
||||
@@ -613,7 +636,6 @@ void update_cpu_features(int cpu,
|
||||
|
||||
/*
|
||||
* EL3 is not our concern.
|
||||
* ID_AA64PFR1 is currently RES0.
|
||||
*/
|
||||
taint |= check_update_ftr_reg(SYS_ID_AA64PFR0_EL1, cpu,
|
||||
info->reg_id_aa64pfr0, boot->reg_id_aa64pfr0);
|
||||
@@ -808,14 +830,34 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
|
||||
ID_AA64PFR0_FP_SHIFT) < 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
||||
static bool __meltdown_safe = true;
|
||||
static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
|
||||
|
||||
static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
|
||||
int __unused)
|
||||
int scope)
|
||||
{
|
||||
char const *str = "command line option";
|
||||
u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
|
||||
/* List of CPUs that are not vulnerable and don't need KPTI */
|
||||
static const struct midr_range kpti_safe_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
|
||||
MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
|
||||
MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
|
||||
};
|
||||
char const *str = "kpti command line option";
|
||||
bool meltdown_safe;
|
||||
|
||||
meltdown_safe = is_midr_in_range_list(read_cpuid_id(), kpti_safe_list);
|
||||
|
||||
/* Defer to CPU feature registers */
|
||||
if (has_cpuid_feature(entry, scope))
|
||||
meltdown_safe = true;
|
||||
|
||||
if (!meltdown_safe)
|
||||
__meltdown_safe = false;
|
||||
|
||||
/*
|
||||
* For reasons that aren't entirely clear, enabling KPTI on Cavium
|
||||
@@ -827,6 +869,24 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
|
||||
__kpti_forced = -1;
|
||||
}
|
||||
|
||||
/* Useful for KASLR robustness */
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset() > 0) {
|
||||
if (!__kpti_forced) {
|
||||
str = "KASLR";
|
||||
__kpti_forced = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_mitigations_off() && !__kpti_forced) {
|
||||
str = "mitigations=off";
|
||||
__kpti_forced = -1;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) {
|
||||
pr_info_once("kernel page table isolation disabled by kernel configuration\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Forced? */
|
||||
if (__kpti_forced) {
|
||||
pr_info_once("kernel page table isolation forced %s by %s\n",
|
||||
@@ -834,28 +894,12 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
|
||||
return __kpti_forced > 0;
|
||||
}
|
||||
|
||||
/* Useful for KASLR robustness */
|
||||
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
|
||||
return true;
|
||||
|
||||
/* Don't force KPTI for CPUs that are not vulnerable */
|
||||
switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
|
||||
case MIDR_CAVIUM_THUNDERX2:
|
||||
case MIDR_BRCM_VULCAN:
|
||||
case MIDR_CORTEX_A53:
|
||||
case MIDR_CORTEX_A55:
|
||||
case MIDR_CORTEX_A57:
|
||||
case MIDR_CORTEX_A72:
|
||||
case MIDR_CORTEX_A73:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Defer to CPU feature registers */
|
||||
return !cpuid_feature_extract_unsigned_field(pfr0,
|
||||
ID_AA64PFR0_CSV3_SHIFT);
|
||||
return !meltdown_safe;
|
||||
}
|
||||
|
||||
static int __nocfi kpti_install_ng_mappings(void *__unused)
|
||||
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
||||
static void __nocfi
|
||||
kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
typedef void (kpti_remap_fn)(int, int, phys_addr_t);
|
||||
extern kpti_remap_fn idmap_kpti_install_ng_mappings;
|
||||
@@ -865,7 +909,7 @@ static int __nocfi kpti_install_ng_mappings(void *__unused)
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
if (kpti_applied)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings);
|
||||
|
||||
@@ -876,8 +920,14 @@ static int __nocfi kpti_install_ng_mappings(void *__unused)
|
||||
if (!cpu)
|
||||
kpti_applied = true;
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
|
||||
|
||||
static int __init parse_kpti(char *str)
|
||||
{
|
||||
@@ -891,9 +941,8 @@ static int __init parse_kpti(char *str)
|
||||
return 0;
|
||||
}
|
||||
early_param("kpti", parse_kpti);
|
||||
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
|
||||
|
||||
static int cpu_copy_el2regs(void *__unused)
|
||||
static void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
/*
|
||||
* Copy register values that aren't redirected by hardware.
|
||||
@@ -905,15 +954,55 @@ static int cpu_copy_el2regs(void *__unused)
|
||||
*/
|
||||
if (!alternatives_applied)
|
||||
write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_SSBD
|
||||
static int ssbs_emulation_handler(struct pt_regs *regs, u32 instr)
|
||||
{
|
||||
if (user_mode(regs))
|
||||
return 1;
|
||||
|
||||
if (instr & BIT(CRm_shift))
|
||||
regs->pstate |= PSR_SSBS_BIT;
|
||||
else
|
||||
regs->pstate &= ~PSR_SSBS_BIT;
|
||||
|
||||
arm64_skip_faulting_instruction(regs, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct undef_hook ssbs_emulation_hook = {
|
||||
.instr_mask = ~(1U << CRm_shift),
|
||||
.instr_val = 0xd500001f | REG_PSTATE_SSBS_IMM,
|
||||
.fn = ssbs_emulation_handler,
|
||||
};
|
||||
|
||||
static void cpu_enable_ssbs(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
static bool undef_hook_registered = false;
|
||||
static DEFINE_SPINLOCK(hook_lock);
|
||||
|
||||
spin_lock(&hook_lock);
|
||||
if (!undef_hook_registered) {
|
||||
register_undef_hook(&ssbs_emulation_hook);
|
||||
undef_hook_registered = true;
|
||||
}
|
||||
spin_unlock(&hook_lock);
|
||||
|
||||
if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) {
|
||||
sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_DSSBS);
|
||||
arm64_set_ssbd_mitigation(false);
|
||||
} else {
|
||||
arm64_set_ssbd_mitigation(true);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_ARM64_SSBD */
|
||||
|
||||
static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
{
|
||||
.desc = "GIC system register CPU interface",
|
||||
.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_useable_gicv3_cpuif,
|
||||
.sys_reg = SYS_ID_AA64PFR0_EL1,
|
||||
.field_pos = ID_AA64PFR0_GIC_SHIFT,
|
||||
@@ -924,20 +1013,20 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
{
|
||||
.desc = "Privileged Access Never",
|
||||
.capability = ARM64_HAS_PAN,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_cpuid_feature,
|
||||
.sys_reg = SYS_ID_AA64MMFR1_EL1,
|
||||
.field_pos = ID_AA64MMFR1_PAN_SHIFT,
|
||||
.sign = FTR_UNSIGNED,
|
||||
.min_field_value = 1,
|
||||
.enable = cpu_enable_pan,
|
||||
.cpu_enable = cpu_enable_pan,
|
||||
},
|
||||
#endif /* CONFIG_ARM64_PAN */
|
||||
#if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
|
||||
{
|
||||
.desc = "LSE atomic instructions",
|
||||
.capability = ARM64_HAS_LSE_ATOMICS,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_cpuid_feature,
|
||||
.sys_reg = SYS_ID_AA64ISAR0_EL1,
|
||||
.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
|
||||
@@ -948,14 +1037,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
{
|
||||
.desc = "Software prefetching using PRFM",
|
||||
.capability = ARM64_HAS_NO_HW_PREFETCH,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
|
||||
.matches = has_no_hw_prefetch,
|
||||
},
|
||||
#ifdef CONFIG_ARM64_UAO
|
||||
{
|
||||
.desc = "User Access Override",
|
||||
.capability = ARM64_HAS_UAO,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_cpuid_feature,
|
||||
.sys_reg = SYS_ID_AA64MMFR2_EL1,
|
||||
.field_pos = ID_AA64MMFR2_UAO_SHIFT,
|
||||
@@ -969,21 +1058,23 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
#ifdef CONFIG_ARM64_PAN
|
||||
{
|
||||
.capability = ARM64_ALT_PAN_NOT_UAO,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = cpufeature_pan_not_uao,
|
||||
},
|
||||
#endif /* CONFIG_ARM64_PAN */
|
||||
#ifdef CONFIG_ARM64_VHE
|
||||
{
|
||||
.desc = "Virtualization Host Extensions",
|
||||
.capability = ARM64_HAS_VIRT_HOST_EXTN,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE,
|
||||
.matches = runs_at_el2,
|
||||
.enable = cpu_copy_el2regs,
|
||||
.cpu_enable = cpu_copy_el2regs,
|
||||
},
|
||||
#endif /* CONFIG_ARM64_VHE */
|
||||
{
|
||||
.desc = "32-bit EL0 Support",
|
||||
.capability = ARM64_HAS_32BIT_EL0,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_cpuid_feature,
|
||||
.sys_reg = SYS_ID_AA64PFR0_EL1,
|
||||
.sign = FTR_UNSIGNED,
|
||||
@@ -993,22 +1084,28 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
{
|
||||
.desc = "Reduced HYP mapping offset",
|
||||
.capability = ARM64_HYP_OFFSET_LOW,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = hyp_offset_low,
|
||||
},
|
||||
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
||||
{
|
||||
.desc = "Kernel page table isolation (KPTI)",
|
||||
.capability = ARM64_UNMAP_KERNEL_AT_EL0,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
|
||||
/*
|
||||
* The ID feature fields below are used to indicate that
|
||||
* the CPU doesn't need KPTI. See unmap_kernel_at_el0 for
|
||||
* more details.
|
||||
*/
|
||||
.sys_reg = SYS_ID_AA64PFR0_EL1,
|
||||
.field_pos = ID_AA64PFR0_CSV3_SHIFT,
|
||||
.min_field_value = 1,
|
||||
.matches = unmap_kernel_at_el0,
|
||||
.enable = kpti_install_ng_mappings,
|
||||
.cpu_enable = kpti_install_ng_mappings,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
/* FP/SIMD is not implemented */
|
||||
.capability = ARM64_HAS_NO_FPSIMD,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.min_field_value = 0,
|
||||
.matches = has_no_fpsimd,
|
||||
},
|
||||
@@ -1016,26 +1113,39 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
{
|
||||
.desc = "Data cache clean to Point of Persistence",
|
||||
.capability = ARM64_HAS_DCPOP,
|
||||
.def_scope = SCOPE_SYSTEM,
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_cpuid_feature,
|
||||
.sys_reg = SYS_ID_AA64ISAR1_EL1,
|
||||
.field_pos = ID_AA64ISAR1_DPB_SHIFT,
|
||||
.min_field_value = 1,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_SSBD
|
||||
{
|
||||
.desc = "Speculative Store Bypassing Safe (SSBS)",
|
||||
.capability = ARM64_SSBS,
|
||||
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
|
||||
.matches = has_cpuid_feature,
|
||||
.sys_reg = SYS_ID_AA64PFR1_EL1,
|
||||
.field_pos = ID_AA64PFR1_SSBS_SHIFT,
|
||||
.sign = FTR_UNSIGNED,
|
||||
.min_field_value = ID_AA64PFR1_SSBS_PSTATE_ONLY,
|
||||
.cpu_enable = cpu_enable_ssbs,
|
||||
},
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
|
||||
#define HWCAP_CAP(reg, field, s, min_value, type, cap) \
|
||||
#define HWCAP_CAP(reg, field, s, min_value, cap_type, cap) \
|
||||
{ \
|
||||
.desc = #cap, \
|
||||
.def_scope = SCOPE_SYSTEM, \
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE, \
|
||||
.matches = has_cpuid_feature, \
|
||||
.sys_reg = reg, \
|
||||
.field_pos = field, \
|
||||
.sign = s, \
|
||||
.min_field_value = min_value, \
|
||||
.hwcap_type = type, \
|
||||
.hwcap_type = cap_type, \
|
||||
.hwcap = cap, \
|
||||
}
|
||||
|
||||
@@ -1052,14 +1162,20 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM3_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM3),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM4_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM4),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_DP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDDP),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_FHM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDFHM),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_TS_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_FLAGM),
|
||||
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_FP),
|
||||
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP),
|
||||
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
|
||||
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_ASIMDHP),
|
||||
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_DIT_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_DIT),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_DPB_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_DCPOP),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_JSCVT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_JSCVT),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_FCMA),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_LRCPC),
|
||||
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_ILRCPC),
|
||||
HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_AT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_USCAT),
|
||||
HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_SSBS_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_SSBS_PSTATE_INSNS, CAP_HWCAP, HWCAP_SSBS),
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -1124,7 +1240,7 @@ static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps)
|
||||
/* We support emulation of accesses to CPU ID feature registers */
|
||||
elf_hwcap |= HWCAP_CPUID;
|
||||
for (; hwcaps->matches; hwcaps++)
|
||||
if (hwcaps->matches(hwcaps, hwcaps->def_scope))
|
||||
if (hwcaps->matches(hwcaps, cpucap_default_scope(hwcaps)))
|
||||
cap_set_elf_hwcap(hwcaps);
|
||||
}
|
||||
|
||||
@@ -1147,11 +1263,13 @@ static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
|
||||
return false;
|
||||
}
|
||||
|
||||
void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
|
||||
const char *info)
|
||||
static void __update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
|
||||
u16 scope_mask, const char *info)
|
||||
{
|
||||
scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
|
||||
for (; caps->matches; caps++) {
|
||||
if (!caps->matches(caps, caps->def_scope))
|
||||
if (!(caps->type & scope_mask) ||
|
||||
!caps->matches(caps, cpucap_default_scope(caps)))
|
||||
continue;
|
||||
|
||||
if (!cpus_have_cap(caps->capability) && caps->desc)
|
||||
@@ -1160,33 +1278,69 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
|
||||
}
|
||||
}
|
||||
|
||||
static void update_cpu_capabilities(u16 scope_mask)
|
||||
{
|
||||
__update_cpu_capabilities(arm64_features, scope_mask, "detected:");
|
||||
__update_cpu_capabilities(arm64_errata, scope_mask,
|
||||
"enabling workaround for");
|
||||
}
|
||||
|
||||
static int __enable_cpu_capability(void *arg)
|
||||
{
|
||||
const struct arm64_cpu_capabilities *cap = arg;
|
||||
|
||||
cap->cpu_enable(cap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run through the enabled capabilities and enable() it on all active
|
||||
* CPUs
|
||||
*/
|
||||
void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
|
||||
static void __init
|
||||
__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
|
||||
u16 scope_mask)
|
||||
{
|
||||
scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
|
||||
for (; caps->matches; caps++) {
|
||||
unsigned int num = caps->capability;
|
||||
|
||||
if (!cpus_have_cap(num))
|
||||
if (!(caps->type & scope_mask) || !cpus_have_cap(num))
|
||||
continue;
|
||||
|
||||
/* Ensure cpus_have_const_cap(num) works */
|
||||
static_branch_enable(&cpu_hwcap_keys[num]);
|
||||
|
||||
if (caps->enable) {
|
||||
if (caps->cpu_enable) {
|
||||
/*
|
||||
* Use stop_machine() as it schedules the work allowing
|
||||
* us to modify PSTATE, instead of on_each_cpu() which
|
||||
* uses an IPI, giving us a PSTATE that disappears when
|
||||
* we return.
|
||||
* Capabilities with SCOPE_BOOT_CPU scope are finalised
|
||||
* before any secondary CPU boots. Thus, each secondary
|
||||
* will enable the capability as appropriate via
|
||||
* check_local_cpu_capabilities(). The only exception is
|
||||
* the boot CPU, for which the capability must be
|
||||
* enabled here. This approach avoids costly
|
||||
* stop_machine() calls for this case.
|
||||
*
|
||||
* Otherwise, use stop_machine() as it schedules the
|
||||
* work allowing us to modify PSTATE, instead of
|
||||
* on_each_cpu() which uses an IPI, giving us a PSTATE
|
||||
* that disappears when we return.
|
||||
*/
|
||||
stop_machine(caps->enable, (void *)caps, cpu_online_mask);
|
||||
if (scope_mask & SCOPE_BOOT_CPU)
|
||||
caps->cpu_enable(caps);
|
||||
else
|
||||
stop_machine(__enable_cpu_capability,
|
||||
(void *)caps, cpu_online_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __init enable_cpu_capabilities(u16 scope_mask)
|
||||
{
|
||||
__enable_cpu_capabilities(arm64_features, scope_mask);
|
||||
__enable_cpu_capabilities(arm64_errata, scope_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flag to indicate if we have computed the system wide
|
||||
* capabilities based on the boot time active CPUs. This
|
||||
@@ -1202,14 +1356,83 @@ static inline void set_sys_caps_initialised(void)
|
||||
sys_caps_initialised = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run through the list of capabilities to check for conflicts.
|
||||
* If the system has already detected a capability, take necessary
|
||||
* action on this CPU.
|
||||
*
|
||||
* Returns "false" on conflicts.
|
||||
*/
|
||||
static bool
|
||||
__verify_local_cpu_caps(const struct arm64_cpu_capabilities *caps_list,
|
||||
u16 scope_mask)
|
||||
{
|
||||
bool cpu_has_cap, system_has_cap;
|
||||
const struct arm64_cpu_capabilities *caps;
|
||||
|
||||
scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
|
||||
|
||||
for (caps = caps_list; caps->matches; caps++) {
|
||||
if (!(caps->type & scope_mask))
|
||||
continue;
|
||||
|
||||
cpu_has_cap = __this_cpu_has_cap(caps_list, caps->capability);
|
||||
system_has_cap = cpus_have_cap(caps->capability);
|
||||
|
||||
if (system_has_cap) {
|
||||
/*
|
||||
* Check if the new CPU misses an advertised feature,
|
||||
* which is not safe to miss.
|
||||
*/
|
||||
if (!cpu_has_cap && !cpucap_late_cpu_optional(caps))
|
||||
break;
|
||||
/*
|
||||
* We have to issue cpu_enable() irrespective of
|
||||
* whether the CPU has it or not, as it is enabeld
|
||||
* system wide. It is upto the call back to take
|
||||
* appropriate action on this CPU.
|
||||
*/
|
||||
if (caps->cpu_enable)
|
||||
caps->cpu_enable(caps);
|
||||
} else {
|
||||
/*
|
||||
* Check if the CPU has this capability if it isn't
|
||||
* safe to have when the system doesn't.
|
||||
*/
|
||||
if (cpu_has_cap && !cpucap_late_cpu_permitted(caps))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (caps->matches) {
|
||||
pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n",
|
||||
smp_processor_id(), caps->capability,
|
||||
caps->desc, system_has_cap, cpu_has_cap);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool verify_local_cpu_caps(u16 scope_mask)
|
||||
{
|
||||
return __verify_local_cpu_caps(arm64_errata, scope_mask) &&
|
||||
__verify_local_cpu_caps(arm64_features, scope_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for CPU features that are used in early boot
|
||||
* based on the Boot CPU value.
|
||||
*/
|
||||
static void check_early_cpu_features(void)
|
||||
{
|
||||
verify_cpu_run_el();
|
||||
verify_cpu_asid_bits();
|
||||
/*
|
||||
* Early features are used by the kernel already. If there
|
||||
* is a conflict, we cannot proceed further.
|
||||
*/
|
||||
if (!verify_local_cpu_caps(SCOPE_BOOT_CPU))
|
||||
cpu_panic_kernel();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1224,26 +1447,6 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
|
||||
{
|
||||
const struct arm64_cpu_capabilities *caps = caps_list;
|
||||
for (; caps->matches; caps++) {
|
||||
if (!cpus_have_cap(caps->capability))
|
||||
continue;
|
||||
/*
|
||||
* If the new CPU misses an advertised feature, we cannot proceed
|
||||
* further, park the cpu.
|
||||
*/
|
||||
if (!__this_cpu_has_cap(caps_list, caps->capability)) {
|
||||
pr_crit("CPU%d: missing feature: %s\n",
|
||||
smp_processor_id(), caps->desc);
|
||||
cpu_die_early();
|
||||
}
|
||||
if (caps->enable)
|
||||
caps->enable((void *)caps);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Run through the enabled system capabilities and enable() it on this CPU.
|
||||
@@ -1255,8 +1458,14 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list)
|
||||
*/
|
||||
static void verify_local_cpu_capabilities(void)
|
||||
{
|
||||
verify_local_cpu_errata_workarounds();
|
||||
verify_local_cpu_features(arm64_features);
|
||||
/*
|
||||
* The capabilities with SCOPE_BOOT_CPU are checked from
|
||||
* check_early_cpu_features(), as they need to be verified
|
||||
* on all secondary CPUs.
|
||||
*/
|
||||
if (!verify_local_cpu_caps(SCOPE_ALL & ~SCOPE_BOOT_CPU))
|
||||
cpu_die_early();
|
||||
|
||||
verify_local_elf_hwcaps(arm64_elf_hwcaps);
|
||||
if (system_supports_32bit_el0())
|
||||
verify_local_elf_hwcaps(compat_elf_hwcaps);
|
||||
@@ -1272,20 +1481,22 @@ void check_local_cpu_capabilities(void)
|
||||
|
||||
/*
|
||||
* If we haven't finalised the system capabilities, this CPU gets
|
||||
* a chance to update the errata work arounds.
|
||||
* a chance to update the errata work arounds and local features.
|
||||
* Otherwise, this CPU should verify that it has all the system
|
||||
* advertised capabilities.
|
||||
*/
|
||||
if (!sys_caps_initialised)
|
||||
update_cpu_errata_workarounds();
|
||||
update_cpu_capabilities(SCOPE_LOCAL_CPU);
|
||||
else
|
||||
verify_local_cpu_capabilities();
|
||||
}
|
||||
|
||||
static void __init setup_feature_capabilities(void)
|
||||
static void __init setup_boot_cpu_capabilities(void)
|
||||
{
|
||||
update_cpu_capabilities(arm64_features, "detected feature:");
|
||||
enable_cpu_capabilities(arm64_features);
|
||||
/* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
|
||||
update_cpu_capabilities(SCOPE_BOOT_CPU | SCOPE_LOCAL_CPU);
|
||||
/* Enable the SCOPE_BOOT_CPU capabilities alone right away */
|
||||
enable_cpu_capabilities(SCOPE_BOOT_CPU);
|
||||
}
|
||||
|
||||
DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
|
||||
@@ -1304,14 +1515,24 @@ bool this_cpu_has_cap(unsigned int cap)
|
||||
__this_cpu_has_cap(arm64_errata, cap));
|
||||
}
|
||||
|
||||
static void __init setup_system_capabilities(void)
|
||||
{
|
||||
/*
|
||||
* We have finalised the system-wide safe feature
|
||||
* registers, finalise the capabilities that depend
|
||||
* on it. Also enable all the available capabilities,
|
||||
* that are not enabled already.
|
||||
*/
|
||||
update_cpu_capabilities(SCOPE_SYSTEM);
|
||||
enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU);
|
||||
}
|
||||
|
||||
void __init setup_cpu_features(void)
|
||||
{
|
||||
u32 cwg;
|
||||
int cls;
|
||||
|
||||
/* Set the CPU feature capabilies */
|
||||
setup_feature_capabilities();
|
||||
enable_errata_workarounds();
|
||||
setup_system_capabilities();
|
||||
mark_const_caps_ready();
|
||||
setup_elf_hwcaps(arm64_elf_hwcaps);
|
||||
|
||||
@@ -1437,3 +1658,15 @@ static int __init enable_mrs_emulation(void)
|
||||
}
|
||||
|
||||
core_initcall(enable_mrs_emulation);
|
||||
|
||||
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (__meltdown_safe)
|
||||
return sprintf(buf, "Not affected\n");
|
||||
|
||||
if (arm64_kernel_unmapped_at_el0())
|
||||
return sprintf(buf, "Mitigation: PTI\n");
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ static const char *const hwcap_str[] = {
|
||||
"fcma",
|
||||
"lrcpc",
|
||||
"dcpop",
|
||||
"sve",
|
||||
"asimdfhm",
|
||||
"dit",
|
||||
"uscat",
|
||||
"ilrcpc",
|
||||
"flagm",
|
||||
"ssbs",
|
||||
"sha3",
|
||||
"sm3",
|
||||
"sm4",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/signal.h>
|
||||
|
||||
#include <asm/fpsimd.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/simd.h>
|
||||
|
||||
|
||||
@@ -388,17 +388,13 @@ ENTRY(el2_setup)
|
||||
mrs x0, CurrentEL
|
||||
cmp x0, #CurrentEL_EL2
|
||||
b.eq 1f
|
||||
mrs x0, sctlr_el1
|
||||
CPU_BE( orr x0, x0, #(3 << 24) ) // Set the EE and E0E bits for EL1
|
||||
CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
|
||||
mov_q x0, (SCTLR_EL1_RES1 | ENDIAN_SET_EL1)
|
||||
msr sctlr_el1, x0
|
||||
mov w0, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1
|
||||
isb
|
||||
ret
|
||||
|
||||
1: mrs x0, sctlr_el2
|
||||
CPU_BE( orr x0, x0, #(1 << 25) ) // Set the EE bit for EL2
|
||||
CPU_LE( bic x0, x0, #(1 << 25) ) // Clear the EE bit for EL2
|
||||
1: mov_q x0, (SCTLR_EL2_RES1 | ENDIAN_SET_EL2)
|
||||
msr sctlr_el2, x0
|
||||
|
||||
#ifdef CONFIG_ARM64_VHE
|
||||
@@ -505,10 +501,7 @@ install_el2_stub:
|
||||
* requires no configuration, and all non-hyp-specific EL2 setup
|
||||
* will be done via the _EL1 system register aliases in __cpu_setup.
|
||||
*/
|
||||
/* sctlr_el1 */
|
||||
mov x0, #0x0800 // Set/clear RES{1,0} bits
|
||||
CPU_BE( movk x0, #0x33d0, lsl #16 ) // Set EE and E0E on BE systems
|
||||
CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems
|
||||
mov_q x0, (SCTLR_EL1_RES1 | ENDIAN_SET_EL1)
|
||||
msr sctlr_el1, x0
|
||||
|
||||
/* Coprocessor traps. */
|
||||
|
||||
@@ -363,6 +363,10 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
||||
if (IS_ENABLED(CONFIG_ARM64_UAO) &&
|
||||
cpus_have_const_cap(ARM64_HAS_UAO))
|
||||
childregs->pstate |= PSR_UAO_BIT;
|
||||
|
||||
if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE)
|
||||
set_ssbs_bit(childregs);
|
||||
|
||||
p->thread.cpu_context.x19 = stack_start;
|
||||
p->thread.cpu_context.x20 = stk_sz;
|
||||
}
|
||||
@@ -402,6 +406,32 @@ void uao_thread_switch(struct task_struct *next)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Force SSBS state on context-switch, since it may be lost after migrating
|
||||
* from a CPU which treats the bit as RES0 in a heterogeneous system.
|
||||
*/
|
||||
static void ssbs_thread_switch(struct task_struct *next)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(next);
|
||||
|
||||
/*
|
||||
* Nothing to do for kernel threads, but 'regs' may be junk
|
||||
* (e.g. idle task) so check the flags and bail early.
|
||||
*/
|
||||
if (unlikely(next->flags & PF_KTHREAD))
|
||||
return;
|
||||
|
||||
/* If the mitigation is enabled, then we leave SSBS clear. */
|
||||
if ((arm64_get_ssbd_state() == ARM64_SSBD_FORCE_ENABLE) ||
|
||||
test_tsk_thread_flag(next, TIF_SSBD))
|
||||
return;
|
||||
|
||||
if (compat_user_mode(regs))
|
||||
set_compat_ssbs_bit(regs);
|
||||
else if (user_mode(regs))
|
||||
set_ssbs_bit(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* We store our current task in sp_el0, which is clobbered by userspace. Keep a
|
||||
* shadow copy so that we can restore this upon entry from userspace.
|
||||
@@ -430,6 +460,7 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
|
||||
contextidr_thread_switch(next);
|
||||
entry_task_switch(next);
|
||||
uao_thread_switch(next);
|
||||
ssbs_thread_switch(next);
|
||||
|
||||
/*
|
||||
* Complete any pending TLB or cache maintenance on this CPU in case
|
||||
|
||||
@@ -1402,15 +1402,20 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs)
|
||||
}
|
||||
|
||||
/*
|
||||
* Bits which are always architecturally RES0 per ARM DDI 0487A.h
|
||||
* SPSR_ELx bits which are always architecturally RES0 per ARM DDI 0487D.a.
|
||||
* We permit userspace to set SSBS (AArch64 bit 12, AArch32 bit 23) which is
|
||||
* not described in ARM DDI 0487D.a.
|
||||
* We treat PAN and UAO as RES0 bits, as they are meaningless at EL0, and may
|
||||
* be allocated an EL0 meaning in future.
|
||||
* Userspace cannot use these until they have an architectural meaning.
|
||||
* Note that this follows the SPSR_ELx format, not the AArch32 PSR format.
|
||||
* We also reserve IL for the kernel; SS is handled dynamically.
|
||||
*/
|
||||
#define SPSR_EL1_AARCH64_RES0_BITS \
|
||||
(GENMASK_ULL(63,32) | GENMASK_ULL(27, 22) | GENMASK_ULL(20, 10) | \
|
||||
GENMASK_ULL(5, 5))
|
||||
(GENMASK_ULL(63, 32) | GENMASK_ULL(27, 25) | GENMASK_ULL(23, 22) | \
|
||||
GENMASK_ULL(20, 13) | GENMASK_ULL(11, 10) | GENMASK_ULL(5, 5))
|
||||
#define SPSR_EL1_AARCH32_RES0_BITS \
|
||||
(GENMASK_ULL(63,32) | GENMASK_ULL(24, 22) | GENMASK_ULL(20,20))
|
||||
(GENMASK_ULL(63, 32) | GENMASK_ULL(22, 22) | GENMASK_ULL(20, 20))
|
||||
|
||||
static int valid_compat_regs(struct user_pt_regs *regs)
|
||||
{
|
||||
|
||||
@@ -83,43 +83,6 @@ enum ipi_msg_type {
|
||||
IPI_WAKEUP
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARM64_VHE
|
||||
|
||||
/* Whether the boot CPU is running in HYP mode or not*/
|
||||
static bool boot_cpu_hyp_mode;
|
||||
|
||||
static inline void save_boot_cpu_run_el(void)
|
||||
{
|
||||
boot_cpu_hyp_mode = is_kernel_in_hyp_mode();
|
||||
}
|
||||
|
||||
static inline bool is_boot_cpu_in_hyp_mode(void)
|
||||
{
|
||||
return boot_cpu_hyp_mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a secondary CPU is running the kernel at the same
|
||||
* EL as that of the boot CPU.
|
||||
*/
|
||||
void verify_cpu_run_el(void)
|
||||
{
|
||||
bool in_el2 = is_kernel_in_hyp_mode();
|
||||
bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode();
|
||||
|
||||
if (in_el2 ^ boot_cpu_el2) {
|
||||
pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n",
|
||||
smp_processor_id(),
|
||||
in_el2 ? 2 : 1,
|
||||
boot_cpu_el2 ? 2 : 1);
|
||||
cpu_panic_kernel();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void save_boot_cpu_run_el(void) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static int op_cpu_kill(unsigned int cpu);
|
||||
#else
|
||||
@@ -448,13 +411,6 @@ void __init smp_prepare_boot_cpu(void)
|
||||
*/
|
||||
jump_label_init();
|
||||
cpuinfo_store_boot_cpu();
|
||||
save_boot_cpu_run_el();
|
||||
/*
|
||||
* Run the errata work around checks on the boot CPU, once we have
|
||||
* initialised the cpu feature infrastructure from
|
||||
* cpuinfo_store_boot_cpu() above.
|
||||
*/
|
||||
update_cpu_errata_workarounds();
|
||||
}
|
||||
|
||||
static u64 __init of_get_cpu_mpidr(struct device_node *dn)
|
||||
|
||||
@@ -3,13 +3,32 @@
|
||||
* Copyright (C) 2018 ARM Ltd, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/prctl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
#include <linux/thread_info.h>
|
||||
|
||||
#include <asm/compat.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
static void ssbd_ssbs_enable(struct task_struct *task)
|
||||
{
|
||||
u64 val = is_compat_thread(task_thread_info(task)) ?
|
||||
PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
|
||||
|
||||
task_pt_regs(task)->pstate |= val;
|
||||
}
|
||||
|
||||
static void ssbd_ssbs_disable(struct task_struct *task)
|
||||
{
|
||||
u64 val = is_compat_thread(task_thread_info(task)) ?
|
||||
PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
|
||||
|
||||
task_pt_regs(task)->pstate &= ~val;
|
||||
}
|
||||
|
||||
/*
|
||||
* prctl interface for SSBD
|
||||
*/
|
||||
@@ -45,12 +64,14 @@ static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||
return -EPERM;
|
||||
task_clear_spec_ssb_disable(task);
|
||||
clear_tsk_thread_flag(task, TIF_SSBD);
|
||||
ssbd_ssbs_enable(task);
|
||||
break;
|
||||
case PR_SPEC_DISABLE:
|
||||
if (state == ARM64_SSBD_FORCE_DISABLE)
|
||||
return -EPERM;
|
||||
task_set_spec_ssb_disable(task);
|
||||
set_tsk_thread_flag(task, TIF_SSBD);
|
||||
ssbd_ssbs_disable(task);
|
||||
break;
|
||||
case PR_SPEC_FORCE_DISABLE:
|
||||
if (state == ARM64_SSBD_FORCE_DISABLE)
|
||||
@@ -58,6 +79,7 @@ static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||
task_set_spec_ssb_disable(task);
|
||||
task_set_spec_ssb_force_disable(task);
|
||||
set_tsk_thread_flag(task, TIF_SSBD);
|
||||
ssbd_ssbs_disable(task);
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/debug-monitors.h>
|
||||
#include <asm/esr.h>
|
||||
#include <asm/insn.h>
|
||||
@@ -436,10 +437,9 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
|
||||
force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
|
||||
}
|
||||
|
||||
int cpu_enable_cache_maint_trap(void *__unused)
|
||||
void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
config_sctlr_el1(SCTLR_EL1_UCI, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define __user_cache_maint(insn, address, res) \
|
||||
|
||||
@@ -196,15 +196,3 @@ alternative_endif
|
||||
|
||||
eret
|
||||
ENDPROC(__fpsimd_guest_restore)
|
||||
|
||||
ENTRY(__qcom_hyp_sanitize_btac_predictors)
|
||||
/**
|
||||
* Call SMC64 with Silicon provider serviceID 23<<8 (0xc2001700)
|
||||
* 0xC2000000-0xC200FFFF: assigned to SiP Service Calls
|
||||
* b15-b0: contains SiP functionID
|
||||
*/
|
||||
movz x0, #0x1700
|
||||
movk x0, #0xc200, lsl #16
|
||||
smc #0
|
||||
ret
|
||||
ENDPROC(__qcom_hyp_sanitize_btac_predictors)
|
||||
|
||||
@@ -405,16 +405,6 @@ again:
|
||||
|
||||
__set_host_arch_workaround_state(vcpu);
|
||||
|
||||
if (cpus_have_const_cap(ARM64_HARDEN_BP_POST_GUEST_EXIT)) {
|
||||
u32 midr = read_cpuid_id();
|
||||
|
||||
/* Apply BTAC predictors mitigation to all Falkor chips */
|
||||
if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) ||
|
||||
((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1)) {
|
||||
__qcom_hyp_sanitize_btac_predictors();
|
||||
}
|
||||
}
|
||||
|
||||
fp_enabled = __fpsimd_enabled();
|
||||
|
||||
__sysreg_save_guest_state(guest_ctxt);
|
||||
|
||||
@@ -188,3 +188,14 @@ void __hyp_text __kvm_set_tpidr_el2(u64 tpidr_el2)
|
||||
{
|
||||
asm("msr tpidr_el2, %0": : "r" (tpidr_el2));
|
||||
}
|
||||
|
||||
void __hyp_text __kvm_enable_ssbs(void)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
asm volatile(
|
||||
"mrs %0, sctlr_el2\n"
|
||||
"orr %0, %0, %1\n"
|
||||
"msr sctlr_el2, %0"
|
||||
: "=&r" (tmp) : "L" (SCTLR_ELx_DSSBS));
|
||||
}
|
||||
|
||||
@@ -875,7 +875,7 @@ asmlinkage int __exception do_debug_exception(unsigned long addr_if_watchpoint,
|
||||
NOKPROBE_SYMBOL(do_debug_exception);
|
||||
|
||||
#ifdef CONFIG_ARM64_PAN
|
||||
int cpu_enable_pan(void *__unused)
|
||||
void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
/*
|
||||
* We modify PSTATE. This won't work from irq context as the PSTATE
|
||||
@@ -885,6 +885,5 @@ int cpu_enable_pan(void *__unused)
|
||||
|
||||
config_sctlr_el1(SCTLR_EL1_SPAN, 0);
|
||||
asm(SET_PSTATE_PAN(1));
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ARM64_PAN */
|
||||
|
||||
@@ -430,11 +430,7 @@ ENTRY(__cpu_setup)
|
||||
/*
|
||||
* Prepare SCTLR
|
||||
*/
|
||||
adr x5, crval
|
||||
ldp w5, w6, [x5]
|
||||
mrs x0, sctlr_el1
|
||||
bic x0, x0, x5 // clear bits
|
||||
orr x0, x0, x6 // set bits
|
||||
mov_q x0, SCTLR_EL1_SET
|
||||
/*
|
||||
* Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for
|
||||
* both user and kernel.
|
||||
@@ -470,21 +466,3 @@ ENTRY(__cpu_setup)
|
||||
msr tcr_el1, x10
|
||||
ret // return to head.S
|
||||
ENDPROC(__cpu_setup)
|
||||
|
||||
/*
|
||||
* We set the desired value explicitly, including those of the
|
||||
* reserved bits. The values of bits EE & E0E were set early in
|
||||
* el2_setup, which are left untouched below.
|
||||
*
|
||||
* n n T
|
||||
* U E WT T UD US IHBS
|
||||
* CE0 XWHW CZ ME TEEA S
|
||||
* .... .IEE .... NEAI TE.I ..AD DEN0 ACAM
|
||||
* 0011 0... 1101 ..0. ..0. 10.. .0.. .... < hardware reserved
|
||||
* .... .1.. .... 01.1 11.1 ..01 0.01 1101 < software settings
|
||||
*/
|
||||
.type crval, #object
|
||||
crval:
|
||||
.word 0xfcffffff // clear
|
||||
.word 0x34d5d91d // set
|
||||
.popsection
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
|
||||
miscintc: interrupt-controller@18060010 {
|
||||
compatible = "qca,ar7240-misc-intc";
|
||||
reg = <0x18060010 0x4>;
|
||||
reg = <0x18060010 0x8>;
|
||||
|
||||
interrupt-parent = <&cpuintc>;
|
||||
interrupts = <6>;
|
||||
|
||||
@@ -110,7 +110,7 @@ static int __init serial_init(void)
|
||||
}
|
||||
module_init(serial_init);
|
||||
|
||||
static void __init serial_exit(void)
|
||||
static void __exit serial_exit(void)
|
||||
{
|
||||
platform_device_unregister(&uart8250_device);
|
||||
}
|
||||
|
||||
@@ -658,6 +658,13 @@ static void build_restore_pagemask(u32 **p, struct uasm_reloc **r,
|
||||
int restore_scratch)
|
||||
{
|
||||
if (restore_scratch) {
|
||||
/*
|
||||
* Ensure the MFC0 below observes the value written to the
|
||||
* KScratch register by the prior MTC0.
|
||||
*/
|
||||
if (scratch_reg >= 0)
|
||||
uasm_i_ehb(p);
|
||||
|
||||
/* Reset default page size */
|
||||
if (PM_DEFAULT_MASK >> 16) {
|
||||
uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
|
||||
@@ -672,12 +679,10 @@ static void build_restore_pagemask(u32 **p, struct uasm_reloc **r,
|
||||
uasm_i_mtc0(p, 0, C0_PAGEMASK);
|
||||
uasm_il_b(p, r, lid);
|
||||
}
|
||||
if (scratch_reg >= 0) {
|
||||
uasm_i_ehb(p);
|
||||
if (scratch_reg >= 0)
|
||||
UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
|
||||
} else {
|
||||
else
|
||||
UASM_i_LW(p, 1, scratchpad_offset(0), 0);
|
||||
}
|
||||
} else {
|
||||
/* Reset default page size */
|
||||
if (PM_DEFAULT_MASK >> 16) {
|
||||
@@ -926,6 +931,10 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
|
||||
}
|
||||
if (mode != not_refill && check_for_high_segbits) {
|
||||
uasm_l_large_segbits_fault(l, *p);
|
||||
|
||||
if (mode == refill_scratch && scratch_reg >= 0)
|
||||
uasm_i_ehb(p);
|
||||
|
||||
/*
|
||||
* We get here if we are an xsseg address, or if we are
|
||||
* an xuseg address above (PGDIR_SHIFT+PGDIR_BITS) boundary.
|
||||
@@ -942,12 +951,10 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
|
||||
uasm_i_jr(p, ptr);
|
||||
|
||||
if (mode == refill_scratch) {
|
||||
if (scratch_reg >= 0) {
|
||||
uasm_i_ehb(p);
|
||||
if (scratch_reg >= 0)
|
||||
UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
|
||||
} else {
|
||||
else
|
||||
UASM_i_LW(p, 1, scratchpad_offset(0), 0);
|
||||
}
|
||||
} else {
|
||||
uasm_i_nop(p);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* arch/parisc/mm/ioremap.c
|
||||
*
|
||||
* (C) Copyright 1995 1996 Linus Torvalds
|
||||
* (C) Copyright 2001-2006 Helge Deller <deller@gmx.de>
|
||||
* (C) Copyright 2001-2019 Helge Deller <deller@gmx.de>
|
||||
* (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
|
||||
*/
|
||||
|
||||
@@ -84,7 +84,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
|
||||
addr = (void __iomem *) area->addr;
|
||||
if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
|
||||
phys_addr, pgprot)) {
|
||||
vfree(addr);
|
||||
vunmap(addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -92,9 +92,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
|
||||
}
|
||||
EXPORT_SYMBOL(__ioremap);
|
||||
|
||||
void iounmap(const volatile void __iomem *addr)
|
||||
void iounmap(const volatile void __iomem *io_addr)
|
||||
{
|
||||
if (addr > high_memory)
|
||||
return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
|
||||
unsigned long addr = (unsigned long)io_addr & PAGE_MASK;
|
||||
|
||||
if (is_vmalloc_addr((void *)addr))
|
||||
vunmap((void *)addr);
|
||||
}
|
||||
EXPORT_SYMBOL(iounmap);
|
||||
|
||||
@@ -973,7 +973,7 @@ struct kvm_x86_ops {
|
||||
unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
|
||||
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
|
||||
|
||||
void (*tlb_flush)(struct kvm_vcpu *vcpu);
|
||||
void (*tlb_flush)(struct kvm_vcpu *vcpu, bool invalidate_gpa);
|
||||
|
||||
void (*run)(struct kvm_vcpu *vcpu);
|
||||
int (*handle_exit)(struct kvm_vcpu *vcpu);
|
||||
@@ -998,7 +998,7 @@ struct kvm_x86_ops {
|
||||
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
|
||||
void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
|
||||
void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
|
||||
void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu, bool set);
|
||||
void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
|
||||
void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
|
||||
void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
|
||||
int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -145,13 +145,31 @@ unsigned long __head __startup_64(unsigned long physaddr,
|
||||
* we might write invalid pmds, when the kernel is relocated
|
||||
* cleanup_highmap() fixes this up along with the mappings
|
||||
* beyond _end.
|
||||
*
|
||||
* Only the region occupied by the kernel image has so far
|
||||
* been checked against the table of usable memory regions
|
||||
* provided by the firmware, so invalidate pages outside that
|
||||
* region. A page table entry that maps to a reserved area of
|
||||
* memory would allow processor speculation into that area,
|
||||
* and on some hardware (particularly the UV platform) even
|
||||
* speculative access to some reserved areas is caught as an
|
||||
* error, causing the BIOS to halt the system.
|
||||
*/
|
||||
|
||||
pmd = fixup_pointer(level2_kernel_pgt, physaddr);
|
||||
for (i = 0; i < PTRS_PER_PMD; i++) {
|
||||
|
||||
/* invalidate pages before the kernel image */
|
||||
for (i = 0; i < pmd_index((unsigned long)_text); i++)
|
||||
pmd[i] &= ~_PAGE_PRESENT;
|
||||
|
||||
/* fixup pages that are part of the kernel image */
|
||||
for (; i <= pmd_index((unsigned long)_end); i++)
|
||||
if (pmd[i] & _PAGE_PRESENT)
|
||||
pmd[i] += load_delta;
|
||||
}
|
||||
|
||||
/* invalidate pages after the kernel image */
|
||||
for (; i < PTRS_PER_PMD; i++)
|
||||
pmd[i] &= ~_PAGE_PRESENT;
|
||||
|
||||
/*
|
||||
* Fixup phys_base - remove the memory encryption mask to obtain
|
||||
|
||||
@@ -1967,13 +1967,11 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
|
||||
}
|
||||
}
|
||||
|
||||
if ((old_value ^ value) & X2APIC_ENABLE) {
|
||||
if (value & X2APIC_ENABLE) {
|
||||
kvm_apic_set_x2apic_id(apic, vcpu->vcpu_id);
|
||||
kvm_x86_ops->set_virtual_x2apic_mode(vcpu, true);
|
||||
} else
|
||||
kvm_x86_ops->set_virtual_x2apic_mode(vcpu, false);
|
||||
}
|
||||
if (((old_value ^ value) & X2APIC_ENABLE) && (value & X2APIC_ENABLE))
|
||||
kvm_apic_set_x2apic_id(apic, vcpu->vcpu_id);
|
||||
|
||||
if ((old_value ^ value) & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE))
|
||||
kvm_x86_ops->set_virtual_apic_mode(vcpu);
|
||||
|
||||
apic->base_address = apic->vcpu->arch.apic_base &
|
||||
MSR_IA32_APICBASE_BASE;
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
#define APIC_BUS_CYCLE_NS 1
|
||||
#define APIC_BUS_FREQUENCY (1000000000ULL / APIC_BUS_CYCLE_NS)
|
||||
|
||||
enum lapic_mode {
|
||||
LAPIC_MODE_DISABLED = 0,
|
||||
LAPIC_MODE_INVALID = X2APIC_ENABLE,
|
||||
LAPIC_MODE_XAPIC = MSR_IA32_APICBASE_ENABLE,
|
||||
LAPIC_MODE_X2APIC = MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE,
|
||||
};
|
||||
|
||||
struct kvm_timer {
|
||||
struct hrtimer timer;
|
||||
s64 period; /* unit: ns */
|
||||
@@ -89,6 +96,7 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
|
||||
int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
|
||||
int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
|
||||
int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
|
||||
enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu);
|
||||
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
|
||||
|
||||
u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
|
||||
@@ -220,4 +228,10 @@ void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu);
|
||||
void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu);
|
||||
bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu);
|
||||
void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu);
|
||||
|
||||
static inline enum lapic_mode kvm_apic_mode(u64 apic_base)
|
||||
{
|
||||
return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -299,7 +299,7 @@ static int vgif = true;
|
||||
module_param(vgif, int, 0444);
|
||||
|
||||
static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
|
||||
static void svm_flush_tlb(struct kvm_vcpu *vcpu);
|
||||
static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa);
|
||||
static void svm_complete_interrupts(struct vcpu_svm *svm);
|
||||
|
||||
static int nested_svm_exit_handled(struct vcpu_svm *svm);
|
||||
@@ -2097,7 +2097,7 @@ static int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
||||
return 1;
|
||||
|
||||
if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
|
||||
svm_flush_tlb(vcpu);
|
||||
svm_flush_tlb(vcpu, true);
|
||||
|
||||
vcpu->arch.cr4 = cr4;
|
||||
if (!npt_enabled)
|
||||
@@ -2438,7 +2438,7 @@ static void nested_svm_set_tdp_cr3(struct kvm_vcpu *vcpu,
|
||||
|
||||
svm->vmcb->control.nested_cr3 = __sme_set(root);
|
||||
mark_dirty(svm->vmcb, VMCB_NPT);
|
||||
svm_flush_tlb(vcpu);
|
||||
svm_flush_tlb(vcpu, true);
|
||||
}
|
||||
|
||||
static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
|
||||
@@ -3111,7 +3111,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm)
|
||||
svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions;
|
||||
svm->nested.intercept = nested_vmcb->control.intercept;
|
||||
|
||||
svm_flush_tlb(&svm->vcpu);
|
||||
svm_flush_tlb(&svm->vcpu, true);
|
||||
svm->vmcb->control.int_ctl = nested_vmcb->control.int_ctl | V_INTR_MASKING_MASK;
|
||||
if (nested_vmcb->control.int_ctl & V_INTR_MASKING_MASK)
|
||||
svm->vcpu.arch.hflags |= HF_VINTR_MASK;
|
||||
@@ -4589,7 +4589,7 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
|
||||
set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
|
||||
}
|
||||
|
||||
static void svm_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
|
||||
static void svm_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -4947,7 +4947,7 @@ static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void svm_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
||||
@@ -5288,7 +5288,7 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
|
||||
|
||||
svm->vmcb->save.cr3 = __sme_set(root);
|
||||
mark_dirty(svm->vmcb, VMCB_CR);
|
||||
svm_flush_tlb(vcpu);
|
||||
svm_flush_tlb(vcpu, true);
|
||||
}
|
||||
|
||||
static void set_tdp_cr3(struct kvm_vcpu *vcpu, unsigned long root)
|
||||
@@ -5302,7 +5302,7 @@ static void set_tdp_cr3(struct kvm_vcpu *vcpu, unsigned long root)
|
||||
svm->vmcb->save.cr3 = kvm_read_cr3(vcpu);
|
||||
mark_dirty(svm->vmcb, VMCB_CR);
|
||||
|
||||
svm_flush_tlb(vcpu);
|
||||
svm_flush_tlb(vcpu, true);
|
||||
}
|
||||
|
||||
static int is_disabled(void)
|
||||
@@ -5713,7 +5713,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
|
||||
.enable_nmi_window = enable_nmi_window,
|
||||
.enable_irq_window = enable_irq_window,
|
||||
.update_cr8_intercept = update_cr8_intercept,
|
||||
.set_virtual_x2apic_mode = svm_set_virtual_x2apic_mode,
|
||||
.set_virtual_apic_mode = svm_set_virtual_apic_mode,
|
||||
.get_enable_apicv = svm_get_enable_apicv,
|
||||
.refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
|
||||
.load_eoi_exitmap = svm_load_eoi_exitmap,
|
||||
|
||||
@@ -591,7 +591,8 @@ struct nested_vmx {
|
||||
*/
|
||||
bool sync_shadow_vmcs;
|
||||
|
||||
bool change_vmcs01_virtual_x2apic_mode;
|
||||
bool change_vmcs01_virtual_apic_mode;
|
||||
|
||||
/* L2 must run next, and mustn't decide to exit to L1. */
|
||||
bool nested_run_pending;
|
||||
|
||||
@@ -4427,9 +4428,10 @@ static void exit_lmode(struct kvm_vcpu *vcpu)
|
||||
|
||||
#endif
|
||||
|
||||
static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid)
|
||||
static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid,
|
||||
bool invalidate_gpa)
|
||||
{
|
||||
if (enable_ept) {
|
||||
if (enable_ept && (invalidate_gpa || !enable_vpid)) {
|
||||
if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
|
||||
return;
|
||||
ept_sync_context(construct_eptp(vcpu, vcpu->arch.mmu.root_hpa));
|
||||
@@ -4438,15 +4440,9 @@ static inline void __vmx_flush_tlb(struct kvm_vcpu *vcpu, int vpid)
|
||||
}
|
||||
}
|
||||
|
||||
static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
static void vmx_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
|
||||
{
|
||||
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid);
|
||||
}
|
||||
|
||||
static void vmx_flush_tlb_ept_only(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (enable_ept)
|
||||
vmx_flush_tlb(vcpu);
|
||||
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->vpid, invalidate_gpa);
|
||||
}
|
||||
|
||||
static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
|
||||
@@ -4644,7 +4640,7 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
|
||||
ept_load_pdptrs(vcpu);
|
||||
}
|
||||
|
||||
vmx_flush_tlb(vcpu);
|
||||
vmx_flush_tlb(vcpu, true);
|
||||
vmcs_writel(GUEST_CR3, guest_cr3);
|
||||
}
|
||||
|
||||
@@ -8314,7 +8310,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
}
|
||||
|
||||
__vmx_flush_tlb(vcpu, vmx->nested.vpid02);
|
||||
__vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
|
||||
nested_vmx_succeed(vcpu);
|
||||
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
@@ -9295,31 +9291,43 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
|
||||
vmcs_write32(TPR_THRESHOLD, irr);
|
||||
}
|
||||
|
||||
static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
|
||||
static void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u32 sec_exec_control;
|
||||
|
||||
if (!lapic_in_kernel(vcpu))
|
||||
return;
|
||||
|
||||
/* Postpone execution until vmcs01 is the current VMCS. */
|
||||
if (is_guest_mode(vcpu)) {
|
||||
to_vmx(vcpu)->nested.change_vmcs01_virtual_x2apic_mode = true;
|
||||
to_vmx(vcpu)->nested.change_vmcs01_virtual_apic_mode = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cpu_has_vmx_virtualize_x2apic_mode())
|
||||
return;
|
||||
|
||||
if (!cpu_need_tpr_shadow(vcpu))
|
||||
return;
|
||||
|
||||
sec_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
|
||||
sec_exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
|
||||
SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
|
||||
|
||||
if (set) {
|
||||
sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||
sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
|
||||
} else {
|
||||
sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
|
||||
sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||
vmx_flush_tlb_ept_only(vcpu);
|
||||
switch (kvm_get_apic_mode(vcpu)) {
|
||||
case LAPIC_MODE_INVALID:
|
||||
WARN_ONCE(true, "Invalid local APIC state");
|
||||
case LAPIC_MODE_DISABLED:
|
||||
break;
|
||||
case LAPIC_MODE_XAPIC:
|
||||
if (flexpriority_enabled) {
|
||||
sec_exec_control |=
|
||||
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||
vmx_flush_tlb(vcpu, true);
|
||||
}
|
||||
break;
|
||||
case LAPIC_MODE_X2APIC:
|
||||
if (cpu_has_vmx_virtualize_x2apic_mode())
|
||||
sec_exec_control |=
|
||||
SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
|
||||
break;
|
||||
}
|
||||
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control);
|
||||
|
||||
@@ -9347,7 +9355,7 @@ static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
|
||||
!nested_cpu_has2(get_vmcs12(&vmx->vcpu),
|
||||
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
|
||||
vmcs_write64(APIC_ACCESS_ADDR, hpa);
|
||||
vmx_flush_tlb_ept_only(vcpu);
|
||||
vmx_flush_tlb(vcpu, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11214,11 +11222,11 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
|
||||
vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->nested.vpid02);
|
||||
if (vmcs12->virtual_processor_id != vmx->nested.last_vpid) {
|
||||
vmx->nested.last_vpid = vmcs12->virtual_processor_id;
|
||||
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
|
||||
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02, true);
|
||||
}
|
||||
} else {
|
||||
vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
|
||||
vmx_flush_tlb(vcpu);
|
||||
vmx_flush_tlb(vcpu, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11242,7 +11250,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
|
||||
}
|
||||
} else if (nested_cpu_has2(vmcs12,
|
||||
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
|
||||
vmx_flush_tlb_ept_only(vcpu);
|
||||
vmx_flush_tlb(vcpu, true);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -11921,7 +11929,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
|
||||
* L1's vpid. TODO: move to a more elaborate solution, giving
|
||||
* each L2 its own vpid and exposing the vpid feature to L1.
|
||||
*/
|
||||
vmx_flush_tlb(vcpu);
|
||||
vmx_flush_tlb(vcpu, true);
|
||||
}
|
||||
/* Restore posted intr vector. */
|
||||
if (nested_cpu_has_posted_intr(vmcs12))
|
||||
@@ -12190,14 +12198,13 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
|
||||
if (kvm_has_tsc_control)
|
||||
decache_tsc_multiplier(vmx);
|
||||
|
||||
if (vmx->nested.change_vmcs01_virtual_x2apic_mode) {
|
||||
vmx->nested.change_vmcs01_virtual_x2apic_mode = false;
|
||||
vmx_set_virtual_x2apic_mode(vcpu,
|
||||
vcpu->arch.apic_base & X2APIC_ENABLE);
|
||||
if (vmx->nested.change_vmcs01_virtual_apic_mode) {
|
||||
vmx->nested.change_vmcs01_virtual_apic_mode = false;
|
||||
vmx_set_virtual_apic_mode(vcpu);
|
||||
} else if (!nested_cpu_has_ept(vmcs12) &&
|
||||
nested_cpu_has2(vmcs12,
|
||||
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
|
||||
vmx_flush_tlb_ept_only(vcpu);
|
||||
vmx_flush_tlb(vcpu, true);
|
||||
}
|
||||
|
||||
/* This is needed for same reason as it was needed in prepare_vmcs02 */
|
||||
@@ -12754,7 +12761,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
|
||||
.enable_nmi_window = enable_nmi_window,
|
||||
.enable_irq_window = enable_irq_window,
|
||||
.update_cr8_intercept = update_cr8_intercept,
|
||||
.set_virtual_x2apic_mode = vmx_set_virtual_x2apic_mode,
|
||||
.set_virtual_apic_mode = vmx_set_virtual_apic_mode,
|
||||
.set_apic_access_page_addr = vmx_set_apic_access_page_addr,
|
||||
.get_enable_apicv = vmx_get_enable_apicv,
|
||||
.refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
|
||||
|
||||
@@ -306,23 +306,27 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_get_apic_base);
|
||||
|
||||
enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return kvm_apic_mode(kvm_get_apic_base(vcpu));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_get_apic_mode);
|
||||
|
||||
int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
{
|
||||
u64 old_state = vcpu->arch.apic_base &
|
||||
(MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
|
||||
u64 new_state = msr_info->data &
|
||||
(MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
|
||||
enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
|
||||
enum lapic_mode new_mode = kvm_apic_mode(msr_info->data);
|
||||
u64 reserved_bits = ((~0ULL) << cpuid_maxphyaddr(vcpu)) | 0x2ff |
|
||||
(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
|
||||
|
||||
if ((msr_info->data & reserved_bits) || new_state == X2APIC_ENABLE)
|
||||
return 1;
|
||||
if (!msr_info->host_initiated &&
|
||||
((new_state == MSR_IA32_APICBASE_ENABLE &&
|
||||
old_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)) ||
|
||||
(new_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) &&
|
||||
old_state == 0)))
|
||||
if ((msr_info->data & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
|
||||
return 1;
|
||||
if (!msr_info->host_initiated) {
|
||||
if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
|
||||
return 1;
|
||||
if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
|
||||
return 1;
|
||||
}
|
||||
|
||||
kvm_lapic_set_base(vcpu, msr_info->data);
|
||||
return 0;
|
||||
@@ -6943,10 +6947,10 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
|
||||
kvm_x86_ops->load_eoi_exitmap(vcpu, eoi_exit_bitmap);
|
||||
}
|
||||
|
||||
static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
|
||||
{
|
||||
++vcpu->stat.tlb_flush;
|
||||
kvm_x86_ops->tlb_flush(vcpu);
|
||||
kvm_x86_ops->tlb_flush(vcpu, invalidate_gpa);
|
||||
}
|
||||
|
||||
void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
|
||||
@@ -7017,7 +7021,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
if (kvm_check_request(KVM_REQ_MMU_SYNC, vcpu))
|
||||
kvm_mmu_sync_roots(vcpu);
|
||||
if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
|
||||
kvm_vcpu_flush_tlb(vcpu);
|
||||
kvm_vcpu_flush_tlb(vcpu, true);
|
||||
if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) {
|
||||
vcpu->run->exit_reason = KVM_EXIT_TPR_ACCESS;
|
||||
r = 0;
|
||||
|
||||
@@ -77,7 +77,9 @@ static efi_system_table_t __init *xen_efi_probe(void)
|
||||
efi.get_variable = xen_efi_get_variable;
|
||||
efi.get_next_variable = xen_efi_get_next_variable;
|
||||
efi.set_variable = xen_efi_set_variable;
|
||||
efi.set_variable_nonblocking = xen_efi_set_variable;
|
||||
efi.query_variable_info = xen_efi_query_variable_info;
|
||||
efi.query_variable_info_nonblocking = xen_efi_query_variable_info;
|
||||
efi.update_capsule = xen_efi_update_capsule;
|
||||
efi.query_capsule_caps = xen_efi_query_capsule_caps;
|
||||
efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count;
|
||||
|
||||
@@ -114,13 +114,6 @@ EXPORT_SYMBOL(__invalidate_icache_range);
|
||||
// FIXME EXPORT_SYMBOL(screen_info);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(outsb);
|
||||
EXPORT_SYMBOL(outsw);
|
||||
EXPORT_SYMBOL(outsl);
|
||||
EXPORT_SYMBOL(insb);
|
||||
EXPORT_SYMBOL(insw);
|
||||
EXPORT_SYMBOL(insl);
|
||||
|
||||
extern long common_exception_return;
|
||||
EXPORT_SYMBOL(common_exception_return);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fwnode.h>
|
||||
@@ -2845,6 +2846,8 @@ void device_shutdown(void)
|
||||
wait_for_device_probe();
|
||||
device_block_probing();
|
||||
|
||||
cpufreq_suspend();
|
||||
|
||||
spin_lock(&devices_kset->list_lock);
|
||||
/*
|
||||
* Walk the devices list backward, shutting down each in turn.
|
||||
|
||||
@@ -552,6 +552,9 @@ store_soft_offline_page(struct device *dev,
|
||||
pfn >>= PAGE_SHIFT;
|
||||
if (!pfn_valid(pfn))
|
||||
return -ENXIO;
|
||||
/* Only online pages can be soft-offlined (esp., not ZONE_DEVICE). */
|
||||
if (!pfn_to_online_page(pfn))
|
||||
return -EIO;
|
||||
ret = soft_offline_page(pfn_to_page(pfn), 0);
|
||||
return ret == 0 ? count : ret;
|
||||
}
|
||||
|
||||
@@ -1605,6 +1605,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
arg = (unsigned long) compat_ptr(arg);
|
||||
case LOOP_SET_FD:
|
||||
case LOOP_CHANGE_FD:
|
||||
case LOOP_SET_DIRECT_IO:
|
||||
err = lo_ioctl(bdev, mode, cmd, arg);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -2599,14 +2599,6 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
|
||||
|
||||
/*
|
||||
* Stop cpufreq at shutdown to make sure it isn't holding any locks
|
||||
* or mutexes when secondary CPUs are halted.
|
||||
*/
|
||||
static struct syscore_ops cpufreq_syscore_ops = {
|
||||
.shutdown = cpufreq_suspend,
|
||||
};
|
||||
|
||||
struct kobject *cpufreq_global_kobject;
|
||||
EXPORT_SYMBOL(cpufreq_global_kobject);
|
||||
|
||||
@@ -2618,8 +2610,6 @@ static int __init cpufreq_core_init(void)
|
||||
cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
|
||||
BUG_ON(!cpufreq_global_kobject);
|
||||
|
||||
register_syscore_ops(&cpufreq_syscore_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_param(off, int, 0444);
|
||||
|
||||
@@ -572,6 +572,41 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
if (!amdgpu_si_support) {
|
||||
switch (flags & AMD_ASIC_MASK) {
|
||||
case CHIP_TAHITI:
|
||||
case CHIP_PITCAIRN:
|
||||
case CHIP_VERDE:
|
||||
case CHIP_OLAND:
|
||||
case CHIP_HAINAN:
|
||||
dev_info(&pdev->dev,
|
||||
"SI support provided by radeon.\n");
|
||||
dev_info(&pdev->dev,
|
||||
"Use radeon.si_support=0 amdgpu.si_support=1 to override.\n"
|
||||
);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||
if (!amdgpu_cik_support) {
|
||||
switch (flags & AMD_ASIC_MASK) {
|
||||
case CHIP_KAVERI:
|
||||
case CHIP_BONAIRE:
|
||||
case CHIP_HAWAII:
|
||||
case CHIP_KABINI:
|
||||
case CHIP_MULLINS:
|
||||
dev_info(&pdev->dev,
|
||||
"CIK support provided by radeon.\n");
|
||||
dev_info(&pdev->dev,
|
||||
"Use radeon.cik_support=0 amdgpu.cik_support=1 to override.\n"
|
||||
);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get rid of things like offb */
|
||||
ret = amdgpu_kick_out_firmware_fb(pdev);
|
||||
if (ret)
|
||||
|
||||
@@ -87,41 +87,6 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
||||
struct amdgpu_device *adev;
|
||||
int r, acpi_status;
|
||||
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
if (!amdgpu_si_support) {
|
||||
switch (flags & AMD_ASIC_MASK) {
|
||||
case CHIP_TAHITI:
|
||||
case CHIP_PITCAIRN:
|
||||
case CHIP_VERDE:
|
||||
case CHIP_OLAND:
|
||||
case CHIP_HAINAN:
|
||||
dev_info(dev->dev,
|
||||
"SI support provided by radeon.\n");
|
||||
dev_info(dev->dev,
|
||||
"Use radeon.si_support=0 amdgpu.si_support=1 to override.\n"
|
||||
);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||
if (!amdgpu_cik_support) {
|
||||
switch (flags & AMD_ASIC_MASK) {
|
||||
case CHIP_KAVERI:
|
||||
case CHIP_BONAIRE:
|
||||
case CHIP_HAWAII:
|
||||
case CHIP_KABINI:
|
||||
case CHIP_MULLINS:
|
||||
dev_info(dev->dev,
|
||||
"CIK support provided by radeon.\n");
|
||||
dev_info(dev->dev,
|
||||
"Use radeon.cik_support=0 amdgpu.cik_support=1 to override.\n"
|
||||
);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
adev = kzalloc(sizeof(struct amdgpu_device), GFP_KERNEL);
|
||||
if (adev == NULL) {
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -164,6 +164,9 @@ static const struct edid_quirk {
|
||||
/* Medion MD 30217 PG */
|
||||
{ "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 },
|
||||
|
||||
/* Lenovo G50 */
|
||||
{ "SDC", 18514, EDID_QUIRK_FORCE_6BPC },
|
||||
|
||||
/* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
|
||||
{ "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
|
||||
|
||||
|
||||
@@ -368,19 +368,11 @@ radeon_pci_remove(struct pci_dev *pdev)
|
||||
static void
|
||||
radeon_pci_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *ddev = pci_get_drvdata(pdev);
|
||||
|
||||
/* if we are running in a VM, make sure the device
|
||||
* torn down properly on reboot/shutdown
|
||||
*/
|
||||
if (radeon_device_is_virtual())
|
||||
radeon_pci_remove(pdev);
|
||||
|
||||
/* Some adapters need to be suspended before a
|
||||
* shutdown occurs in order to prevent an error
|
||||
* during kexec.
|
||||
*/
|
||||
radeon_suspend_kms(ddev, true, true, false);
|
||||
}
|
||||
|
||||
static int radeon_pmops_suspend(struct device *dev)
|
||||
|
||||
@@ -260,13 +260,17 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int err;
|
||||
struct fw_ri_tpte tpt;
|
||||
struct fw_ri_tpte *tpt;
|
||||
u32 stag_idx;
|
||||
static atomic_t key;
|
||||
|
||||
if (c4iw_fatal_error(rdev))
|
||||
return -EIO;
|
||||
|
||||
tpt = kmalloc(sizeof(*tpt), GFP_KERNEL);
|
||||
if (!tpt)
|
||||
return -ENOMEM;
|
||||
|
||||
stag_state = stag_state > 0;
|
||||
stag_idx = (*stag) >> 8;
|
||||
|
||||
@@ -276,6 +280,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
|
||||
mutex_lock(&rdev->stats.lock);
|
||||
rdev->stats.stag.fail++;
|
||||
mutex_unlock(&rdev->stats.lock);
|
||||
kfree(tpt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
mutex_lock(&rdev->stats.lock);
|
||||
@@ -290,28 +295,28 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
|
||||
|
||||
/* write TPT entry */
|
||||
if (reset_tpt_entry)
|
||||
memset(&tpt, 0, sizeof(tpt));
|
||||
memset(tpt, 0, sizeof(*tpt));
|
||||
else {
|
||||
tpt.valid_to_pdid = cpu_to_be32(FW_RI_TPTE_VALID_F |
|
||||
tpt->valid_to_pdid = cpu_to_be32(FW_RI_TPTE_VALID_F |
|
||||
FW_RI_TPTE_STAGKEY_V((*stag & FW_RI_TPTE_STAGKEY_M)) |
|
||||
FW_RI_TPTE_STAGSTATE_V(stag_state) |
|
||||
FW_RI_TPTE_STAGTYPE_V(type) | FW_RI_TPTE_PDID_V(pdid));
|
||||
tpt.locread_to_qpid = cpu_to_be32(FW_RI_TPTE_PERM_V(perm) |
|
||||
tpt->locread_to_qpid = cpu_to_be32(FW_RI_TPTE_PERM_V(perm) |
|
||||
(bind_enabled ? FW_RI_TPTE_MWBINDEN_F : 0) |
|
||||
FW_RI_TPTE_ADDRTYPE_V((zbva ? FW_RI_ZERO_BASED_TO :
|
||||
FW_RI_VA_BASED_TO))|
|
||||
FW_RI_TPTE_PS_V(page_size));
|
||||
tpt.nosnoop_pbladdr = !pbl_size ? 0 : cpu_to_be32(
|
||||
tpt->nosnoop_pbladdr = !pbl_size ? 0 : cpu_to_be32(
|
||||
FW_RI_TPTE_PBLADDR_V(PBL_OFF(rdev, pbl_addr)>>3));
|
||||
tpt.len_lo = cpu_to_be32((u32)(len & 0xffffffffUL));
|
||||
tpt.va_hi = cpu_to_be32((u32)(to >> 32));
|
||||
tpt.va_lo_fbo = cpu_to_be32((u32)(to & 0xffffffffUL));
|
||||
tpt.dca_mwbcnt_pstag = cpu_to_be32(0);
|
||||
tpt.len_hi = cpu_to_be32((u32)(len >> 32));
|
||||
tpt->len_lo = cpu_to_be32((u32)(len & 0xffffffffUL));
|
||||
tpt->va_hi = cpu_to_be32((u32)(to >> 32));
|
||||
tpt->va_lo_fbo = cpu_to_be32((u32)(to & 0xffffffffUL));
|
||||
tpt->dca_mwbcnt_pstag = cpu_to_be32(0);
|
||||
tpt->len_hi = cpu_to_be32((u32)(len >> 32));
|
||||
}
|
||||
err = write_adapter_mem(rdev, stag_idx +
|
||||
(rdev->lldi.vr->stag.start >> 5),
|
||||
sizeof(tpt), &tpt, skb);
|
||||
sizeof(*tpt), tpt, skb);
|
||||
|
||||
if (reset_tpt_entry) {
|
||||
c4iw_put_resource(&rdev->resource.tpt_table, stag_idx);
|
||||
@@ -319,6 +324,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
|
||||
rdev->stats.stag.cur -= 32;
|
||||
mutex_unlock(&rdev->stats.lock);
|
||||
}
|
||||
kfree(tpt);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,10 +248,7 @@ static int da9063_onkey_probe(struct platform_device *pdev)
|
||||
onkey->input->phys = onkey->phys;
|
||||
onkey->input->dev.parent = &pdev->dev;
|
||||
|
||||
if (onkey->key_power)
|
||||
input_set_capability(onkey->input, EV_KEY, KEY_POWER);
|
||||
|
||||
input_set_capability(onkey->input, EV_KEY, KEY_SLEEP);
|
||||
input_set_capability(onkey->input, EV_KEY, KEY_POWER);
|
||||
|
||||
INIT_DELAYED_WORK(&onkey->work, da9063_poll_on);
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
|
||||
}
|
||||
|
||||
mutex_lock(&data->irq_mutex);
|
||||
bitmap_and(data->irq_status, data->irq_status, data->current_irq_mask,
|
||||
bitmap_and(data->irq_status, data->irq_status, data->fn_irq_bits,
|
||||
data->irq_count);
|
||||
/*
|
||||
* At this point, irq_status has all bits that are set in the
|
||||
@@ -412,6 +412,8 @@ static int rmi_driver_set_irq_bits(struct rmi_device *rmi_dev,
|
||||
bitmap_copy(data->current_irq_mask, data->new_irq_mask,
|
||||
data->num_of_irq_regs);
|
||||
|
||||
bitmap_or(data->fn_irq_bits, data->fn_irq_bits, mask, data->irq_count);
|
||||
|
||||
error_unlock:
|
||||
mutex_unlock(&data->irq_mutex);
|
||||
return error;
|
||||
@@ -425,6 +427,8 @@ static int rmi_driver_clear_irq_bits(struct rmi_device *rmi_dev,
|
||||
struct device *dev = &rmi_dev->dev;
|
||||
|
||||
mutex_lock(&data->irq_mutex);
|
||||
bitmap_andnot(data->fn_irq_bits,
|
||||
data->fn_irq_bits, mask, data->irq_count);
|
||||
bitmap_andnot(data->new_irq_mask,
|
||||
data->current_irq_mask, mask, data->irq_count);
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
|
||||
} else {
|
||||
pr_err("md/raid0:%s: cannot assemble multi-zone RAID0 with default_layout setting\n",
|
||||
mdname(mddev));
|
||||
pr_err("md/raid0: please set raid.default_layout to 1 or 2\n");
|
||||
pr_err("md/raid0: please set raid0.default_layout to 1 or 2\n");
|
||||
err = -ENOTSUPP;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@@ -947,7 +947,7 @@ static int jmb38x_ms_probe(struct pci_dev *pdev,
|
||||
if (!cnt) {
|
||||
rc = -ENODEV;
|
||||
pci_dev_busy = 1;
|
||||
goto err_out;
|
||||
goto err_out_int;
|
||||
}
|
||||
|
||||
jm = kzalloc(sizeof(struct jmb38x_ms)
|
||||
|
||||
@@ -551,7 +551,7 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
|
||||
|
||||
/* Setup connection between CPU port & user ports */
|
||||
for (i = 0; i < DSA_MAX_PORTS; i++) {
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
/* CPU port gets connected to all user ports of the switch */
|
||||
if (dsa_is_cpu_port(ds, i)) {
|
||||
qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
|
||||
@@ -900,7 +900,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
|
||||
if (id != QCA8K_ID_QCA8337)
|
||||
return -ENODEV;
|
||||
|
||||
priv->ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS);
|
||||
priv->ds = dsa_switch_alloc(&mdiodev->dev, QCA8K_NUM_PORTS);
|
||||
if (!priv->ds)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -368,6 +368,7 @@ struct bcmgenet_mib_counters {
|
||||
#define EXT_PWR_DOWN_PHY_EN (1 << 20)
|
||||
|
||||
#define EXT_RGMII_OOB_CTRL 0x0C
|
||||
#define RGMII_MODE_EN_V123 (1 << 0)
|
||||
#define RGMII_LINK (1 << 4)
|
||||
#define OOB_DISABLE (1 << 5)
|
||||
#define RGMII_MODE_EN (1 << 6)
|
||||
|
||||
@@ -277,7 +277,11 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
|
||||
*/
|
||||
if (priv->ext_phy) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||
reg |= RGMII_MODE_EN | id_mode_dis;
|
||||
reg |= id_mode_dis;
|
||||
if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
|
||||
reg |= RGMII_MODE_EN_V123;
|
||||
else
|
||||
reg |= RGMII_MODE_EN;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||
}
|
||||
|
||||
@@ -292,11 +296,12 @@ int bcmgenet_mii_probe(struct net_device *dev)
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
struct phy_device *phydev;
|
||||
u32 phy_flags;
|
||||
u32 phy_flags = 0;
|
||||
int ret;
|
||||
|
||||
/* Communicate the integrated PHY revision */
|
||||
phy_flags = priv->gphy_rev;
|
||||
if (priv->internal_phy)
|
||||
phy_flags = priv->gphy_rev;
|
||||
|
||||
/* Initialize link state variables that bcmgenet_mii_setup() uses */
|
||||
priv->old_link = -1;
|
||||
|
||||
@@ -156,11 +156,15 @@ static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev,
|
||||
{
|
||||
u32 time_cnt;
|
||||
u32 reg_value;
|
||||
int ret;
|
||||
|
||||
regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val);
|
||||
|
||||
for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) {
|
||||
regmap_read(mdio_dev->subctrl_vbase, st_reg, ®_value);
|
||||
ret = regmap_read(mdio_dev->subctrl_vbase, st_reg, ®_value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
reg_value &= st_msk;
|
||||
if ((!!check_st) == (!!reg_value))
|
||||
break;
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
|
||||
#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
|
||||
|
||||
#define LIB82596_DMA_ATTR DMA_ATTR_NON_CONSISTENT
|
||||
|
||||
#define DMA_WBACK(ndev, addr, len) \
|
||||
do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
|
||||
|
||||
@@ -199,7 +201,7 @@ static int __exit lan_remove_chip(struct parisc_device *pdev)
|
||||
|
||||
unregister_netdev (dev);
|
||||
dma_free_attrs(&pdev->dev, sizeof(struct i596_private), lp->dma,
|
||||
lp->dma_addr, DMA_ATTR_NON_CONSISTENT);
|
||||
lp->dma_addr, LIB82596_DMA_ATTR);
|
||||
free_netdev (dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1065,7 +1065,7 @@ static int i82596_probe(struct net_device *dev)
|
||||
|
||||
dma = dma_alloc_attrs(dev->dev.parent, sizeof(struct i596_dma),
|
||||
&lp->dma_addr, GFP_KERNEL,
|
||||
DMA_ATTR_NON_CONSISTENT);
|
||||
LIB82596_DMA_ATTR);
|
||||
if (!dma) {
|
||||
printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
|
||||
return -ENOMEM;
|
||||
@@ -1087,7 +1087,7 @@ static int i82596_probe(struct net_device *dev)
|
||||
i = register_netdev(dev);
|
||||
if (i) {
|
||||
dma_free_attrs(dev->dev.parent, sizeof(struct i596_dma),
|
||||
dma, lp->dma_addr, DMA_ATTR_NON_CONSISTENT);
|
||||
dma, lp->dma_addr, LIB82596_DMA_ATTR);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
static const char sni_82596_string[] = "snirm_82596";
|
||||
|
||||
#define LIB82596_DMA_ATTR 0
|
||||
|
||||
#define DMA_WBACK(priv, addr, len) do { } while (0)
|
||||
#define DMA_INV(priv, addr, len) do { } while (0)
|
||||
#define DMA_WBACK_INV(priv, addr, len) do { } while (0)
|
||||
@@ -151,7 +153,7 @@ static int sni_82596_driver_remove(struct platform_device *pdev)
|
||||
|
||||
unregister_netdev(dev);
|
||||
dma_free_attrs(dev->dev.parent, sizeof(struct i596_private), lp->dma,
|
||||
lp->dma_addr, DMA_ATTR_NON_CONSISTENT);
|
||||
lp->dma_addr, LIB82596_DMA_ATTR);
|
||||
iounmap(lp->ca);
|
||||
iounmap(lp->mpu_port);
|
||||
free_netdev (dev);
|
||||
|
||||
@@ -4402,8 +4402,10 @@ int stmmac_suspend(struct device *dev)
|
||||
priv->hw->mac->set_mac(priv->ioaddr, false);
|
||||
pinctrl_pm_select_sleep_state(priv->device);
|
||||
/* Disable clock in case of PWM is off */
|
||||
clk_disable(priv->plat->pclk);
|
||||
clk_disable(priv->plat->stmmac_clk);
|
||||
if (priv->plat->clk_ptp_ref)
|
||||
clk_disable_unprepare(priv->plat->clk_ptp_ref);
|
||||
clk_disable_unprepare(priv->plat->pclk);
|
||||
clk_disable_unprepare(priv->plat->stmmac_clk);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
@@ -4468,8 +4470,10 @@ int stmmac_resume(struct device *dev)
|
||||
} else {
|
||||
pinctrl_pm_select_default_state(priv->device);
|
||||
/* enable the clk previously disabled */
|
||||
clk_enable(priv->plat->stmmac_clk);
|
||||
clk_enable(priv->plat->pclk);
|
||||
clk_prepare_enable(priv->plat->stmmac_clk);
|
||||
clk_prepare_enable(priv->plat->pclk);
|
||||
if (priv->plat->clk_ptp_ref)
|
||||
clk_prepare_enable(priv->plat->clk_ptp_ref);
|
||||
/* reset the phy so that it's ready */
|
||||
if (priv->mii)
|
||||
stmmac_mdio_reset(priv->mii);
|
||||
|
||||
@@ -3153,12 +3153,12 @@ static int ca8210_probe(struct spi_device *spi_device)
|
||||
goto error;
|
||||
}
|
||||
|
||||
priv->spi->dev.platform_data = pdata;
|
||||
ret = ca8210_get_platform_data(priv->spi, pdata);
|
||||
if (ret) {
|
||||
dev_crit(&spi_device->dev, "ca8210_get_platform_data failed\n");
|
||||
goto error;
|
||||
}
|
||||
priv->spi->dev.platform_data = pdata;
|
||||
|
||||
ret = ca8210_dev_com_init(priv);
|
||||
if (ret) {
|
||||
|
||||
@@ -4465,10 +4465,9 @@ static int rtl8152_reset_resume(struct usb_interface *intf)
|
||||
struct r8152 *tp = usb_get_intfdata(intf);
|
||||
|
||||
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
|
||||
mutex_lock(&tp->control);
|
||||
tp->rtl_ops.init(tp);
|
||||
queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0);
|
||||
mutex_unlock(&tp->control);
|
||||
set_ethernet_addr(tp);
|
||||
return rtl8152_resume(intf);
|
||||
}
|
||||
|
||||
|
||||
@@ -718,7 +718,6 @@ err_unmap:
|
||||
xenvif_unmap_frontend_data_rings(queue);
|
||||
netif_napi_del(&queue->napi);
|
||||
err:
|
||||
module_put(THIS_MODULE);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -748,19 +748,6 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_power_up - Put the given device into D0 forcibly
|
||||
* @dev: PCI device to power up
|
||||
*/
|
||||
void pci_power_up(struct pci_dev *dev)
|
||||
{
|
||||
if (platform_pci_power_manageable(dev))
|
||||
platform_pci_set_power_state(dev, PCI_D0);
|
||||
|
||||
pci_raw_set_power_state(dev, PCI_D0);
|
||||
pci_update_current_state(dev, PCI_D0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_platform_power_transition - Use platform to change device power state
|
||||
* @dev: PCI device to handle.
|
||||
@@ -939,6 +926,17 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
}
|
||||
EXPORT_SYMBOL(pci_set_power_state);
|
||||
|
||||
/**
|
||||
* pci_power_up - Put the given device into D0 forcibly
|
||||
* @dev: PCI device to power up
|
||||
*/
|
||||
void pci_power_up(struct pci_dev *dev)
|
||||
{
|
||||
__pci_start_power_transition(dev, PCI_D0);
|
||||
pci_raw_set_power_state(dev, PCI_D0);
|
||||
pci_update_current_state(dev, PCI_D0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_choose_state - Choose the power state of a PCI device
|
||||
* @dev: PCI device to be suspended
|
||||
|
||||
@@ -170,10 +170,10 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
|
||||
PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19),
|
||||
BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19),
|
||||
18, 2, "gpio", "uart"),
|
||||
PIN_GRP_GPIO("led0_od", 11, 1, BIT(20), "led"),
|
||||
PIN_GRP_GPIO("led1_od", 12, 1, BIT(21), "led"),
|
||||
PIN_GRP_GPIO("led2_od", 13, 1, BIT(22), "led"),
|
||||
PIN_GRP_GPIO("led3_od", 14, 1, BIT(23), "led"),
|
||||
PIN_GRP_GPIO_2("led0_od", 11, 1, BIT(20), BIT(20), 0, "led"),
|
||||
PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"),
|
||||
PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
|
||||
PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"),
|
||||
|
||||
};
|
||||
|
||||
@@ -205,11 +205,11 @@ static const struct armada_37xx_pin_data armada_37xx_pin_sb = {
|
||||
};
|
||||
|
||||
static inline void armada_37xx_update_reg(unsigned int *reg,
|
||||
unsigned int offset)
|
||||
unsigned int *offset)
|
||||
{
|
||||
/* We never have more than 2 registers */
|
||||
if (offset >= GPIO_PER_REG) {
|
||||
offset -= GPIO_PER_REG;
|
||||
if (*offset >= GPIO_PER_REG) {
|
||||
*offset -= GPIO_PER_REG;
|
||||
*reg += sizeof(u32);
|
||||
}
|
||||
}
|
||||
@@ -373,7 +373,7 @@ static inline void armada_37xx_irq_update_reg(unsigned int *reg,
|
||||
{
|
||||
int offset = irqd_to_hwirq(d);
|
||||
|
||||
armada_37xx_update_reg(reg, offset);
|
||||
armada_37xx_update_reg(reg, &offset);
|
||||
}
|
||||
|
||||
static int armada_37xx_gpio_direction_input(struct gpio_chip *chip,
|
||||
@@ -383,7 +383,7 @@ static int armada_37xx_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned int reg = OUTPUT_EN;
|
||||
unsigned int mask;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
|
||||
return regmap_update_bits(info->regmap, reg, mask, 0);
|
||||
@@ -396,7 +396,7 @@ static int armada_37xx_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int reg = OUTPUT_EN;
|
||||
unsigned int val, mask;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
regmap_read(info->regmap, reg, &val);
|
||||
|
||||
@@ -410,7 +410,7 @@ static int armada_37xx_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned int reg = OUTPUT_EN;
|
||||
unsigned int mask, val, ret;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
|
||||
ret = regmap_update_bits(info->regmap, reg, mask, mask);
|
||||
@@ -431,7 +431,7 @@ static int armada_37xx_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
unsigned int reg = INPUT_VAL;
|
||||
unsigned int val, mask;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
|
||||
regmap_read(info->regmap, reg, &val);
|
||||
@@ -446,7 +446,7 @@ static void armada_37xx_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned int reg = OUTPUT_VAL;
|
||||
unsigned int mask, val;
|
||||
|
||||
armada_37xx_update_reg(®, offset);
|
||||
armada_37xx_update_reg(®, &offset);
|
||||
mask = BIT(offset);
|
||||
val = value ? mask : 0;
|
||||
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
|
||||
struct kmem_cache *zfcp_fsf_qtcb_cache;
|
||||
|
||||
static bool ber_stop = true;
|
||||
module_param(ber_stop, bool, 0600);
|
||||
MODULE_PARM_DESC(ber_stop,
|
||||
"Shuts down FCP devices for FCP channels that report a bit-error count in excess of its threshold (default on)");
|
||||
|
||||
static void zfcp_fsf_request_timeout_handler(unsigned long data)
|
||||
{
|
||||
struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
|
||||
@@ -230,10 +235,15 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
|
||||
case FSF_STATUS_READ_SENSE_DATA_AVAIL:
|
||||
break;
|
||||
case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
|
||||
dev_warn(&adapter->ccw_device->dev,
|
||||
"The error threshold for checksum statistics "
|
||||
"has been exceeded\n");
|
||||
zfcp_dbf_hba_bit_err("fssrh_3", req);
|
||||
if (ber_stop) {
|
||||
dev_warn(&adapter->ccw_device->dev,
|
||||
"All paths over this FCP device are disused because of excessive bit errors\n");
|
||||
zfcp_erp_adapter_shutdown(adapter, 0, "fssrh_b");
|
||||
} else {
|
||||
dev_warn(&adapter->ccw_device->dev,
|
||||
"The error threshold for checksum statistics has been exceeded\n");
|
||||
}
|
||||
break;
|
||||
case FSF_STATUS_READ_LINK_DOWN:
|
||||
zfcp_fsf_status_read_link_down(req);
|
||||
|
||||
@@ -578,7 +578,6 @@ ch_release(struct inode *inode, struct file *file)
|
||||
scsi_changer *ch = file->private_data;
|
||||
|
||||
scsi_device_put(ch->device);
|
||||
ch->device = NULL;
|
||||
file->private_data = NULL;
|
||||
kref_put(&ch->ref, ch_destroy);
|
||||
return 0;
|
||||
|
||||
@@ -4221,11 +4221,11 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
*/
|
||||
if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ &&
|
||||
pdev->subsystem_device == 0xC000)
|
||||
return -ENODEV;
|
||||
goto out_disable_device;
|
||||
/* Now check the magic signature byte */
|
||||
pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic);
|
||||
if (magic != HBA_SIGNATURE_471 && magic != HBA_SIGNATURE)
|
||||
return -ENODEV;
|
||||
goto out_disable_device;
|
||||
/* Ok it is probably a megaraid */
|
||||
}
|
||||
|
||||
|
||||
@@ -996,6 +996,7 @@ static void qlt_free_session_done(struct work_struct *work)
|
||||
|
||||
if (logout_started) {
|
||||
bool traced = false;
|
||||
u16 cnt = 0;
|
||||
|
||||
while (!ACCESS_ONCE(sess->logout_completed)) {
|
||||
if (!traced) {
|
||||
@@ -1005,6 +1006,9 @@ static void qlt_free_session_done(struct work_struct *work)
|
||||
traced = true;
|
||||
}
|
||||
msleep(100);
|
||||
cnt++;
|
||||
if (cnt > 200)
|
||||
break;
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0xf087,
|
||||
|
||||
@@ -935,6 +935,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
|
||||
ses->sdb = scmd->sdb;
|
||||
ses->next_rq = scmd->request->next_rq;
|
||||
ses->result = scmd->result;
|
||||
ses->resid_len = scmd->req.resid_len;
|
||||
ses->underflow = scmd->underflow;
|
||||
ses->prot_op = scmd->prot_op;
|
||||
ses->eh_eflags = scmd->eh_eflags;
|
||||
@@ -946,6 +947,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
|
||||
memset(&scmd->sdb, 0, sizeof(scmd->sdb));
|
||||
scmd->request->next_rq = NULL;
|
||||
scmd->result = 0;
|
||||
scmd->req.resid_len = 0;
|
||||
|
||||
if (sense_bytes) {
|
||||
scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
|
||||
@@ -999,6 +1001,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
|
||||
scmd->sdb = ses->sdb;
|
||||
scmd->request->next_rq = ses->next_rq;
|
||||
scmd->result = ses->result;
|
||||
scmd->req.resid_len = ses->resid_len;
|
||||
scmd->underflow = ses->underflow;
|
||||
scmd->prot_op = ses->prot_op;
|
||||
scmd->eh_eflags = ses->eh_eflags;
|
||||
|
||||
@@ -722,6 +722,14 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
struct scsi_device *sdev = to_scsi_device(dev);
|
||||
|
||||
/*
|
||||
* We need to try to get module, avoiding the module been removed
|
||||
* during delete.
|
||||
*/
|
||||
if (scsi_device_get(sdev))
|
||||
return -ENODEV;
|
||||
|
||||
kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
|
||||
WARN_ON_ONCE(!kn);
|
||||
@@ -736,9 +744,10 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr,
|
||||
* state into SDEV_DEL.
|
||||
*/
|
||||
device_remove_file(dev, attr);
|
||||
scsi_remove_device(to_scsi_device(dev));
|
||||
scsi_remove_device(sdev);
|
||||
if (kn)
|
||||
sysfs_unbreak_active_protection(kn);
|
||||
scsi_device_put(sdev);
|
||||
return count;
|
||||
};
|
||||
static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
|
||||
|
||||
@@ -1658,7 +1658,8 @@ static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
|
||||
/* we need to evaluate the error return */
|
||||
if (scsi_sense_valid(sshdr) &&
|
||||
(sshdr->asc == 0x3a || /* medium not present */
|
||||
sshdr->asc == 0x20)) /* invalid command */
|
||||
sshdr->asc == 0x20 || /* invalid command */
|
||||
(sshdr->asc == 0x74 && sshdr->ascq == 0x71))) /* drive is password locked */
|
||||
/* this is no error here */
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -7755,6 +7755,9 @@ int ufshcd_shutdown(struct ufs_hba *hba)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!hba->is_powered)
|
||||
goto out;
|
||||
|
||||
if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba))
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -490,10 +490,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
|
||||
/* Set the encryption - we only support wep */
|
||||
if (is_wep) {
|
||||
if (sme->key) {
|
||||
if (sme->key_idx >= NUM_WEPKEYS) {
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
if (sme->key_idx >= NUM_WEPKEYS)
|
||||
return -EINVAL;
|
||||
|
||||
result = prism2_domibset_uint32(wlandev,
|
||||
DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID,
|
||||
|
||||
@@ -458,6 +458,7 @@ static void usblp_cleanup(struct usblp *usblp)
|
||||
kfree(usblp->readbuf);
|
||||
kfree(usblp->device_id_string);
|
||||
kfree(usblp->statusbuf);
|
||||
usb_put_intf(usblp->intf);
|
||||
kfree(usblp);
|
||||
}
|
||||
|
||||
@@ -1120,7 +1121,7 @@ static int usblp_probe(struct usb_interface *intf,
|
||||
init_waitqueue_head(&usblp->wwait);
|
||||
init_usb_anchor(&usblp->urbs);
|
||||
usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
|
||||
usblp->intf = intf;
|
||||
usblp->intf = usb_get_intf(intf);
|
||||
|
||||
/* Malloc device ID string buffer to the largest expected length,
|
||||
* since we can re-query it on an ioctl and a dynamic string
|
||||
@@ -1209,6 +1210,7 @@ abort:
|
||||
kfree(usblp->readbuf);
|
||||
kfree(usblp->statusbuf);
|
||||
kfree(usblp->device_id_string);
|
||||
usb_put_intf(usblp->intf);
|
||||
kfree(usblp);
|
||||
abort_ret:
|
||||
return retval;
|
||||
|
||||
@@ -1178,11 +1178,11 @@ static void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
|
||||
tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
|
||||
|
||||
bl = bytes - n;
|
||||
if (bl > 3)
|
||||
bl = 3;
|
||||
if (bl > 4)
|
||||
bl = 4;
|
||||
|
||||
for (i = 0; i < bl; i++)
|
||||
data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF);
|
||||
data[n + i] = (u8) ((tmp >> (i * 8)) & 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -383,10 +383,7 @@ static int ld_usb_release(struct inode *inode, struct file *file)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&dev->mutex)) {
|
||||
retval = -ERESTARTSYS;
|
||||
goto exit;
|
||||
}
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
if (dev->open_count != 1) {
|
||||
retval = -ENODEV;
|
||||
@@ -470,7 +467,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
|
||||
|
||||
/* wait for data */
|
||||
spin_lock_irq(&dev->rbsl);
|
||||
if (dev->ring_head == dev->ring_tail) {
|
||||
while (dev->ring_head == dev->ring_tail) {
|
||||
dev->interrupt_in_done = 0;
|
||||
spin_unlock_irq(&dev->rbsl);
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
@@ -480,12 +477,17 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
|
||||
retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
|
||||
if (retval < 0)
|
||||
goto unlock_exit;
|
||||
} else {
|
||||
spin_unlock_irq(&dev->rbsl);
|
||||
|
||||
spin_lock_irq(&dev->rbsl);
|
||||
}
|
||||
spin_unlock_irq(&dev->rbsl);
|
||||
|
||||
/* actual_buffer contains actual_length + interrupt_in_buffer */
|
||||
actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_tail * (sizeof(size_t)+dev->interrupt_in_endpoint_size));
|
||||
if (*actual_buffer > dev->interrupt_in_endpoint_size) {
|
||||
retval = -EIO;
|
||||
goto unlock_exit;
|
||||
}
|
||||
bytes_to_read = min(count, *actual_buffer);
|
||||
if (bytes_to_read < *actual_buffer)
|
||||
dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n",
|
||||
@@ -696,7 +698,9 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
|
||||
|
||||
dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint);
|
||||
dev->ring_buffer = kmalloc(ring_buffer_size*(sizeof(size_t)+dev->interrupt_in_endpoint_size), GFP_KERNEL);
|
||||
dev->ring_buffer = kcalloc(ring_buffer_size,
|
||||
sizeof(size_t) + dev->interrupt_in_endpoint_size,
|
||||
GFP_KERNEL);
|
||||
if (!dev->ring_buffer)
|
||||
goto error;
|
||||
dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
|
||||
|
||||
@@ -423,10 +423,7 @@ static int tower_release (struct inode *inode, struct file *file)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&dev->lock)) {
|
||||
retval = -ERESTARTSYS;
|
||||
goto exit;
|
||||
}
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
if (dev->open_count != 1) {
|
||||
dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n",
|
||||
|
||||
@@ -780,7 +780,6 @@ static void ti_close(struct usb_serial_port *port)
|
||||
struct ti_port *tport;
|
||||
int port_number;
|
||||
int status;
|
||||
int do_unlock;
|
||||
unsigned long flags;
|
||||
|
||||
tdev = usb_get_serial_data(port->serial);
|
||||
@@ -804,16 +803,13 @@ static void ti_close(struct usb_serial_port *port)
|
||||
"%s - cannot send close port command, %d\n"
|
||||
, __func__, status);
|
||||
|
||||
/* if mutex_lock is interrupted, continue anyway */
|
||||
do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
|
||||
mutex_lock(&tdev->td_open_close_lock);
|
||||
--tport->tp_tdev->td_open_port_count;
|
||||
if (tport->tp_tdev->td_open_port_count <= 0) {
|
||||
if (tport->tp_tdev->td_open_port_count == 0) {
|
||||
/* last port is closed, shut down interrupt urb */
|
||||
usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
|
||||
tport->tp_tdev->td_open_port_count = 0;
|
||||
}
|
||||
if (do_unlock)
|
||||
mutex_unlock(&tdev->td_open_close_lock);
|
||||
mutex_unlock(&tdev->td_open_close_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10255,6 +10255,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
|
||||
btrfs_err(info,
|
||||
"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups",
|
||||
cache->key.objectid);
|
||||
btrfs_put_block_group(cache);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -181,6 +181,9 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
|
||||
/* we do not want to loop forever */
|
||||
last_mid = cur_mid;
|
||||
cur_mid++;
|
||||
/* avoid 0xFFFF MID */
|
||||
if (cur_mid == 0xffff)
|
||||
cur_mid++;
|
||||
|
||||
/*
|
||||
* This nested loop looks more expensive than it is.
|
||||
|
||||
@@ -231,7 +231,8 @@ void ocfs2_recovery_exit(struct ocfs2_super *osb)
|
||||
/* At this point, we know that no more recovery threads can be
|
||||
* launched, so wait for any recovery completion work to
|
||||
* complete. */
|
||||
flush_workqueue(osb->ocfs2_wq);
|
||||
if (osb->ocfs2_wq)
|
||||
flush_workqueue(osb->ocfs2_wq);
|
||||
|
||||
/*
|
||||
* Now that recovery is shut down, and the osb is about to be
|
||||
|
||||
@@ -391,7 +391,8 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
|
||||
struct ocfs2_dinode *alloc = NULL;
|
||||
|
||||
cancel_delayed_work(&osb->la_enable_wq);
|
||||
flush_workqueue(osb->ocfs2_wq);
|
||||
if (osb->ocfs2_wq)
|
||||
flush_workqueue(osb->ocfs2_wq);
|
||||
|
||||
if (osb->local_alloc_state == OCFS2_LA_UNUSED)
|
||||
goto out;
|
||||
|
||||
@@ -42,10 +42,12 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
|
||||
return -EINVAL;
|
||||
|
||||
while (count > 0) {
|
||||
if (pfn_valid(pfn))
|
||||
ppage = pfn_to_page(pfn);
|
||||
else
|
||||
ppage = NULL;
|
||||
/*
|
||||
* TODO: ZONE_DEVICE support requires to identify
|
||||
* memmaps that were actually initialized.
|
||||
*/
|
||||
ppage = pfn_to_online_page(pfn);
|
||||
|
||||
if (!ppage || PageSlab(ppage))
|
||||
pcount = 0;
|
||||
else
|
||||
@@ -214,10 +216,11 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf,
|
||||
return -EINVAL;
|
||||
|
||||
while (count > 0) {
|
||||
if (pfn_valid(pfn))
|
||||
ppage = pfn_to_page(pfn);
|
||||
else
|
||||
ppage = NULL;
|
||||
/*
|
||||
* TODO: ZONE_DEVICE support requires to identify
|
||||
* memmaps that were actually initialized.
|
||||
*/
|
||||
ppage = pfn_to_online_page(pfn);
|
||||
|
||||
if (put_user(stable_page_flags(ppage), out)) {
|
||||
ret = -EFAULT;
|
||||
@@ -259,10 +262,11 @@ static ssize_t kpagecgroup_read(struct file *file, char __user *buf,
|
||||
return -EINVAL;
|
||||
|
||||
while (count > 0) {
|
||||
if (pfn_valid(pfn))
|
||||
ppage = pfn_to_page(pfn);
|
||||
else
|
||||
ppage = NULL;
|
||||
/*
|
||||
* TODO: ZONE_DEVICE support requires to identify
|
||||
* memmaps that were actually initialized.
|
||||
*/
|
||||
ppage = pfn_to_online_page(pfn);
|
||||
|
||||
if (ppage)
|
||||
ino = page_cgroup_ino(ppage);
|
||||
|
||||
@@ -32,6 +32,7 @@ extern int scsi_ioctl_reset(struct scsi_device *, int __user *);
|
||||
struct scsi_eh_save {
|
||||
/* saved state */
|
||||
int result;
|
||||
unsigned int resid_len;
|
||||
int eh_eflags;
|
||||
enum dma_data_direction data_direction;
|
||||
unsigned underflow;
|
||||
|
||||
@@ -1081,11 +1081,10 @@ static bool pfn_range_valid_gigantic(struct zone *z,
|
||||
struct page *page;
|
||||
|
||||
for (i = start_pfn; i < end_pfn; i++) {
|
||||
if (!pfn_valid(i))
|
||||
page = pfn_to_online_page(i);
|
||||
if (!page)
|
||||
return false;
|
||||
|
||||
page = pfn_to_page(i);
|
||||
|
||||
if (page_zone(page) != z)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -273,7 +273,8 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,
|
||||
* not matter as the mixed block count will still be correct
|
||||
*/
|
||||
for (; pfn < end_pfn; ) {
|
||||
if (!pfn_valid(pfn)) {
|
||||
page = pfn_to_online_page(pfn);
|
||||
if (!page) {
|
||||
pfn = ALIGN(pfn + 1, MAX_ORDER_NR_PAGES);
|
||||
continue;
|
||||
}
|
||||
@@ -281,13 +282,13 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,
|
||||
block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
|
||||
block_end_pfn = min(block_end_pfn, end_pfn);
|
||||
|
||||
page = pfn_to_page(pfn);
|
||||
pageblock_mt = get_pageblock_migratetype(page);
|
||||
|
||||
for (; pfn < block_end_pfn; pfn++) {
|
||||
if (!pfn_valid_within(pfn))
|
||||
continue;
|
||||
|
||||
/* The pageblock is online, no need to recheck. */
|
||||
page = pfn_to_page(pfn);
|
||||
|
||||
if (page_zone(page) != zone)
|
||||
|
||||
18
mm/shmem.c
18
mm/shmem.c
@@ -2677,11 +2677,12 @@ static void shmem_tag_pins(struct address_space *mapping)
|
||||
void **slot;
|
||||
pgoff_t start;
|
||||
struct page *page;
|
||||
unsigned int tagged = 0;
|
||||
|
||||
lru_add_drain();
|
||||
start = 0;
|
||||
rcu_read_lock();
|
||||
|
||||
spin_lock_irq(&mapping->tree_lock);
|
||||
radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) {
|
||||
page = radix_tree_deref_slot(slot);
|
||||
if (!page || radix_tree_exception(page)) {
|
||||
@@ -2690,18 +2691,19 @@ static void shmem_tag_pins(struct address_space *mapping)
|
||||
continue;
|
||||
}
|
||||
} else if (page_count(page) - page_mapcount(page) > 1) {
|
||||
spin_lock_irq(&mapping->tree_lock);
|
||||
radix_tree_tag_set(&mapping->page_tree, iter.index,
|
||||
SHMEM_TAG_PINNED);
|
||||
spin_unlock_irq(&mapping->tree_lock);
|
||||
}
|
||||
|
||||
if (need_resched()) {
|
||||
slot = radix_tree_iter_resume(slot, &iter);
|
||||
cond_resched_rcu();
|
||||
}
|
||||
if (++tagged % 1024)
|
||||
continue;
|
||||
|
||||
slot = radix_tree_iter_resume(slot, &iter);
|
||||
spin_unlock_irq(&mapping->tree_lock);
|
||||
cond_resched();
|
||||
spin_lock_irq(&mapping->tree_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
spin_unlock_irq(&mapping->tree_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
13
mm/slub.c
13
mm/slub.c
@@ -4790,7 +4790,17 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
|
||||
}
|
||||
}
|
||||
|
||||
get_online_mems();
|
||||
/*
|
||||
* It is impossible to take "mem_hotplug_lock" here with "kernfs_mutex"
|
||||
* already held which will conflict with an existing lock order:
|
||||
*
|
||||
* mem_hotplug_lock->slab_mutex->kernfs_mutex
|
||||
*
|
||||
* We don't really need mem_hotplug_lock (to hold off
|
||||
* slab_mem_going_offline_callback) here because slab's memory hot
|
||||
* unplug code doesn't destroy the kmem_cache->node[] data.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SLUB_DEBUG
|
||||
if (flags & SO_ALL) {
|
||||
struct kmem_cache_node *n;
|
||||
@@ -4831,7 +4841,6 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
|
||||
x += sprintf(buf + x, " N%d=%lu",
|
||||
node, nodes[node]);
|
||||
#endif
|
||||
put_online_mems();
|
||||
kfree(nodes);
|
||||
return x + sprintf(buf + x, "\n");
|
||||
}
|
||||
|
||||
@@ -2351,14 +2351,17 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
|
||||
int orig_oif = fl4->flowi4_oif;
|
||||
unsigned int flags = 0;
|
||||
struct rtable *rth;
|
||||
int err = -ENETUNREACH;
|
||||
int err;
|
||||
|
||||
if (fl4->saddr) {
|
||||
rth = ERR_PTR(-EINVAL);
|
||||
if (ipv4_is_multicast(fl4->saddr) ||
|
||||
ipv4_is_lbcast(fl4->saddr) ||
|
||||
ipv4_is_zeronet(fl4->saddr))
|
||||
ipv4_is_zeronet(fl4->saddr)) {
|
||||
rth = ERR_PTR(-EINVAL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rth = ERR_PTR(-ENETUNREACH);
|
||||
|
||||
/* I removed check for oif == dev_out->oif here.
|
||||
It was wrong for two reasons:
|
||||
|
||||
@@ -490,9 +490,14 @@ static ssize_t ieee80211_if_fmt_aqm(
|
||||
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct txq_info *txqi = to_txq_info(sdata->vif.txq);
|
||||
struct txq_info *txqi;
|
||||
int len;
|
||||
|
||||
if (!sdata->vif.txq)
|
||||
return 0;
|
||||
|
||||
txqi = to_txq_info(sdata->vif.txq);
|
||||
|
||||
spin_lock_bh(&local->fq.lock);
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -659,7 +664,9 @@ static void add_common_files(struct ieee80211_sub_if_data *sdata)
|
||||
DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
|
||||
DEBUGFS_ADD(hw_queues);
|
||||
|
||||
if (sdata->local->ops->wake_tx_queue)
|
||||
if (sdata->local->ops->wake_tx_queue &&
|
||||
sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
|
||||
sdata->vif.type != NL80211_IFTYPE_NAN)
|
||||
DEBUGFS_ADD(aqm);
|
||||
}
|
||||
|
||||
|
||||
@@ -2430,7 +2430,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
|
||||
|
||||
rcu_read_lock();
|
||||
ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
|
||||
if (WARN_ON_ONCE(ssid == NULL))
|
||||
if (WARN_ONCE(!ssid || ssid[1] > IEEE80211_MAX_SSID_LEN,
|
||||
"invalid SSID element (len=%d)", ssid ? ssid[1] : -1))
|
||||
ssid_len = 0;
|
||||
else
|
||||
ssid_len = ssid[1];
|
||||
@@ -4756,7 +4757,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
rcu_read_lock();
|
||||
ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
|
||||
if (!ssidie) {
|
||||
if (!ssidie || ssidie[1] > sizeof(assoc_data->ssid)) {
|
||||
rcu_read_unlock();
|
||||
kfree(assoc_data);
|
||||
return -EINVAL;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user