mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
Merge branch 'linux-linaro-lsk-v4.4' of git://git.linaro.org/kernel/linux-linaro-stable.git
* linux-linaro-lsk-v4.4: (519 commits)
Linux 4.4.154
cdrom: Fix info leak/OOB read in cdrom_ioctl_drive_status
iscsi target: fix session creation failure handling
scsi: core: Avoid that SCSI device removal through sysfs triggers a deadlock
scsi: sysfs: Introduce sysfs_{un,}break_active_protection()
MIPS: lib: Provide MIPS64r6 __multi3() for GCC < 7
MIPS: Correct the 64-bit DSP accumulator register size
kprobes: Make list and blacklist root user read only
s390/pci: fix out of bounds access during irq setup
s390/qdio: reset old sbal_state flags
s390: fix br_r1_trampoline for machines without exrl
x86/spectre: Add missing family 6 check to microcode check
x86/irqflags: Mark native_restore_fl extern inline
pinctrl: freescale: off by one in imx1_pinconf_group_dbg_show()
ASoC: sirf: Fix potential NULL pointer dereference
ASoC: dpcm: don't merge format from invalid codec dai
udl-kms: fix crash due to uninitialized memory
udl-kms: handle allocation failure
udl-kms: change down_interruptible to down
fuse: Add missed unlock_page() to fuse_readpages_fill()
...
Conflicts:
Makefile
arch/arm64/mm/init.c
fs/squashfs/block.c
include/uapi/linux/prctl.h
kernel/sys.c
Change-Id: Ie03b5adfbbb4ab2bf16bc55d99f0d8a9c540a53b
This commit is contained in:
commit
75654db877
|
|
@ -276,6 +276,7 @@ What: /sys/devices/system/cpu/vulnerabilities
|
|||
/sys/devices/system/cpu/vulnerabilities/meltdown
|
||||
/sys/devices/system/cpu/vulnerabilities/spectre_v1
|
||||
/sys/devices/system/cpu/vulnerabilities/spectre_v2
|
||||
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
|
||||
Date: January 2018
|
||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description: Information about CPU vulnerabilities
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ o GNU C 3.2 # gcc --version
|
|||
o GNU make 3.80 # make --version
|
||||
o binutils 2.12 # ld -v
|
||||
o util-linux 2.10o # fdformat --version
|
||||
o module-init-tools 0.9.10 # depmod -V
|
||||
o kmod 13 # depmod -V
|
||||
o e2fsprogs 1.41.4 # e2fsck -V
|
||||
o jfsutils 1.1.3 # fsck.jfs -V
|
||||
o reiserfsprogs 3.6.3 # reiserfsck -V
|
||||
|
|
@ -132,12 +132,6 @@ is not build with CONFIG_KALLSYMS and you have no way to rebuild and
|
|||
reproduce the Oops with that option, then you can still decode that Oops
|
||||
with ksymoops.
|
||||
|
||||
Module-Init-Tools
|
||||
-----------------
|
||||
|
||||
A new module loader is now in the kernel that requires module-init-tools
|
||||
to use. It is backward compatible with the 2.4.x series kernels.
|
||||
|
||||
Mkinitrd
|
||||
--------
|
||||
|
||||
|
|
@ -319,14 +313,15 @@ Util-linux
|
|||
----------
|
||||
o <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>
|
||||
|
||||
Kmod
|
||||
----
|
||||
o <https://www.kernel.org/pub/linux/utils/kernel/kmod/>
|
||||
o <https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git>
|
||||
|
||||
Ksymoops
|
||||
--------
|
||||
o <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
|
||||
|
||||
Module-Init-Tools
|
||||
-----------------
|
||||
o <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
|
||||
|
||||
Mkinitrd
|
||||
--------
|
||||
o <https://code.launchpad.net/initrd-tools/main>
|
||||
|
|
|
|||
|
|
@ -2520,6 +2520,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
allow data leaks with this option, which is equivalent
|
||||
to spectre_v2=off.
|
||||
|
||||
nospec_store_bypass_disable
|
||||
[HW] Disable all mitigations for the Speculative Store Bypass vulnerability
|
||||
|
||||
noxsave [BUGS=X86] Disables x86 extended register state save
|
||||
and restore using xsave. The kernel will fallback to
|
||||
enabling legacy floating-point and sse state.
|
||||
|
|
@ -3693,6 +3696,48 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
Not specifying this option is equivalent to
|
||||
spectre_v2=auto.
|
||||
|
||||
spec_store_bypass_disable=
|
||||
[HW] Control Speculative Store Bypass (SSB) Disable mitigation
|
||||
(Speculative Store Bypass vulnerability)
|
||||
|
||||
Certain CPUs are vulnerable to an exploit against a
|
||||
a common industry wide performance optimization known
|
||||
as "Speculative Store Bypass" in which recent stores
|
||||
to the same memory location may not be observed by
|
||||
later loads during speculative execution. The idea
|
||||
is that such stores are unlikely and that they can
|
||||
be detected prior to instruction retirement at the
|
||||
end of a particular speculation execution window.
|
||||
|
||||
In vulnerable processors, the speculatively forwarded
|
||||
store can be used in a cache side channel attack, for
|
||||
example to read memory to which the attacker does not
|
||||
directly have access (e.g. inside sandboxed code).
|
||||
|
||||
This parameter controls whether the Speculative Store
|
||||
Bypass optimization is used.
|
||||
|
||||
on - Unconditionally disable Speculative Store Bypass
|
||||
off - Unconditionally enable Speculative Store Bypass
|
||||
auto - Kernel detects whether the CPU model contains an
|
||||
implementation of Speculative Store Bypass and
|
||||
picks the most appropriate mitigation. If the
|
||||
CPU is not vulnerable, "off" is selected. If the
|
||||
CPU is vulnerable the default mitigation is
|
||||
architecture and Kconfig dependent. See below.
|
||||
prctl - Control Speculative Store Bypass per thread
|
||||
via prctl. Speculative Store Bypass is enabled
|
||||
for a process by default. The state of the control
|
||||
is inherited on fork.
|
||||
seccomp - Same as "prctl" above, but all seccomp threads
|
||||
will disable SSB unless they explicitly opt out.
|
||||
|
||||
Not specifying this option is equivalent to
|
||||
spec_store_bypass_disable=auto.
|
||||
|
||||
Default mitigations:
|
||||
X86: If CONFIG_SECCOMP=y "seccomp", otherwise "prctl"
|
||||
|
||||
spia_io_base= [HW,MTD]
|
||||
spia_fio_base=
|
||||
spia_pedr=
|
||||
|
|
|
|||
94
Documentation/spec_ctrl.txt
Normal file
94
Documentation/spec_ctrl.txt
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
===================
|
||||
Speculation Control
|
||||
===================
|
||||
|
||||
Quite some CPUs have speculation-related misfeatures which are in
|
||||
fact vulnerabilities causing data leaks in various forms even across
|
||||
privilege domains.
|
||||
|
||||
The kernel provides mitigation for such vulnerabilities in various
|
||||
forms. Some of these mitigations are compile-time configurable and some
|
||||
can be supplied on the kernel command line.
|
||||
|
||||
There is also a class of mitigations which are very expensive, but they can
|
||||
be restricted to a certain set of processes or tasks in controlled
|
||||
environments. The mechanism to control these mitigations is via
|
||||
:manpage:`prctl(2)`.
|
||||
|
||||
There are two prctl options which are related to this:
|
||||
|
||||
* PR_GET_SPECULATION_CTRL
|
||||
|
||||
* PR_SET_SPECULATION_CTRL
|
||||
|
||||
PR_GET_SPECULATION_CTRL
|
||||
-----------------------
|
||||
|
||||
PR_GET_SPECULATION_CTRL returns the state of the speculation misfeature
|
||||
which is selected with arg2 of prctl(2). The return value uses bits 0-3 with
|
||||
the following meaning:
|
||||
|
||||
==== ===================== ===================================================
|
||||
Bit Define Description
|
||||
==== ===================== ===================================================
|
||||
0 PR_SPEC_PRCTL Mitigation can be controlled per task by
|
||||
PR_SET_SPECULATION_CTRL.
|
||||
1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is
|
||||
disabled.
|
||||
2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is
|
||||
enabled.
|
||||
3 PR_SPEC_FORCE_DISABLE Same as PR_SPEC_DISABLE, but cannot be undone. A
|
||||
subsequent prctl(..., PR_SPEC_ENABLE) will fail.
|
||||
==== ===================== ===================================================
|
||||
|
||||
If all bits are 0 the CPU is not affected by the speculation misfeature.
|
||||
|
||||
If PR_SPEC_PRCTL is set, then the per-task control of the mitigation is
|
||||
available. If not set, prctl(PR_SET_SPECULATION_CTRL) for the speculation
|
||||
misfeature will fail.
|
||||
|
||||
PR_SET_SPECULATION_CTRL
|
||||
-----------------------
|
||||
|
||||
PR_SET_SPECULATION_CTRL allows to control the speculation misfeature, which
|
||||
is selected by arg2 of :manpage:`prctl(2)` per task. arg3 is used to hand
|
||||
in the control value, i.e. either PR_SPEC_ENABLE or PR_SPEC_DISABLE or
|
||||
PR_SPEC_FORCE_DISABLE.
|
||||
|
||||
Common error codes
|
||||
------------------
|
||||
======= =================================================================
|
||||
Value Meaning
|
||||
======= =================================================================
|
||||
EINVAL The prctl is not implemented by the architecture or unused
|
||||
prctl(2) arguments are not 0.
|
||||
|
||||
ENODEV arg2 is selecting a not supported speculation misfeature.
|
||||
======= =================================================================
|
||||
|
||||
PR_SET_SPECULATION_CTRL error codes
|
||||
-----------------------------------
|
||||
======= =================================================================
|
||||
Value Meaning
|
||||
======= =================================================================
|
||||
0 Success
|
||||
|
||||
ERANGE arg3 is incorrect, i.e. it's neither PR_SPEC_ENABLE nor
|
||||
PR_SPEC_DISABLE nor PR_SPEC_FORCE_DISABLE.
|
||||
|
||||
ENXIO Control of the selected speculation misfeature is not possible.
|
||||
See PR_GET_SPECULATION_CTRL.
|
||||
|
||||
EPERM Speculation was disabled with PR_SPEC_FORCE_DISABLE and caller
|
||||
tried to enable it again.
|
||||
======= =================================================================
|
||||
|
||||
Speculation misfeature controls
|
||||
-------------------------------
|
||||
- PR_SPEC_STORE_BYPASS: Speculative Store Bypass
|
||||
|
||||
Invocations:
|
||||
* prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0);
|
||||
* prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
|
||||
* prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
|
||||
* prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
|
||||
7
Makefile
7
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 143
|
||||
SUBLEVEL = 154
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
@ -442,7 +442,9 @@ export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
|
|||
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
|
||||
|
||||
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
|
||||
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV CFLAGS_KCOV CFLAGS_KASAN
|
||||
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV
|
||||
export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE
|
||||
export CFLAGS_KCOV
|
||||
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
|
||||
|
|
@ -648,6 +650,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,)
|
|||
KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context)
|
||||
KBUILD_CFLAGS += $(call cc-disable-warning, attribute-alias)
|
||||
|
||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
KBUILD_CFLAGS += $(call cc-option,-Oz,-Os)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ endif
|
|||
|
||||
KBUILD_DEFCONFIG := nsim_700_defconfig
|
||||
|
||||
cflags-y += -fno-common -pipe -fno-builtin -D__linux__
|
||||
cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__
|
||||
cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7
|
||||
cflags-$(CONFIG_ISA_ARCV2) += -mcpu=archs
|
||||
|
||||
|
|
@ -137,16 +137,3 @@ dtbs: scripts
|
|||
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
# Hacks to enable final link due to absence of link-time branch relexation
|
||||
# and gcc choosing optimal(shorter) branches at -O3
|
||||
#
|
||||
# vineetg Feb 2010: -mlong-calls switched off for overall kernel build
|
||||
# However lib/decompress_inflate.o (.init.text) calls
|
||||
# zlib_inflate_workspacesize (.text) causing relocation errors.
|
||||
# Thus forcing all exten calls in this file to be long calls
|
||||
export CFLAGS_decompress_inflate.o = -mmedium-calls
|
||||
export CFLAGS_initramfs.o = -mmedium-calls
|
||||
ifdef CONFIG_SMP
|
||||
export CFLAGS_core.o = -mmedium-calls
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -17,8 +17,11 @@
|
|||
#ifndef __ASM_ARC_UDELAY_H
|
||||
#define __ASM_ARC_UDELAY_H
|
||||
|
||||
#include <asm-generic/types.h>
|
||||
#include <asm/param.h> /* HZ */
|
||||
|
||||
extern unsigned long loops_per_jiffy;
|
||||
|
||||
static inline void __delay(unsigned long loops)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
|
|
|
|||
|
|
@ -34,9 +34,7 @@ struct machine_desc {
|
|||
const char *name;
|
||||
const char **dt_compat;
|
||||
void (*init_early)(void);
|
||||
#ifdef CONFIG_SMP
|
||||
void (*init_per_cpu)(unsigned int);
|
||||
#endif
|
||||
void (*init_machine)(void);
|
||||
void (*init_late)(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ typedef pte_t * pgtable_t;
|
|||
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
||||
|
||||
/* Default Permissions for stack/heaps pages (Non Executable) */
|
||||
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE)
|
||||
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
||||
|
||||
#define WANT_PAGE_VIRTUAL 1
|
||||
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
|
|||
|
||||
/* Decode a PTE containing swap "identifier "into constituents */
|
||||
#define __swp_type(pte_lookalike) (((pte_lookalike).val) & 0x1f)
|
||||
#define __swp_offset(pte_lookalike) ((pte_lookalike).val << 13)
|
||||
#define __swp_offset(pte_lookalike) ((pte_lookalike).val >> 13)
|
||||
|
||||
/* NOPs, to keep generic kernel happy */
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ void __init init_IRQ(void)
|
|||
/* a SMP H/w block could do IPI IRQ request here */
|
||||
if (plat_smp_ops.init_per_cpu)
|
||||
plat_smp_ops.init_per_cpu(smp_processor_id());
|
||||
#endif
|
||||
|
||||
if (machine_desc->init_per_cpu)
|
||||
machine_desc->init_per_cpu(smp_processor_id());
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -821,7 +821,7 @@ void flush_cache_mm(struct mm_struct *mm)
|
|||
void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr,
|
||||
unsigned long pfn)
|
||||
{
|
||||
unsigned int paddr = pfn << PAGE_SHIFT;
|
||||
phys_addr_t paddr = pfn << PAGE_SHIFT;
|
||||
|
||||
u_vaddr &= PAGE_MASK;
|
||||
|
||||
|
|
@ -841,8 +841,9 @@ void flush_anon_page(struct vm_area_struct *vma, struct page *page,
|
|||
unsigned long u_vaddr)
|
||||
{
|
||||
/* TBD: do we really need to clear the kernel mapping */
|
||||
__flush_dcache_page(page_address(page), u_vaddr);
|
||||
__flush_dcache_page(page_address(page), page_address(page));
|
||||
__flush_dcache_page((phys_addr_t)page_address(page), u_vaddr);
|
||||
__flush_dcache_page((phys_addr_t)page_address(page),
|
||||
(phys_addr_t)page_address(page));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ omap3_pmx_core2: pinmux@480025d8 {
|
|||
};
|
||||
};
|
||||
|
||||
/* Table Table 5-79 of the TRM shows 480ab000 is reserved */
|
||||
&usb_otg_hs {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&iva {
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -508,6 +508,8 @@ edt-ft5306@38 {
|
|||
|
||||
touchscreen-size-x = <480>;
|
||||
touchscreen-size-y = <272>;
|
||||
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
tlv320aic3106: tlv320aic3106@1b {
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ i2c0: i2c@18008000 {
|
|||
reg = <0x18008000 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <100000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
@ -138,7 +138,7 @@ i2c1: i2c@1800b000 {
|
|||
reg = <0x1800b000 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <100000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -267,11 +267,7 @@ gpio: gpio@1e26000 {
|
|||
compatible = "ti,dm6441-gpio";
|
||||
gpio-controller;
|
||||
reg = <0x226000 0x1000>;
|
||||
interrupts = <42 IRQ_TYPE_EDGE_BOTH
|
||||
43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH
|
||||
45 IRQ_TYPE_EDGE_BOTH 46 IRQ_TYPE_EDGE_BOTH
|
||||
47 IRQ_TYPE_EDGE_BOTH 48 IRQ_TYPE_EDGE_BOTH
|
||||
49 IRQ_TYPE_EDGE_BOTH 50 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupts = <42 43 44 45 46 47 48 49 50>;
|
||||
ti,ngpio = <144>;
|
||||
ti,davinci-gpio-unbanked = <0>;
|
||||
status = "disabled";
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ pcie: pcie@0x08000000 {
|
|||
/* non-prefetchable memory */
|
||||
0x82000000 0 0x08000000 0x08000000 0 0x00f00000>;
|
||||
num-lanes = <1>;
|
||||
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clks IMX6SX_CLK_PCIE_REF_125M>,
|
||||
<&clks IMX6SX_CLK_PCIE_AXI>,
|
||||
<&clks IMX6SX_CLK_LVDS1_OUT>,
|
||||
|
|
|
|||
|
|
@ -145,9 +145,11 @@ CONFIG_USB_STORAGE=y
|
|||
CONFIG_USB_CHIPIDEA=y
|
||||
CONFIG_USB_CHIPIDEA_UDC=y
|
||||
CONFIG_USB_CHIPIDEA_HOST=y
|
||||
CONFIG_USB_CHIPIDEA_ULPI=y
|
||||
CONFIG_NOP_USB_XCEIV=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_ETH=m
|
||||
CONFIG_USB_ULPI_BUS=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
|
|
|
|||
|
|
@ -261,6 +261,7 @@ CONFIG_USB_STORAGE=y
|
|||
CONFIG_USB_CHIPIDEA=y
|
||||
CONFIG_USB_CHIPIDEA_UDC=y
|
||||
CONFIG_USB_CHIPIDEA_HOST=y
|
||||
CONFIG_USB_CHIPIDEA_ULPI=y
|
||||
CONFIG_USB_SERIAL=m
|
||||
CONFIG_USB_SERIAL_GENERIC=y
|
||||
CONFIG_USB_SERIAL_FTDI_SIO=m
|
||||
|
|
@ -287,6 +288,7 @@ CONFIG_USB_G_NCM=m
|
|||
CONFIG_USB_GADGETFS=m
|
||||
CONFIG_USB_MASS_STORAGE=m
|
||||
CONFIG_USB_G_SERIAL=m
|
||||
CONFIG_USB_ULPI_BUS=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ extern int __put_user_8(void *, unsigned long long);
|
|||
({ \
|
||||
unsigned long __limit = current_thread_info()->addr_limit - 1; \
|
||||
const typeof(*(p)) __user *__tmp_p = (p); \
|
||||
register const typeof(*(p)) __r2 asm("r2") = (x); \
|
||||
register typeof(*(p)) __r2 asm("r2") = (x); \
|
||||
register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
|
||||
register unsigned long __l asm("r1") = __limit; \
|
||||
register int __e asm("r0"); \
|
||||
|
|
|
|||
|
|
@ -899,19 +899,35 @@ static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
|
|||
pmd = stage2_get_pmd(kvm, cache, addr);
|
||||
VM_BUG_ON(!pmd);
|
||||
|
||||
/*
|
||||
* Mapping in huge pages should only happen through a fault. If a
|
||||
* page is merged into a transparent huge page, the individual
|
||||
* subpages of that huge page should be unmapped through MMU
|
||||
* notifiers before we get here.
|
||||
*
|
||||
* Merging of CompoundPages is not supported; they should become
|
||||
* splitting first, unmapped, merged, and mapped back in on-demand.
|
||||
*/
|
||||
VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd));
|
||||
|
||||
old_pmd = *pmd;
|
||||
if (pmd_present(old_pmd)) {
|
||||
/*
|
||||
* Multiple vcpus faulting on the same PMD entry, can
|
||||
* lead to them sequentially updating the PMD with the
|
||||
* same value. Following the break-before-make
|
||||
* (pmd_clear() followed by tlb_flush()) process can
|
||||
* hinder forward progress due to refaults generated
|
||||
* on missing translations.
|
||||
*
|
||||
* Skip updating the page table if the entry is
|
||||
* unchanged.
|
||||
*/
|
||||
if (pmd_val(old_pmd) == pmd_val(*new_pmd))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Mapping in huge pages should only happen through a
|
||||
* fault. If a page is merged into a transparent huge
|
||||
* page, the individual subpages of that huge page
|
||||
* should be unmapped through MMU notifiers before we
|
||||
* get here.
|
||||
*
|
||||
* Merging of CompoundPages is not supported; they
|
||||
* should become splitting first, unmapped, merged,
|
||||
* and mapped back in on-demand.
|
||||
*/
|
||||
VM_BUG_ON(pmd_pfn(old_pmd) != pmd_pfn(*new_pmd));
|
||||
|
||||
pmd_clear(pmd);
|
||||
kvm_tlb_flush_vmid_ipa(kvm, addr);
|
||||
} else {
|
||||
|
|
@ -968,6 +984,10 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
|
|||
/* Create 2nd stage page table mapping - Level 3 */
|
||||
old_pte = *pte;
|
||||
if (pte_present(old_pte)) {
|
||||
/* Skip page table update if there is no change */
|
||||
if (pte_val(old_pte) == pte_val(*new_pte))
|
||||
return 0;
|
||||
|
||||
kvm_set_pte(pte, __pte(0));
|
||||
kvm_tlb_flush_vmid_ipa(kvm, addr);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ static int pxa_irq_suspend(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pxa_internal_irq_nr / 32; i++) {
|
||||
for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) {
|
||||
void __iomem *base = irq_base(i);
|
||||
|
||||
saved_icmr[i] = __raw_readl(base + ICMR);
|
||||
|
|
@ -204,7 +204,7 @@ static void pxa_irq_resume(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pxa_internal_irq_nr / 32; i++) {
|
||||
for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) {
|
||||
void __iomem *base = irq_base(i);
|
||||
|
||||
__raw_writel(saved_icmr[i], base + ICMR);
|
||||
|
|
|
|||
|
|
@ -716,19 +716,28 @@ int __mark_rodata_ro(void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kernel_set_to_readonly __read_mostly;
|
||||
|
||||
void mark_rodata_ro(void)
|
||||
{
|
||||
kernel_set_to_readonly = 1;
|
||||
stop_machine(__mark_rodata_ro, NULL, NULL);
|
||||
}
|
||||
|
||||
void set_kernel_text_rw(void)
|
||||
{
|
||||
if (!kernel_set_to_readonly)
|
||||
return;
|
||||
|
||||
set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false,
|
||||
current->active_mm);
|
||||
}
|
||||
|
||||
void set_kernel_text_ro(void)
|
||||
{
|
||||
if (!kernel_set_to_readonly)
|
||||
return;
|
||||
|
||||
set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
|
||||
current->active_mm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ static void smp_store_cpu_info(unsigned int cpuid)
|
|||
* This is the secondary CPU boot entry. We're using this CPUs
|
||||
* idle thread stack, but a set of temporary page tables.
|
||||
*/
|
||||
asmlinkage void secondary_start_kernel(void)
|
||||
asmlinkage notrace void secondary_start_kernel(void)
|
||||
{
|
||||
struct mm_struct *mm = &init_mm;
|
||||
unsigned int cpu;
|
||||
|
|
|
|||
|
|
@ -267,11 +267,13 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_PFN_VALID
|
||||
#define PFN_MASK ((1UL << (64 - PAGE_SHIFT)) - 1)
|
||||
|
||||
int pfn_valid(unsigned long pfn)
|
||||
{
|
||||
return (pfn & PFN_MASK) == pfn && memblock_is_map_memory(pfn << PAGE_SHIFT);
|
||||
phys_addr_t addr = pfn << PAGE_SHIFT;
|
||||
|
||||
if ((addr >> PAGE_SHIFT) != pfn)
|
||||
return 0;
|
||||
return memblock_is_map_memory(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(pfn_valid);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -882,12 +882,12 @@ int pmd_clear_huge(pmd_t *pmd)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
|
||||
int pud_free_pmd_page(pud_t *pud)
|
||||
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
return pud_none(*pud);
|
||||
}
|
||||
|
||||
int pmd_free_pte_page(pmd_t *pmd)
|
||||
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
|
||||
{
|
||||
return pmd_none(*pmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
|
|||
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
|
||||
unsigned long address)
|
||||
{
|
||||
pgtable_page_dtor(page);
|
||||
__free_page(page);
|
||||
}
|
||||
|
||||
|
|
@ -73,8 +74,9 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
|||
return page;
|
||||
}
|
||||
|
||||
extern inline void pte_free(struct mm_struct *mm, struct page *page)
|
||||
static inline void pte_free(struct mm_struct *mm, struct page *page)
|
||||
{
|
||||
pgtable_page_dtor(page);
|
||||
__free_page(page);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,17 +21,19 @@ $(obj)/linux.bin.gz: $(obj)/linux.bin FORCE
|
|||
quiet_cmd_cp = CP $< $@$2
|
||||
cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false)
|
||||
|
||||
quiet_cmd_strip = STRIP $@
|
||||
quiet_cmd_strip = STRIP $< $@$2
|
||||
cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \
|
||||
-K _fdt_start vmlinux -o $@
|
||||
-K _fdt_start $< -o $@$2
|
||||
|
||||
UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR)
|
||||
UIMAGE_IN = $@
|
||||
UIMAGE_OUT = $@.ub
|
||||
|
||||
$(obj)/simpleImage.%: vmlinux FORCE
|
||||
$(call if_changed,cp,.unstrip)
|
||||
$(call if_changed,objcopy)
|
||||
$(call if_changed,uimage)
|
||||
$(call if_changed,strip)
|
||||
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
|
||||
$(call if_changed,strip,.strip)
|
||||
@echo 'Kernel: $(UIMAGE_OUT) is ready' ' (#'`cat .version`')'
|
||||
|
||||
clean-files += simpleImage.*.unstrip linux.bin.ub dts/*.dtb
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init);
|
|||
|
||||
void ath79_ddr_wb_flush(u32 reg)
|
||||
{
|
||||
void __iomem *flush_reg = ath79_ddr_wb_flush_base + reg;
|
||||
void __iomem *flush_reg = ath79_ddr_wb_flush_base + (reg * 4);
|
||||
|
||||
/* Flush the DDR write buffer. */
|
||||
__raw_writel(0x1, flush_reg);
|
||||
|
|
|
|||
|
|
@ -249,12 +249,6 @@ static int __init bcm47xx_cpu_fixes(void)
|
|||
*/
|
||||
if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
|
||||
cpu_wait = NULL;
|
||||
|
||||
/*
|
||||
* BCM47XX Erratum "R10: PCIe Transactions Periodically Fail"
|
||||
* Enable ExternalSync for sync instruction to take effect
|
||||
*/
|
||||
set_c0_config7(MIPS_CONF7_ES);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -606,8 +606,6 @@
|
|||
#define MIPS_CONF7_WII (_ULCAST_(1) << 31)
|
||||
|
||||
#define MIPS_CONF7_RPS (_ULCAST_(1) << 2)
|
||||
/* ExternalSync */
|
||||
#define MIPS_CONF7_ES (_ULCAST_(1) << 8)
|
||||
|
||||
#define MIPS_CONF7_IAR (_ULCAST_(1) << 10)
|
||||
#define MIPS_CONF7_AR (_ULCAST_(1) << 16)
|
||||
|
|
@ -2015,7 +2013,6 @@ __BUILD_SET_C0(status)
|
|||
__BUILD_SET_C0(cause)
|
||||
__BUILD_SET_C0(config)
|
||||
__BUILD_SET_C0(config5)
|
||||
__BUILD_SET_C0(config7)
|
||||
__BUILD_SET_C0(intcontrol)
|
||||
__BUILD_SET_C0(intctl)
|
||||
__BUILD_SET_C0(srsmap)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
|
|||
phys_addr_t size = resource_size(rsrc);
|
||||
|
||||
*start = fixup_bigphys_addr(rsrc->start, size);
|
||||
*end = rsrc->start + size;
|
||||
*end = rsrc->start + size - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ struct mips_fpu_struct {
|
|||
|
||||
#define NUM_DSP_REGS 6
|
||||
|
||||
typedef __u32 dspreg_t;
|
||||
typedef unsigned long dspreg_t;
|
||||
|
||||
struct mips_dsp_state {
|
||||
dspreg_t dspr[NUM_DSP_REGS];
|
||||
|
|
|
|||
|
|
@ -878,7 +878,7 @@ long arch_ptrace(struct task_struct *child, long request,
|
|||
goto out;
|
||||
}
|
||||
dregs = __get_dsp_regs(child);
|
||||
tmp = (unsigned long) (dregs[addr - DSP_BASE]);
|
||||
tmp = dregs[addr - DSP_BASE];
|
||||
break;
|
||||
}
|
||||
case DSP_CONTROL:
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
|||
goto out;
|
||||
}
|
||||
dregs = __get_dsp_regs(child);
|
||||
tmp = (unsigned long) (dregs[addr - DSP_BASE]);
|
||||
tmp = dregs[addr - DSP_BASE];
|
||||
break;
|
||||
}
|
||||
case DSP_CONTROL:
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
/*
|
||||
* GCC 7 suboptimally generates __multi3 calls for mips64r6, so for that
|
||||
* specific case only we'll implement it here.
|
||||
* GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for
|
||||
* that specific case only we implement that intrinsic here.
|
||||
*
|
||||
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
|
||||
*/
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ == 7)
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8)
|
||||
|
||||
/* multiply 64-bit values, low 64-bits returned */
|
||||
static inline long long notrace dmulu(long long a, long long b)
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ config PREFETCH
|
|||
|
||||
config MLONGCALLS
|
||||
bool "Enable the -mlong-calls compiler option for big kernels"
|
||||
def_bool y if (!MODULES)
|
||||
default y
|
||||
depends on PA8X00
|
||||
help
|
||||
If you configure the kernel to include many drivers built-in instead
|
||||
|
|
|
|||
32
arch/parisc/include/asm/barrier.h
Normal file
32
arch/parisc/include/asm/barrier.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_BARRIER_H
|
||||
#define __ASM_BARRIER_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* The synchronize caches instruction executes as a nop on systems in
|
||||
which all memory references are performed in order. */
|
||||
#define synchronize_caches() __asm__ __volatile__ ("sync" : : : "memory")
|
||||
|
||||
#if defined(CONFIG_SMP)
|
||||
#define mb() do { synchronize_caches(); } while (0)
|
||||
#define rmb() mb()
|
||||
#define wmb() mb()
|
||||
#define dma_rmb() mb()
|
||||
#define dma_wmb() mb()
|
||||
#else
|
||||
#define mb() barrier()
|
||||
#define rmb() barrier()
|
||||
#define wmb() barrier()
|
||||
#define dma_rmb() barrier()
|
||||
#define dma_wmb() barrier()
|
||||
#endif
|
||||
|
||||
#define __smp_mb() mb()
|
||||
#define __smp_rmb() mb()
|
||||
#define __smp_wmb() mb()
|
||||
|
||||
#include <asm-generic/barrier.h>
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
#endif /* __ASM_BARRIER_H */
|
||||
|
|
@ -21,7 +21,6 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x,
|
|||
{
|
||||
volatile unsigned int *a;
|
||||
|
||||
mb();
|
||||
a = __ldcw_align(x);
|
||||
while (__ldcw(a) == 0)
|
||||
while (*a == 0)
|
||||
|
|
@ -31,16 +30,15 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x,
|
|||
local_irq_disable();
|
||||
} else
|
||||
cpu_relax();
|
||||
mb();
|
||||
}
|
||||
|
||||
static inline void arch_spin_unlock(arch_spinlock_t *x)
|
||||
{
|
||||
volatile unsigned int *a;
|
||||
mb();
|
||||
|
||||
a = __ldcw_align(x);
|
||||
*a = 1;
|
||||
mb();
|
||||
*a = 1;
|
||||
}
|
||||
|
||||
static inline int arch_spin_trylock(arch_spinlock_t *x)
|
||||
|
|
@ -48,10 +46,8 @@ static inline int arch_spin_trylock(arch_spinlock_t *x)
|
|||
volatile unsigned int *a;
|
||||
int ret;
|
||||
|
||||
mb();
|
||||
a = __ldcw_align(x);
|
||||
ret = __ldcw(a) != 0;
|
||||
mb();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -481,6 +481,8 @@
|
|||
/* Release pa_tlb_lock lock without reloading lock address. */
|
||||
.macro tlb_unlock0 spc,tmp
|
||||
#ifdef CONFIG_SMP
|
||||
or,COND(=) %r0,\spc,%r0
|
||||
sync
|
||||
or,COND(=) %r0,\spc,%r0
|
||||
stw \spc,0(\tmp)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ ENDPROC(flush_data_cache_local)
|
|||
.macro tlb_unlock la,flags,tmp
|
||||
#ifdef CONFIG_SMP
|
||||
ldi 1,\tmp
|
||||
sync
|
||||
stw \tmp,0(\la)
|
||||
mtsm \flags
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -627,11 +627,12 @@ cas_action:
|
|||
stw %r1, 4(%sr2,%r20)
|
||||
#endif
|
||||
/* The load and store could fail */
|
||||
1: ldw,ma 0(%r26), %r28
|
||||
1: ldw 0(%r26), %r28
|
||||
sub,<> %r28, %r25, %r0
|
||||
2: stw,ma %r24, 0(%r26)
|
||||
2: stw %r24, 0(%r26)
|
||||
/* Free lock */
|
||||
stw,ma %r20, 0(%sr2,%r20)
|
||||
sync
|
||||
stw %r20, 0(%sr2,%r20)
|
||||
#if ENABLE_LWS_DEBUG
|
||||
/* Clear thread register indicator */
|
||||
stw %r0, 4(%sr2,%r20)
|
||||
|
|
@ -645,6 +646,7 @@ cas_action:
|
|||
3:
|
||||
/* Error occurred on load or store */
|
||||
/* Free lock */
|
||||
sync
|
||||
stw %r20, 0(%sr2,%r20)
|
||||
#if ENABLE_LWS_DEBUG
|
||||
stw %r0, 4(%sr2,%r20)
|
||||
|
|
@ -794,30 +796,30 @@ cas2_action:
|
|||
ldo 1(%r0),%r28
|
||||
|
||||
/* 8bit CAS */
|
||||
13: ldb,ma 0(%r26), %r29
|
||||
13: ldb 0(%r26), %r29
|
||||
sub,= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
14: stb,ma %r24, 0(%r26)
|
||||
14: stb %r24, 0(%r26)
|
||||
b cas2_end
|
||||
copy %r0, %r28
|
||||
nop
|
||||
nop
|
||||
|
||||
/* 16bit CAS */
|
||||
15: ldh,ma 0(%r26), %r29
|
||||
15: ldh 0(%r26), %r29
|
||||
sub,= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
16: sth,ma %r24, 0(%r26)
|
||||
16: sth %r24, 0(%r26)
|
||||
b cas2_end
|
||||
copy %r0, %r28
|
||||
nop
|
||||
nop
|
||||
|
||||
/* 32bit CAS */
|
||||
17: ldw,ma 0(%r26), %r29
|
||||
17: ldw 0(%r26), %r29
|
||||
sub,= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
18: stw,ma %r24, 0(%r26)
|
||||
18: stw %r24, 0(%r26)
|
||||
b cas2_end
|
||||
copy %r0, %r28
|
||||
nop
|
||||
|
|
@ -825,10 +827,10 @@ cas2_action:
|
|||
|
||||
/* 64bit CAS */
|
||||
#ifdef CONFIG_64BIT
|
||||
19: ldd,ma 0(%r26), %r29
|
||||
19: ldd 0(%r26), %r29
|
||||
sub,*= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
20: std,ma %r24, 0(%r26)
|
||||
20: std %r24, 0(%r26)
|
||||
copy %r0, %r28
|
||||
#else
|
||||
/* Compare first word */
|
||||
|
|
@ -846,7 +848,8 @@ cas2_action:
|
|||
|
||||
cas2_end:
|
||||
/* Free lock */
|
||||
stw,ma %r20, 0(%sr2,%r20)
|
||||
sync
|
||||
stw %r20, 0(%sr2,%r20)
|
||||
/* Enable interrupts */
|
||||
ssm PSW_SM_I, %r0
|
||||
/* Return to userspace, set no error */
|
||||
|
|
@ -856,6 +859,7 @@ cas2_end:
|
|||
22:
|
||||
/* Error occurred on load or store */
|
||||
/* Free lock */
|
||||
sync
|
||||
stw %r20, 0(%sr2,%r20)
|
||||
ssm PSW_SM_I, %r0
|
||||
ldo 1(%r0),%r28
|
||||
|
|
|
|||
|
|
@ -720,7 +720,7 @@ start_here:
|
|||
tovirt(r6,r6)
|
||||
lis r5, abatron_pteptrs@h
|
||||
ori r5, r5, abatron_pteptrs@l
|
||||
stw r5, 0xf0(r0) /* Must match your Abatron config file */
|
||||
stw r5, 0xf0(0) /* Must match your Abatron config file */
|
||||
tophys(r5,r5)
|
||||
stw r6, 0(r5)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
|
|
|
|||
|
|
@ -69,14 +69,14 @@ static inline void slb_shadow_update(unsigned long ea, int ssize,
|
|||
* updating it. No write barriers are needed here, provided
|
||||
* we only update the current CPU's SLB shadow buffer.
|
||||
*/
|
||||
p->save_area[index].esid = 0;
|
||||
p->save_area[index].vsid = cpu_to_be64(mk_vsid_data(ea, ssize, flags));
|
||||
p->save_area[index].esid = cpu_to_be64(mk_esid_data(ea, ssize, index));
|
||||
WRITE_ONCE(p->save_area[index].esid, 0);
|
||||
WRITE_ONCE(p->save_area[index].vsid, cpu_to_be64(mk_vsid_data(ea, ssize, flags)));
|
||||
WRITE_ONCE(p->save_area[index].esid, cpu_to_be64(mk_esid_data(ea, ssize, index)));
|
||||
}
|
||||
|
||||
static inline void slb_shadow_clear(enum slb_index index)
|
||||
{
|
||||
get_slb_shadow()->save_area[index].esid = 0;
|
||||
WRITE_ONCE(get_slb_shadow()->save_area[index].esid, 0);
|
||||
}
|
||||
|
||||
static inline void create_shadowed_slbe(unsigned long ea, int ssize,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <asm/sections.h>
|
||||
#include <asm/time.h>
|
||||
|
||||
#include <platforms/chrp/chrp.h>
|
||||
|
||||
extern spinlock_t rtc_lock;
|
||||
|
||||
#define NVRAM_AS0 0x74
|
||||
|
|
@ -62,7 +64,7 @@ long __init chrp_time_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int chrp_cmos_clock_read(int addr)
|
||||
static int chrp_cmos_clock_read(int addr)
|
||||
{
|
||||
if (nvram_as1 != 0)
|
||||
outb(addr>>8, nvram_as1);
|
||||
|
|
@ -70,7 +72,7 @@ int chrp_cmos_clock_read(int addr)
|
|||
return (inb(nvram_data));
|
||||
}
|
||||
|
||||
void chrp_cmos_clock_write(unsigned long val, int addr)
|
||||
static void chrp_cmos_clock_write(unsigned long val, int addr)
|
||||
{
|
||||
if (nvram_as1 != 0)
|
||||
outb(addr>>8, nvram_as1);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
*/
|
||||
#define HW_BROADWAY_ICR 0x00
|
||||
#define HW_BROADWAY_IMR 0x04
|
||||
#define HW_STARLET_ICR 0x08
|
||||
#define HW_STARLET_IMR 0x0c
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -74,6 +76,9 @@ static void hlwd_pic_unmask(struct irq_data *d)
|
|||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
|
||||
|
||||
/* Make sure the ARM (aka. Starlet) doesn't handle this interrupt. */
|
||||
clrbits32(io_base + HW_STARLET_IMR, 1 << irq);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -467,7 +467,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
|
|||
boot_infos_t *bi = (boot_infos_t *) r4;
|
||||
unsigned long hdr;
|
||||
unsigned long space;
|
||||
unsigned long ptr, x;
|
||||
unsigned long ptr;
|
||||
char *model;
|
||||
unsigned long offset = reloc_offset();
|
||||
|
||||
|
|
@ -561,6 +561,8 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
|
|||
* MMU switched OFF, so this should not be useful anymore.
|
||||
*/
|
||||
if (bi->version < 4) {
|
||||
unsigned long x __maybe_unused;
|
||||
|
||||
bootx_printf("Touching pages...\n");
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -359,6 +359,7 @@ static int pmac_late_init(void)
|
|||
}
|
||||
machine_late_initcall(powermac, pmac_late_init);
|
||||
|
||||
void note_bootable_part(dev_t dev, int part, int goodness);
|
||||
/*
|
||||
* This is __init_refok because we check for "initializing" before
|
||||
* touching any of the __init sensitive things and "initializing"
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ struct hws_basic_entry {
|
|||
|
||||
struct hws_diag_entry {
|
||||
unsigned int def:16; /* 0-15 Data Entry Format */
|
||||
unsigned int R:14; /* 16-19 and 20-30 reserved */
|
||||
unsigned int R:15; /* 16-19 and 20-30 reserved */
|
||||
unsigned int I:1; /* 31 entry valid or invalid */
|
||||
u8 data[]; /* Machine-dependent sample data */
|
||||
} __packed;
|
||||
|
|
@ -129,7 +129,9 @@ struct hws_trailer_entry {
|
|||
unsigned int f:1; /* 0 - Block Full Indicator */
|
||||
unsigned int a:1; /* 1 - Alert request control */
|
||||
unsigned int t:1; /* 2 - Timestamp format */
|
||||
unsigned long long:61; /* 3 - 63: Reserved */
|
||||
unsigned int :29; /* 3 - 31: Reserved */
|
||||
unsigned int bsdes:16; /* 32-47: size of basic SDE */
|
||||
unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
|
||||
};
|
||||
unsigned long long flags; /* 0 - 63: All indicators */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -261,7 +261,6 @@ struct qdio_outbuf_state {
|
|||
void *user;
|
||||
};
|
||||
|
||||
#define QDIO_OUTBUF_STATE_FLAG_NONE 0x00
|
||||
#define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01
|
||||
|
||||
#define CHSC_AC1_INITIATE_INPUTQ 0x80
|
||||
|
|
|
|||
|
|
@ -459,6 +459,8 @@ static inline int do_exception(struct pt_regs *regs, int access)
|
|||
/* No reason to continue if interrupted by SIGKILL. */
|
||||
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
|
||||
fault = VM_FAULT_SIGNAL;
|
||||
if (flags & FAULT_FLAG_RETRY_NOWAIT)
|
||||
goto out_up;
|
||||
goto out;
|
||||
}
|
||||
if (unlikely(fault & VM_FAULT_ERROR))
|
||||
|
|
|
|||
|
|
@ -522,8 +522,6 @@ static void bpf_jit_epilogue(struct bpf_jit *jit)
|
|||
/* br %r1 */
|
||||
_EMIT2(0x07f1);
|
||||
} else {
|
||||
/* larl %r1,.+14 */
|
||||
EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
|
||||
/* ex 0,S390_lowcore.br_r1_tampoline */
|
||||
EMIT4_DISP(0x44000000, REG_0, REG_0,
|
||||
offsetof(struct _lowcore, br_r1_trampoline));
|
||||
|
|
|
|||
|
|
@ -412,6 +412,8 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
|||
hwirq = 0;
|
||||
for_each_pci_msi_entry(msi, pdev) {
|
||||
rc = -EIO;
|
||||
if (hwirq >= msi_vecs)
|
||||
break;
|
||||
irq = irq_alloc_desc(0); /* Alloc irq on node 0 */
|
||||
if (irq < 0)
|
||||
goto out_msi;
|
||||
|
|
|
|||
|
|
@ -79,24 +79,33 @@ ENTRY(entry_SYSENTER_compat)
|
|||
ASM_CLAC /* Clear AC after saving FLAGS */
|
||||
|
||||
pushq $__USER32_CS /* pt_regs->cs */
|
||||
xorq %r8,%r8
|
||||
pushq %r8 /* pt_regs->ip = 0 (placeholder) */
|
||||
pushq $0 /* pt_regs->ip = 0 (placeholder) */
|
||||
pushq %rax /* pt_regs->orig_ax */
|
||||
pushq %rdi /* pt_regs->di */
|
||||
pushq %rsi /* pt_regs->si */
|
||||
pushq %rdx /* pt_regs->dx */
|
||||
pushq %rcx /* pt_regs->cx */
|
||||
pushq $-ENOSYS /* pt_regs->ax */
|
||||
pushq %r8 /* pt_regs->r8 = 0 */
|
||||
pushq %r8 /* pt_regs->r9 = 0 */
|
||||
pushq %r8 /* pt_regs->r10 = 0 */
|
||||
pushq %r8 /* pt_regs->r11 = 0 */
|
||||
pushq $0 /* pt_regs->r8 = 0 */
|
||||
xorq %r8, %r8 /* nospec r8 */
|
||||
pushq $0 /* pt_regs->r9 = 0 */
|
||||
xorq %r9, %r9 /* nospec r9 */
|
||||
pushq $0 /* pt_regs->r10 = 0 */
|
||||
xorq %r10, %r10 /* nospec r10 */
|
||||
pushq $0 /* pt_regs->r11 = 0 */
|
||||
xorq %r11, %r11 /* nospec r11 */
|
||||
pushq %rbx /* pt_regs->rbx */
|
||||
xorl %ebx, %ebx /* nospec rbx */
|
||||
pushq %rbp /* pt_regs->rbp (will be overwritten) */
|
||||
pushq %r8 /* pt_regs->r12 = 0 */
|
||||
pushq %r8 /* pt_regs->r13 = 0 */
|
||||
pushq %r8 /* pt_regs->r14 = 0 */
|
||||
pushq %r8 /* pt_regs->r15 = 0 */
|
||||
xorl %ebp, %ebp /* nospec rbp */
|
||||
pushq $0 /* pt_regs->r12 = 0 */
|
||||
xorq %r12, %r12 /* nospec r12 */
|
||||
pushq $0 /* pt_regs->r13 = 0 */
|
||||
xorq %r13, %r13 /* nospec r13 */
|
||||
pushq $0 /* pt_regs->r14 = 0 */
|
||||
xorq %r14, %r14 /* nospec r14 */
|
||||
pushq $0 /* pt_regs->r15 = 0 */
|
||||
xorq %r15, %r15 /* nospec r15 */
|
||||
cld
|
||||
|
||||
/*
|
||||
|
|
@ -185,17 +194,26 @@ ENTRY(entry_SYSCALL_compat)
|
|||
pushq %rdx /* pt_regs->dx */
|
||||
pushq %rbp /* pt_regs->cx (stashed in bp) */
|
||||
pushq $-ENOSYS /* pt_regs->ax */
|
||||
xorq %r8,%r8
|
||||
pushq %r8 /* pt_regs->r8 = 0 */
|
||||
pushq %r8 /* pt_regs->r9 = 0 */
|
||||
pushq %r8 /* pt_regs->r10 = 0 */
|
||||
pushq %r8 /* pt_regs->r11 = 0 */
|
||||
pushq $0 /* pt_regs->r8 = 0 */
|
||||
xorq %r8, %r8 /* nospec r8 */
|
||||
pushq $0 /* pt_regs->r9 = 0 */
|
||||
xorq %r9, %r9 /* nospec r9 */
|
||||
pushq $0 /* pt_regs->r10 = 0 */
|
||||
xorq %r10, %r10 /* nospec r10 */
|
||||
pushq $0 /* pt_regs->r11 = 0 */
|
||||
xorq %r11, %r11 /* nospec r11 */
|
||||
pushq %rbx /* pt_regs->rbx */
|
||||
xorl %ebx, %ebx /* nospec rbx */
|
||||
pushq %rbp /* pt_regs->rbp (will be overwritten) */
|
||||
pushq %r8 /* pt_regs->r12 = 0 */
|
||||
pushq %r8 /* pt_regs->r13 = 0 */
|
||||
pushq %r8 /* pt_regs->r14 = 0 */
|
||||
pushq %r8 /* pt_regs->r15 = 0 */
|
||||
xorl %ebp, %ebp /* nospec rbp */
|
||||
pushq $0 /* pt_regs->r12 = 0 */
|
||||
xorq %r12, %r12 /* nospec r12 */
|
||||
pushq $0 /* pt_regs->r13 = 0 */
|
||||
xorq %r13, %r13 /* nospec r13 */
|
||||
pushq $0 /* pt_regs->r14 = 0 */
|
||||
xorq %r14, %r14 /* nospec r14 */
|
||||
pushq $0 /* pt_regs->r15 = 0 */
|
||||
xorq %r15, %r15 /* nospec r15 */
|
||||
|
||||
/*
|
||||
* User mode is traced as though IRQs are on, and SYSENTER
|
||||
|
|
@ -292,17 +310,26 @@ ENTRY(entry_INT80_compat)
|
|||
pushq %rdx /* pt_regs->dx */
|
||||
pushq %rcx /* pt_regs->cx */
|
||||
pushq $-ENOSYS /* pt_regs->ax */
|
||||
xorq %r8,%r8
|
||||
pushq %r8 /* pt_regs->r8 = 0 */
|
||||
pushq %r8 /* pt_regs->r9 = 0 */
|
||||
pushq %r8 /* pt_regs->r10 = 0 */
|
||||
pushq %r8 /* pt_regs->r11 = 0 */
|
||||
pushq $0 /* pt_regs->r8 = 0 */
|
||||
xorq %r8, %r8 /* nospec r8 */
|
||||
pushq $0 /* pt_regs->r9 = 0 */
|
||||
xorq %r9, %r9 /* nospec r9 */
|
||||
pushq $0 /* pt_regs->r10 = 0 */
|
||||
xorq %r10, %r10 /* nospec r10 */
|
||||
pushq $0 /* pt_regs->r11 = 0 */
|
||||
xorq %r11, %r11 /* nospec r11 */
|
||||
pushq %rbx /* pt_regs->rbx */
|
||||
xorl %ebx, %ebx /* nospec rbx */
|
||||
pushq %rbp /* pt_regs->rbp */
|
||||
xorl %ebp, %ebp /* nospec rbp */
|
||||
pushq %r12 /* pt_regs->r12 */
|
||||
xorq %r12, %r12 /* nospec r12 */
|
||||
pushq %r13 /* pt_regs->r13 */
|
||||
xorq %r13, %r13 /* nospec r13 */
|
||||
pushq %r14 /* pt_regs->r14 */
|
||||
xorq %r14, %r14 /* nospec r14 */
|
||||
pushq %r15 /* pt_regs->r15 */
|
||||
xorq %r15, %r15 /* nospec r15 */
|
||||
cld
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef _ASM_X86_MACH_DEFAULT_APM_H
|
||||
#define _ASM_X86_MACH_DEFAULT_APM_H
|
||||
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#ifdef APM_ZERO_SEGS
|
||||
# define APM_DO_ZERO_SEGS \
|
||||
"pushl %%ds\n\t" \
|
||||
|
|
@ -31,6 +33,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
|
|||
* N.B. We do NOT need a cld after the BIOS call
|
||||
* because we always save and restore the flags.
|
||||
*/
|
||||
firmware_restrict_branch_speculation_start();
|
||||
__asm__ __volatile__(APM_DO_ZERO_SEGS
|
||||
"pushl %%edi\n\t"
|
||||
"pushl %%ebp\n\t"
|
||||
|
|
@ -43,6 +46,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
|
|||
"=S" (*esi)
|
||||
: "a" (func), "b" (ebx_in), "c" (ecx_in)
|
||||
: "memory", "cc");
|
||||
firmware_restrict_branch_speculation_end();
|
||||
}
|
||||
|
||||
static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in,
|
||||
|
|
@ -55,6 +59,7 @@ static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in,
|
|||
* N.B. We do NOT need a cld after the BIOS call
|
||||
* because we always save and restore the flags.
|
||||
*/
|
||||
firmware_restrict_branch_speculation_start();
|
||||
__asm__ __volatile__(APM_DO_ZERO_SEGS
|
||||
"pushl %%edi\n\t"
|
||||
"pushl %%ebp\n\t"
|
||||
|
|
@ -67,6 +72,7 @@ static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in,
|
|||
"=S" (si)
|
||||
: "a" (func), "b" (ebx_in), "c" (ecx_in)
|
||||
: "memory", "cc");
|
||||
firmware_restrict_branch_speculation_end();
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
|
|||
|
||||
asm volatile ("cmp %1,%2; sbb %0,%0;"
|
||||
:"=r" (mask)
|
||||
:"r"(size),"r" (index)
|
||||
:"g"(size),"r" (index)
|
||||
:"cc");
|
||||
return mask;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ enum cpuid_leafs
|
|||
CPUID_8000_000A_EDX,
|
||||
CPUID_7_ECX,
|
||||
CPUID_8000_0007_EBX,
|
||||
CPUID_7_EDX,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_X86_FEATURE_NAMES
|
||||
|
|
@ -78,8 +79,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
|
|||
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) || \
|
||||
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) || \
|
||||
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) || \
|
||||
CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) || \
|
||||
REQUIRED_MASK_CHECK || \
|
||||
BUILD_BUG_ON_ZERO(NCAPINTS != 18))
|
||||
BUILD_BUG_ON_ZERO(NCAPINTS != 19))
|
||||
|
||||
#define DISABLED_MASK_BIT_SET(feature_bit) \
|
||||
( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 0, feature_bit) || \
|
||||
|
|
@ -100,8 +102,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
|
|||
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) || \
|
||||
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) || \
|
||||
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) || \
|
||||
CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) || \
|
||||
DISABLED_MASK_CHECK || \
|
||||
BUILD_BUG_ON_ZERO(NCAPINTS != 18))
|
||||
BUILD_BUG_ON_ZERO(NCAPINTS != 19))
|
||||
|
||||
#define cpu_has(c, bit) \
|
||||
(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
/*
|
||||
* Defines x86 CPU feature bits
|
||||
*/
|
||||
#define NCAPINTS 18 /* N 32-bit words worth of info */
|
||||
#define NCAPINTS 19 /* N 32-bit words worth of info */
|
||||
#define NBUGINTS 1 /* N 32-bit bug flags */
|
||||
|
||||
/*
|
||||
|
|
@ -193,14 +193,29 @@
|
|||
#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
|
||||
#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
|
||||
|
||||
#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
|
||||
#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */
|
||||
#define X86_FEATURE_RETPOLINE ( 7*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
|
||||
#define X86_FEATURE_RETPOLINE_AMD ( 7*32+13) /* "" AMD Retpoline mitigation for Spectre variant 2 */
|
||||
|
||||
#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
|
||||
#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */
|
||||
|
||||
#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */
|
||||
#define X86_FEATURE_SSBD ( 7*32+17) /* Speculative Store Bypass Disable */
|
||||
|
||||
#define X86_FEATURE_RETPOLINE ( 7*32+29) /* Generic Retpoline mitigation for Spectre variant 2 */
|
||||
#define X86_FEATURE_RETPOLINE_AMD ( 7*32+30) /* AMD Retpoline mitigation for Spectre variant 2 */
|
||||
/* Because the ALTERNATIVE scheme is for members of the X86_FEATURE club... */
|
||||
#define X86_FEATURE_KAISER ( 7*32+31) /* CONFIG_PAGE_TABLE_ISOLATION w/o nokaiser */
|
||||
|
||||
#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled*/
|
||||
#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */
|
||||
#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */
|
||||
#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation */
|
||||
|
||||
#define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */
|
||||
#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */
|
||||
#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
|
||||
#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
|
||||
#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */
|
||||
|
||||
/* Virtualization flags: Linux defined, word 8 */
|
||||
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
|
||||
#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */
|
||||
|
|
@ -251,6 +266,10 @@
|
|||
|
||||
/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */
|
||||
#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */
|
||||
#define X86_FEATURE_AMD_IBPB (13*32+12) /* Indirect Branch Prediction Barrier */
|
||||
#define X86_FEATURE_AMD_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */
|
||||
#define X86_FEATURE_AMD_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */
|
||||
#define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */
|
||||
|
||||
/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */
|
||||
#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */
|
||||
|
|
@ -285,6 +304,16 @@
|
|||
#define X86_FEATURE_SUCCOR (17*32+1) /* Uncorrectable error containment and recovery */
|
||||
#define X86_FEATURE_SMCA (17*32+3) /* Scalable MCA */
|
||||
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
|
||||
#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
|
||||
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
|
||||
#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
|
||||
#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
|
||||
#define X86_FEATURE_FLUSH_L1D (18*32+28) /* Flush L1D cache */
|
||||
#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
|
||||
#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */
|
||||
|
||||
/*
|
||||
* BUG word(s)
|
||||
*/
|
||||
|
|
@ -302,5 +331,7 @@
|
|||
#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* CPU is affected by meltdown attack and needs kernel page table isolation */
|
||||
#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */
|
||||
#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */
|
||||
#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */
|
||||
#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
|
||||
|
||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#define DISABLED_MASK15 0
|
||||
#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE)
|
||||
#define DISABLED_MASK17 0
|
||||
#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
|
||||
#define DISABLED_MASK18 0
|
||||
#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
|
||||
|
||||
#endif /* _ASM_X86_DISABLED_FEATURES_H */
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <asm/fpu/api.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
/*
|
||||
* We map the EFI regions needed for runtime services non-contiguously,
|
||||
|
|
@ -41,8 +42,10 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
|
|||
({ \
|
||||
efi_status_t __s; \
|
||||
kernel_fpu_begin(); \
|
||||
firmware_restrict_branch_speculation_start(); \
|
||||
__s = ((efi_##f##_t __attribute__((regparm(0)))*) \
|
||||
efi.systab->runtime->f)(args); \
|
||||
firmware_restrict_branch_speculation_end(); \
|
||||
kernel_fpu_end(); \
|
||||
__s; \
|
||||
})
|
||||
|
|
@ -51,8 +54,10 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
|
|||
#define __efi_call_virt(f, args...) \
|
||||
({ \
|
||||
kernel_fpu_begin(); \
|
||||
firmware_restrict_branch_speculation_start(); \
|
||||
((efi_##f##_t __attribute__((regparm(0)))*) \
|
||||
efi.systab->runtime->f)(args); \
|
||||
firmware_restrict_branch_speculation_end(); \
|
||||
kernel_fpu_end(); \
|
||||
})
|
||||
|
||||
|
|
@ -73,7 +78,9 @@ extern u64 asmlinkage efi_call(void *fp, ...);
|
|||
efi_sync_low_kernel_mappings(); \
|
||||
preempt_disable(); \
|
||||
__kernel_fpu_begin(); \
|
||||
firmware_restrict_branch_speculation_start(); \
|
||||
__s = efi_call((void *)efi.systab->runtime->f, __VA_ARGS__); \
|
||||
firmware_restrict_branch_speculation_end(); \
|
||||
__kernel_fpu_end(); \
|
||||
preempt_enable(); \
|
||||
__s; \
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#define INTEL_FAM6_CORE_YONAH 0x0E
|
||||
|
||||
#define INTEL_FAM6_CORE2_MEROM 0x0F
|
||||
#define INTEL_FAM6_CORE2_MEROM_L 0x16
|
||||
#define INTEL_FAM6_CORE2_PENRYN 0x17
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
#define INTEL_FAM6_NEHALEM 0x1E
|
||||
#define INTEL_FAM6_NEHALEM_EP 0x1A
|
||||
#define INTEL_FAM6_NEHALEM_EX 0x2E
|
||||
|
||||
#define INTEL_FAM6_WESTMERE 0x25
|
||||
#define INTEL_FAM6_WESTMERE2 0x1F
|
||||
#define INTEL_FAM6_WESTMERE_EP 0x2C
|
||||
|
|
@ -36,9 +38,9 @@
|
|||
#define INTEL_FAM6_HASWELL_GT3E 0x46
|
||||
|
||||
#define INTEL_FAM6_BROADWELL_CORE 0x3D
|
||||
#define INTEL_FAM6_BROADWELL_XEON_D 0x56
|
||||
#define INTEL_FAM6_BROADWELL_GT3E 0x47
|
||||
#define INTEL_FAM6_BROADWELL_X 0x4F
|
||||
#define INTEL_FAM6_BROADWELL_XEON_D 0x56
|
||||
|
||||
#define INTEL_FAM6_SKYLAKE_MOBILE 0x4E
|
||||
#define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E
|
||||
|
|
@ -56,13 +58,15 @@
|
|||
#define INTEL_FAM6_ATOM_SILVERMONT1 0x37 /* BayTrail/BYT / Valleyview */
|
||||
#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */
|
||||
#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */
|
||||
#define INTEL_FAM6_ATOM_MERRIFIELD1 0x4A /* Tangier */
|
||||
#define INTEL_FAM6_ATOM_MERRIFIELD2 0x5A /* Annidale */
|
||||
#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
|
||||
#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Annidale */
|
||||
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C
|
||||
#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
|
||||
#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A
|
||||
|
||||
/* Xeon Phi */
|
||||
|
||||
#define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */
|
||||
#define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */
|
||||
|
||||
#endif /* _ASM_X86_INTEL_FAMILY_H */
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
* Interrupt control:
|
||||
*/
|
||||
|
||||
static inline unsigned long native_save_fl(void)
|
||||
/* Declaration required for gcc < 4.9 to prevent -Werror=missing-prototypes */
|
||||
extern inline unsigned long native_save_fl(void);
|
||||
extern inline unsigned long native_save_fl(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -26,7 +28,8 @@ static inline unsigned long native_save_fl(void)
|
|||
return flags;
|
||||
}
|
||||
|
||||
static inline void native_restore_fl(unsigned long flags)
|
||||
extern inline void native_restore_fl(unsigned long flags);
|
||||
extern inline void native_restore_fl(unsigned long flags)
|
||||
{
|
||||
asm volatile("push %0 ; popf"
|
||||
: /* no output */
|
||||
|
|
|
|||
|
|
@ -3,12 +3,18 @@
|
|||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
/*
|
||||
* The x86 doesn't have a mmu context, but
|
||||
* we put the segment information here.
|
||||
* x86 has arch-specific MMU state beyond what lives in mm_struct.
|
||||
*/
|
||||
typedef struct {
|
||||
/*
|
||||
* ctx_id uniquely identifies this mm_struct. A ctx_id will never
|
||||
* be reused, and zero is not a valid ctx_id.
|
||||
*/
|
||||
u64 ctx_id;
|
||||
|
||||
#ifdef CONFIG_MODIFY_LDT_SYSCALL
|
||||
struct ldt_struct *ldt;
|
||||
#endif
|
||||
|
|
@ -24,6 +30,11 @@ typedef struct {
|
|||
atomic_t perf_rdpmc_allowed; /* nonzero if rdpmc is allowed */
|
||||
} mm_context_t;
|
||||
|
||||
#define INIT_MM_CONTEXT(mm) \
|
||||
.context = { \
|
||||
.ctx_id = 1, \
|
||||
}
|
||||
|
||||
void leave_mm(int cpu);
|
||||
|
||||
#endif /* _ASM_X86_MMU_H */
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
#include <asm/tlbflush.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/mpx.h>
|
||||
|
||||
extern atomic64_t last_mm_ctx_id;
|
||||
|
||||
#ifndef CONFIG_PARAVIRT
|
||||
static inline void paravirt_activate_mm(struct mm_struct *prev,
|
||||
struct mm_struct *next)
|
||||
|
|
@ -52,15 +55,15 @@ struct ldt_struct {
|
|||
/*
|
||||
* Used for LDT copy/destruction.
|
||||
*/
|
||||
int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
|
||||
void destroy_context(struct mm_struct *mm);
|
||||
int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm);
|
||||
void destroy_context_ldt(struct mm_struct *mm);
|
||||
#else /* CONFIG_MODIFY_LDT_SYSCALL */
|
||||
static inline int init_new_context(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
static inline int init_new_context_ldt(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void destroy_context(struct mm_struct *mm) {}
|
||||
static inline void destroy_context_ldt(struct mm_struct *mm) {}
|
||||
#endif
|
||||
|
||||
static inline void load_mm_ldt(struct mm_struct *mm)
|
||||
|
|
@ -102,6 +105,17 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
|
|||
this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
|
||||
}
|
||||
|
||||
static inline int init_new_context(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
mm->context.ctx_id = atomic64_inc_return(&last_mm_ctx_id);
|
||||
return init_new_context_ldt(tsk, mm);
|
||||
}
|
||||
static inline void destroy_context(struct mm_struct *mm)
|
||||
{
|
||||
destroy_context_ldt(mm);
|
||||
}
|
||||
|
||||
extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
struct task_struct *tsk);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,15 @@
|
|||
#define EFER_FFXSR (1<<_EFER_FFXSR)
|
||||
|
||||
/* Intel MSRs. Some also available on other CPUs */
|
||||
#define MSR_IA32_SPEC_CTRL 0x00000048 /* Speculation Control */
|
||||
#define SPEC_CTRL_IBRS (1 << 0) /* Indirect Branch Restricted Speculation */
|
||||
#define SPEC_CTRL_STIBP (1 << 1) /* Single Thread Indirect Branch Predictors */
|
||||
#define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */
|
||||
#define SPEC_CTRL_SSBD (1 << SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
|
||||
|
||||
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
|
||||
#define PRED_CMD_IBPB (1 << 0) /* Indirect Branch Prediction Barrier */
|
||||
|
||||
#define MSR_IA32_PERFCTR0 0x000000c1
|
||||
#define MSR_IA32_PERFCTR1 0x000000c2
|
||||
#define MSR_FSB_FREQ 0x000000cd
|
||||
|
|
@ -45,6 +54,16 @@
|
|||
#define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
|
||||
|
||||
#define MSR_MTRRcap 0x000000fe
|
||||
|
||||
#define MSR_IA32_ARCH_CAPABILITIES 0x0000010a
|
||||
#define ARCH_CAP_RDCL_NO (1 << 0) /* Not susceptible to Meltdown */
|
||||
#define ARCH_CAP_IBRS_ALL (1 << 1) /* Enhanced IBRS support */
|
||||
#define ARCH_CAP_SSB_NO (1 << 4) /*
|
||||
* Not susceptible to Speculative Store Bypass
|
||||
* attack, so no Speculative Store Bypass
|
||||
* control required.
|
||||
*/
|
||||
|
||||
#define MSR_IA32_BBL_CR_CTL 0x00000119
|
||||
#define MSR_IA32_BBL_CR_CTL3 0x0000011e
|
||||
|
||||
|
|
@ -132,6 +151,7 @@
|
|||
|
||||
/* DEBUGCTLMSR bits (others vary by model): */
|
||||
#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */
|
||||
#define DEBUGCTLMSR_BTF_SHIFT 1
|
||||
#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */
|
||||
#define DEBUGCTLMSR_TR (1UL << 6)
|
||||
#define DEBUGCTLMSR_BTS (1UL << 7)
|
||||
|
|
@ -308,6 +328,8 @@
|
|||
#define MSR_AMD64_IBSOPDATA4 0xc001103d
|
||||
#define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */
|
||||
|
||||
#define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f
|
||||
|
||||
/* Fam 16h MSRs */
|
||||
#define MSR_F16H_L2I_PERF_CTL 0xc0010230
|
||||
#define MSR_F16H_L2I_PERF_CTR 0xc0010231
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <asm/alternative.h>
|
||||
#include <asm/alternative-asm.h>
|
||||
#include <asm/cpufeatures.h>
|
||||
#include <asm/msr-index.h>
|
||||
|
||||
/*
|
||||
* Fill the CPU return stack buffer.
|
||||
|
|
@ -171,6 +172,14 @@ enum spectre_v2_mitigation {
|
|||
SPECTRE_V2_IBRS,
|
||||
};
|
||||
|
||||
/* The Speculative Store Bypass disable variants */
|
||||
enum ssb_mitigation {
|
||||
SPEC_STORE_BYPASS_NONE,
|
||||
SPEC_STORE_BYPASS_DISABLE,
|
||||
SPEC_STORE_BYPASS_PRCTL,
|
||||
SPEC_STORE_BYPASS_SECCOMP,
|
||||
};
|
||||
|
||||
extern char __indirect_thunk_start[];
|
||||
extern char __indirect_thunk_end[];
|
||||
|
||||
|
|
@ -194,6 +203,51 @@ static inline void vmexit_fill_RSB(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
|
||||
{
|
||||
asm volatile(ALTERNATIVE("", "wrmsr", %c[feature])
|
||||
: : "c" (msr),
|
||||
"a" ((u32)val),
|
||||
"d" ((u32)(val >> 32)),
|
||||
[feature] "i" (feature)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void indirect_branch_prediction_barrier(void)
|
||||
{
|
||||
u64 val = PRED_CMD_IBPB;
|
||||
|
||||
alternative_msr_write(MSR_IA32_PRED_CMD, val, X86_FEATURE_USE_IBPB);
|
||||
}
|
||||
|
||||
/* The Intel SPEC CTRL MSR base value cache */
|
||||
extern u64 x86_spec_ctrl_base;
|
||||
|
||||
/*
|
||||
* With retpoline, we must use IBRS to restrict branch prediction
|
||||
* before calling into firmware.
|
||||
*
|
||||
* (Implemented as CPP macros due to header hell.)
|
||||
*/
|
||||
#define firmware_restrict_branch_speculation_start() \
|
||||
do { \
|
||||
u64 val = x86_spec_ctrl_base | SPEC_CTRL_IBRS; \
|
||||
\
|
||||
preempt_disable(); \
|
||||
alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \
|
||||
X86_FEATURE_USE_IBRS_FW); \
|
||||
} while (0)
|
||||
|
||||
#define firmware_restrict_branch_speculation_end() \
|
||||
do { \
|
||||
u64 val = x86_spec_ctrl_base; \
|
||||
\
|
||||
alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \
|
||||
X86_FEATURE_USE_IBRS_FW); \
|
||||
preempt_enable(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -27,8 +27,13 @@
|
|||
#define N_EXCEPTION_STACKS 1
|
||||
|
||||
#ifdef CONFIG_X86_PAE
|
||||
/* 44=32+12, the limit we can fit into an unsigned long pfn */
|
||||
#define __PHYSICAL_MASK_SHIFT 44
|
||||
/*
|
||||
* This is beyond the 44 bit limit imposed by the 32bit long pfns,
|
||||
* but we need the full mask to make sure inverted PROT_NONE
|
||||
* entries have all the host bits set in a guest.
|
||||
* The real limit is still 44 bits.
|
||||
*/
|
||||
#define __PHYSICAL_MASK_SHIFT 52
|
||||
#define __VIRTUAL_MASK_SHIFT 32
|
||||
|
||||
#else /* !CONFIG_X86_PAE */
|
||||
|
|
|
|||
|
|
@ -77,4 +77,21 @@ static inline unsigned long pte_bitop(unsigned long value, unsigned int rightshi
|
|||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val })
|
||||
|
||||
/* No inverted PFNs on 2 level page tables */
|
||||
|
||||
static inline u64 protnone_mask(u64 val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline bool __pte_needs_invert(u64 val)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_PGTABLE_2LEVEL_H */
|
||||
|
|
|
|||
|
|
@ -177,11 +177,44 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp)
|
|||
#endif
|
||||
|
||||
/* Encode and de-code a swap entry */
|
||||
#define SWP_TYPE_BITS 5
|
||||
|
||||
#define SWP_OFFSET_FIRST_BIT (_PAGE_BIT_PROTNONE + 1)
|
||||
|
||||
/* We always extract/encode the offset by shifting it all the way up, and then down again */
|
||||
#define SWP_OFFSET_SHIFT (SWP_OFFSET_FIRST_BIT + SWP_TYPE_BITS)
|
||||
|
||||
#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5)
|
||||
#define __swp_type(x) (((x).val) & 0x1f)
|
||||
#define __swp_offset(x) ((x).val >> 5)
|
||||
#define __swp_entry(type, offset) ((swp_entry_t){(type) | (offset) << 5})
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high })
|
||||
#define __swp_entry_to_pte(x) ((pte_t){ { .pte_high = (x).val } })
|
||||
|
||||
/*
|
||||
* Normally, __swp_entry() converts from arch-independent swp_entry_t to
|
||||
* arch-dependent swp_entry_t, and __swp_entry_to_pte() just stores the result
|
||||
* to pte. But here we have 32bit swp_entry_t and 64bit pte, and need to use the
|
||||
* whole 64 bits. Thus, we shift the "real" arch-dependent conversion to
|
||||
* __swp_entry_to_pte() through the following helper macro based on 64bit
|
||||
* __swp_entry().
|
||||
*/
|
||||
#define __swp_pteval_entry(type, offset) ((pteval_t) { \
|
||||
(~(pteval_t)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \
|
||||
| ((pteval_t)(type) << (64 - SWP_TYPE_BITS)) })
|
||||
|
||||
#define __swp_entry_to_pte(x) ((pte_t){ .pte = \
|
||||
__swp_pteval_entry(__swp_type(x), __swp_offset(x)) })
|
||||
/*
|
||||
* Analogically, __pte_to_swp_entry() doesn't just extract the arch-dependent
|
||||
* swp_entry_t, but also has to convert it from 64bit to the 32bit
|
||||
* intermediate representation, using the following macros based on 64bit
|
||||
* __swp_type() and __swp_offset().
|
||||
*/
|
||||
#define __pteval_swp_type(x) ((unsigned long)((x).pte >> (64 - SWP_TYPE_BITS)))
|
||||
#define __pteval_swp_offset(x) ((unsigned long)(~((x).pte) << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT))
|
||||
|
||||
#define __pte_to_swp_entry(pte) (__swp_entry(__pteval_swp_type(pte), \
|
||||
__pteval_swp_offset(pte)))
|
||||
|
||||
#include <asm/pgtable-invert.h>
|
||||
|
||||
#endif /* _ASM_X86_PGTABLE_3LEVEL_H */
|
||||
|
|
|
|||
41
arch/x86/include/asm/pgtable-invert.h
Normal file
41
arch/x86/include/asm/pgtable-invert.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_PGTABLE_INVERT_H
|
||||
#define _ASM_PGTABLE_INVERT_H 1
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* A clear pte value is special, and doesn't get inverted.
|
||||
*
|
||||
* Note that even users that only pass a pgprot_t (rather
|
||||
* than a full pte) won't trigger the special zero case,
|
||||
* because even PAGE_NONE has _PAGE_PROTNONE | _PAGE_ACCESSED
|
||||
* set. So the all zero case really is limited to just the
|
||||
* cleared page table entry case.
|
||||
*/
|
||||
static inline bool __pte_needs_invert(u64 val)
|
||||
{
|
||||
return val && !(val & _PAGE_PRESENT);
|
||||
}
|
||||
|
||||
/* Get a mask to xor with the page table entry to get the correct pfn. */
|
||||
static inline u64 protnone_mask(u64 val)
|
||||
{
|
||||
return __pte_needs_invert(val) ? ~0ull : 0;
|
||||
}
|
||||
|
||||
static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask)
|
||||
{
|
||||
/*
|
||||
* When a PTE transitions from NONE to !NONE or vice-versa
|
||||
* invert the PFN part to stop speculation.
|
||||
* pte_pfn undoes this when needed.
|
||||
*/
|
||||
if (__pte_needs_invert(oldval) != __pte_needs_invert(val))
|
||||
val = (val & ~mask) | (~val & mask);
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
|
@ -148,19 +148,34 @@ static inline int pte_special(pte_t pte)
|
|||
return pte_flags(pte) & _PAGE_SPECIAL;
|
||||
}
|
||||
|
||||
/* Entries that were set to PROT_NONE are inverted */
|
||||
|
||||
static inline u64 protnone_mask(u64 val);
|
||||
|
||||
static inline unsigned long pte_pfn(pte_t pte)
|
||||
{
|
||||
return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
|
||||
phys_addr_t pfn = pte_val(pte);
|
||||
pfn ^= protnone_mask(pfn);
|
||||
return (pfn & PTE_PFN_MASK) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static inline unsigned long pmd_pfn(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
|
||||
phys_addr_t pfn = pmd_val(pmd);
|
||||
pfn ^= protnone_mask(pfn);
|
||||
return (pfn & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static inline unsigned long pud_pfn(pud_t pud)
|
||||
{
|
||||
return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT;
|
||||
phys_addr_t pfn = pud_val(pud);
|
||||
pfn ^= protnone_mask(pfn);
|
||||
return (pfn & pud_pfn_mask(pud)) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static inline unsigned long pgd_pfn(pgd_t pgd)
|
||||
{
|
||||
return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
|
||||
|
|
@ -305,11 +320,6 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd)
|
|||
return pmd_set_flags(pmd, _PAGE_RW);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
||||
{
|
||||
return pmd_clear_flags(pmd, _PAGE_PRESENT | _PAGE_PROTNONE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
|
||||
static inline int pte_soft_dirty(pte_t pte)
|
||||
{
|
||||
|
|
@ -359,19 +369,58 @@ static inline pgprotval_t massage_pgprot(pgprot_t pgprot)
|
|||
|
||||
static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
|
||||
{
|
||||
return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) |
|
||||
massage_pgprot(pgprot));
|
||||
phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT;
|
||||
pfn ^= protnone_mask(pgprot_val(pgprot));
|
||||
pfn &= PTE_PFN_MASK;
|
||||
return __pte(pfn | massage_pgprot(pgprot));
|
||||
}
|
||||
|
||||
static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
|
||||
{
|
||||
return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) |
|
||||
massage_pgprot(pgprot));
|
||||
phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT;
|
||||
pfn ^= protnone_mask(pgprot_val(pgprot));
|
||||
pfn &= PHYSICAL_PMD_PAGE_MASK;
|
||||
return __pmd(pfn | massage_pgprot(pgprot));
|
||||
}
|
||||
|
||||
static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot)
|
||||
{
|
||||
phys_addr_t pfn = page_nr << PAGE_SHIFT;
|
||||
pfn ^= protnone_mask(pgprot_val(pgprot));
|
||||
pfn &= PHYSICAL_PUD_PAGE_MASK;
|
||||
return __pud(pfn | massage_pgprot(pgprot));
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
||||
{
|
||||
return pfn_pmd(pmd_pfn(pmd),
|
||||
__pgprot(pmd_flags(pmd) & ~(_PAGE_PRESENT|_PAGE_PROTNONE)));
|
||||
}
|
||||
|
||||
static inline pud_t pud_set_flags(pud_t pud, pudval_t set)
|
||||
{
|
||||
pudval_t v = native_pud_val(pud);
|
||||
|
||||
return __pud(v | set);
|
||||
}
|
||||
|
||||
static inline pud_t pud_clear_flags(pud_t pud, pudval_t clear)
|
||||
{
|
||||
pudval_t v = native_pud_val(pud);
|
||||
|
||||
return __pud(v & ~clear);
|
||||
}
|
||||
|
||||
static inline pud_t pud_mkhuge(pud_t pud)
|
||||
{
|
||||
return pud_set_flags(pud, _PAGE_PSE);
|
||||
}
|
||||
|
||||
static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask);
|
||||
|
||||
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
{
|
||||
pteval_t val = pte_val(pte);
|
||||
pteval_t val = pte_val(pte), oldval = val;
|
||||
|
||||
/*
|
||||
* Chop off the NX bit (if present), and add the NX portion of
|
||||
|
|
@ -379,17 +428,17 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|||
*/
|
||||
val &= _PAGE_CHG_MASK;
|
||||
val |= massage_pgprot(newprot) & ~_PAGE_CHG_MASK;
|
||||
|
||||
val = flip_protnone_guard(oldval, val, PTE_PFN_MASK);
|
||||
return __pte(val);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
||||
{
|
||||
pmdval_t val = pmd_val(pmd);
|
||||
pmdval_t val = pmd_val(pmd), oldval = val;
|
||||
|
||||
val &= _HPAGE_CHG_MASK;
|
||||
val |= massage_pgprot(newprot) & ~_HPAGE_CHG_MASK;
|
||||
|
||||
val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK);
|
||||
return __pmd(val);
|
||||
}
|
||||
|
||||
|
|
@ -534,8 +583,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
|
|||
* Currently stuck as a macro due to indirect forward reference to
|
||||
* linux/mmzone.h's __section_mem_map_addr() definition:
|
||||
*/
|
||||
#define pmd_page(pmd) \
|
||||
pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT)
|
||||
#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd))
|
||||
|
||||
/*
|
||||
* the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
|
||||
|
|
@ -603,8 +651,7 @@ static inline unsigned long pud_page_vaddr(pud_t pud)
|
|||
* Currently stuck as a macro due to indirect forward reference to
|
||||
* linux/mmzone.h's __section_mem_map_addr() definition:
|
||||
*/
|
||||
#define pud_page(pud) \
|
||||
pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT)
|
||||
#define pud_page(pud) pfn_to_page(pud_pfn(pud))
|
||||
|
||||
/* Find an entry in the second-level page table.. */
|
||||
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
|
||||
|
|
@ -644,7 +691,7 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd)
|
|||
* Currently stuck as a macro due to indirect forward reference to
|
||||
* linux/mmzone.h's __section_mem_map_addr() definition:
|
||||
*/
|
||||
#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
|
||||
#define pgd_page(pgd) pfn_to_page(pgd_pfn(pgd))
|
||||
|
||||
/* to find an entry in a page-table-directory. */
|
||||
static inline unsigned long pud_index(unsigned long address)
|
||||
|
|
@ -926,6 +973,14 @@ static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define __HAVE_ARCH_PFN_MODIFY_ALLOWED 1
|
||||
extern bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot);
|
||||
|
||||
static inline bool arch_has_pfn_modify_check(void)
|
||||
{
|
||||
return boot_cpu_has_bug(X86_BUG_L1TF);
|
||||
}
|
||||
|
||||
#include <asm-generic/pgtable.h>
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -163,18 +163,52 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
|
|||
#define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
|
||||
#define pte_unmap(pte) ((void)(pte))/* NOP */
|
||||
|
||||
/* Encode and de-code a swap entry */
|
||||
#define SWP_TYPE_BITS 5
|
||||
#define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 1)
|
||||
/*
|
||||
* Encode and de-code a swap entry
|
||||
*
|
||||
* | ... | 11| 10| 9|8|7|6|5| 4| 3|2| 1|0| <- bit number
|
||||
* | ... |SW3|SW2|SW1|G|L|D|A|CD|WT|U| W|P| <- bit names
|
||||
* | TYPE (59-63) | ~OFFSET (9-58) |0|0|X|X| X| X|X|SD|0| <- swp entry
|
||||
*
|
||||
* G (8) is aliased and used as a PROT_NONE indicator for
|
||||
* !present ptes. We need to start storing swap entries above
|
||||
* there. We also need to avoid using A and D because of an
|
||||
* erratum where they can be incorrectly set by hardware on
|
||||
* non-present PTEs.
|
||||
*
|
||||
* SD (1) in swp entry is used to store soft dirty bit, which helps us
|
||||
* remember soft dirty over page migration
|
||||
*
|
||||
* Bit 7 in swp entry should be 0 because pmd_present checks not only P,
|
||||
* but also L and G.
|
||||
*
|
||||
* The offset is inverted by a binary not operation to make the high
|
||||
* physical bits set.
|
||||
*/
|
||||
#define SWP_TYPE_BITS 5
|
||||
|
||||
#define SWP_OFFSET_FIRST_BIT (_PAGE_BIT_PROTNONE + 1)
|
||||
|
||||
/* We always extract/encode the offset by shifting it all the way up, and then down again */
|
||||
#define SWP_OFFSET_SHIFT (SWP_OFFSET_FIRST_BIT+SWP_TYPE_BITS)
|
||||
|
||||
#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS)
|
||||
|
||||
#define __swp_type(x) (((x).val >> (_PAGE_BIT_PRESENT + 1)) \
|
||||
& ((1U << SWP_TYPE_BITS) - 1))
|
||||
#define __swp_offset(x) ((x).val >> SWP_OFFSET_SHIFT)
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { \
|
||||
((type) << (_PAGE_BIT_PRESENT + 1)) \
|
||||
| ((offset) << SWP_OFFSET_SHIFT) })
|
||||
/* Extract the high bits for type */
|
||||
#define __swp_type(x) ((x).val >> (64 - SWP_TYPE_BITS))
|
||||
|
||||
/* Shift up (to get rid of type), then down to get value */
|
||||
#define __swp_offset(x) (~(x).val << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT)
|
||||
|
||||
/*
|
||||
* Shift the offset up "too far" by TYPE bits, then down again
|
||||
* The offset is inverted by a binary not operation to make the high
|
||||
* physical bits set.
|
||||
*/
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { \
|
||||
(~(unsigned long)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \
|
||||
| ((unsigned long)(type) << (64-SWP_TYPE_BITS)) })
|
||||
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val })
|
||||
|
||||
|
|
@ -201,6 +235,8 @@ extern void cleanup_highmap(void);
|
|||
extern void init_extra_mapping_uc(unsigned long phys, unsigned long size);
|
||||
extern void init_extra_mapping_wb(unsigned long phys, unsigned long size);
|
||||
|
||||
#include <asm/pgtable-invert.h>
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_X86_PGTABLE_64_H */
|
||||
|
|
|
|||
|
|
@ -70,15 +70,15 @@
|
|||
/*
|
||||
* Tracking soft dirty bit when a page goes to a swap is tricky.
|
||||
* We need a bit which can be stored in pte _and_ not conflict
|
||||
* with swap entry format. On x86 bits 6 and 7 are *not* involved
|
||||
* into swap entry computation, but bit 6 is used for nonlinear
|
||||
* file mapping, so we borrow bit 7 for soft dirty tracking.
|
||||
* with swap entry format. On x86 bits 1-4 are *not* involved
|
||||
* into swap entry computation, but bit 7 is used for thp migration,
|
||||
* so we borrow bit 1 for soft dirty tracking.
|
||||
*
|
||||
* Please note that this bit must be treated as swap dirty page
|
||||
* mark if and only if the PTE has present bit clear!
|
||||
* mark if and only if the PTE/PMD has present bit clear!
|
||||
*/
|
||||
#ifdef CONFIG_MEM_SOFT_DIRTY
|
||||
#define _PAGE_SWP_SOFT_DIRTY _PAGE_PSE
|
||||
#define _PAGE_SWP_SOFT_DIRTY _PAGE_RW
|
||||
#else
|
||||
#define _PAGE_SWP_SOFT_DIRTY (_AT(pteval_t, 0))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -172,6 +172,11 @@ extern const struct seq_operations cpuinfo_op;
|
|||
|
||||
extern void cpu_detect(struct cpuinfo_x86 *c);
|
||||
|
||||
static inline unsigned long long l1tf_pfn_limit(void)
|
||||
{
|
||||
return BIT_ULL(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT);
|
||||
}
|
||||
|
||||
extern void early_cpu_init(void);
|
||||
extern void identify_boot_cpu(void);
|
||||
extern void identify_secondary_cpu(struct cpuinfo_x86 *);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@
|
|||
#define REQUIRED_MASK15 0
|
||||
#define REQUIRED_MASK16 0
|
||||
#define REQUIRED_MASK17 0
|
||||
#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
|
||||
#define REQUIRED_MASK18 0
|
||||
#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
|
||||
|
||||
#endif /* _ASM_X86_REQUIRED_FEATURES_H */
|
||||
|
|
|
|||
80
arch/x86/include/asm/spec-ctrl.h
Normal file
80
arch/x86/include/asm/spec-ctrl.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_X86_SPECCTRL_H_
|
||||
#define _ASM_X86_SPECCTRL_H_
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
/*
|
||||
* On VMENTER we must preserve whatever view of the SPEC_CTRL MSR
|
||||
* the guest has, while on VMEXIT we restore the host view. This
|
||||
* would be easier if SPEC_CTRL were architecturally maskable or
|
||||
* shadowable for guests but this is not (currently) the case.
|
||||
* Takes the guest view of SPEC_CTRL MSR as a parameter and also
|
||||
* the guest's version of VIRT_SPEC_CTRL, if emulated.
|
||||
*/
|
||||
extern void x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool guest);
|
||||
|
||||
/**
|
||||
* x86_spec_ctrl_set_guest - Set speculation control registers for the guest
|
||||
* @guest_spec_ctrl: The guest content of MSR_SPEC_CTRL
|
||||
* @guest_virt_spec_ctrl: The guest controlled bits of MSR_VIRT_SPEC_CTRL
|
||||
* (may get translated to MSR_AMD64_LS_CFG bits)
|
||||
*
|
||||
* Avoids writing to the MSR if the content/bits are the same
|
||||
*/
|
||||
static inline
|
||||
void x86_spec_ctrl_set_guest(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl)
|
||||
{
|
||||
x86_virt_spec_ctrl(guest_spec_ctrl, guest_virt_spec_ctrl, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* x86_spec_ctrl_restore_host - Restore host speculation control registers
|
||||
* @guest_spec_ctrl: The guest content of MSR_SPEC_CTRL
|
||||
* @guest_virt_spec_ctrl: The guest controlled bits of MSR_VIRT_SPEC_CTRL
|
||||
* (may get translated to MSR_AMD64_LS_CFG bits)
|
||||
*
|
||||
* Avoids writing to the MSR if the content/bits are the same
|
||||
*/
|
||||
static inline
|
||||
void x86_spec_ctrl_restore_host(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl)
|
||||
{
|
||||
x86_virt_spec_ctrl(guest_spec_ctrl, guest_virt_spec_ctrl, false);
|
||||
}
|
||||
|
||||
/* AMD specific Speculative Store Bypass MSR data */
|
||||
extern u64 x86_amd_ls_cfg_base;
|
||||
extern u64 x86_amd_ls_cfg_ssbd_mask;
|
||||
|
||||
static inline u64 ssbd_tif_to_spec_ctrl(u64 tifn)
|
||||
{
|
||||
BUILD_BUG_ON(TIF_SSBD < SPEC_CTRL_SSBD_SHIFT);
|
||||
return (tifn & _TIF_SSBD) >> (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
|
||||
}
|
||||
|
||||
static inline unsigned long ssbd_spec_ctrl_to_tif(u64 spec_ctrl)
|
||||
{
|
||||
BUILD_BUG_ON(TIF_SSBD < SPEC_CTRL_SSBD_SHIFT);
|
||||
return (spec_ctrl & SPEC_CTRL_SSBD) << (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
|
||||
}
|
||||
|
||||
static inline u64 ssbd_tif_to_amd_ls_cfg(u64 tifn)
|
||||
{
|
||||
return (tifn & _TIF_SSBD) ? x86_amd_ls_cfg_ssbd_mask : 0ULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern void speculative_store_bypass_ht_init(void);
|
||||
#else
|
||||
static inline void speculative_store_bypass_ht_init(void) { }
|
||||
#endif
|
||||
|
||||
extern void speculative_store_bypass_update(unsigned long tif);
|
||||
|
||||
static inline void speculative_store_bypass_update_current(void)
|
||||
{
|
||||
speculative_store_bypass_update(current_thread_info()->flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -92,6 +92,7 @@ struct thread_info {
|
|||
#define TIF_SIGPENDING 2 /* signal pending */
|
||||
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
|
||||
#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
|
||||
#define TIF_SSBD 5 /* Reduced data speculation */
|
||||
#define TIF_SYSCALL_EMU 6 /* syscall emulation active */
|
||||
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
|
||||
#define TIF_SECCOMP 8 /* secure computing */
|
||||
|
|
@ -114,8 +115,9 @@ struct thread_info {
|
|||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
|
||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
|
||||
#define _TIF_SSBD (1 << TIF_SSBD)
|
||||
#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
|
||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
||||
|
|
@ -147,7 +149,7 @@ struct thread_info {
|
|||
|
||||
/* flags to check in __switch_to() */
|
||||
#define _TIF_WORK_CTXSW \
|
||||
(_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP)
|
||||
(_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP|_TIF_SSBD)
|
||||
|
||||
#define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
|
||||
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ static inline void invpcid_flush_all_nonglobals(void)
|
|||
struct tlb_state {
|
||||
struct mm_struct *active_mm;
|
||||
int state;
|
||||
/* last user mm's ctx id */
|
||||
u64 last_ctx_id;
|
||||
|
||||
/*
|
||||
* Access to this CR4 shadow and to H/W CR4 is protected by
|
||||
|
|
@ -109,6 +111,16 @@ static inline void cr4_clear_bits(unsigned long mask)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void cr4_toggle_bits(unsigned long mask)
|
||||
{
|
||||
unsigned long cr4;
|
||||
|
||||
cr4 = this_cpu_read(cpu_tlbstate.cr4);
|
||||
cr4 ^= mask;
|
||||
this_cpu_write(cpu_tlbstate.cr4, cr4);
|
||||
__write_cr4(cr4);
|
||||
}
|
||||
|
||||
/* Read the CR4 shadow. */
|
||||
static inline unsigned long cr4_read_shadow(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
|
|||
obj-y += tsc.o tsc_msr.o io_delay.o rtc.o
|
||||
obj-y += pci-iommu_table.o
|
||||
obj-y += resource.o
|
||||
obj-y += irqflags.o
|
||||
|
||||
obj-y += process.o
|
||||
obj-y += fpu/
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/pci-direct.h>
|
||||
#include <asm/delay.h>
|
||||
|
|
@ -519,6 +520,26 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
|
|||
|
||||
if (cpu_has(c, X86_FEATURE_MWAITX))
|
||||
use_mwaitx_delay();
|
||||
|
||||
if (c->x86 >= 0x15 && c->x86 <= 0x17) {
|
||||
unsigned int bit;
|
||||
|
||||
switch (c->x86) {
|
||||
case 0x15: bit = 54; break;
|
||||
case 0x16: bit = 33; break;
|
||||
case 0x17: bit = 10; break;
|
||||
default: return;
|
||||
}
|
||||
/*
|
||||
* Try to cache the base value so further operations can
|
||||
* avoid RMW. If that faults, do not enable SSBD.
|
||||
*/
|
||||
if (!rdmsrl_safe(MSR_AMD64_LS_CFG, &x86_amd_ls_cfg_base)) {
|
||||
setup_force_cpu_cap(X86_FEATURE_LS_CFG_SSBD);
|
||||
setup_force_cpu_cap(X86_FEATURE_SSBD);
|
||||
x86_amd_ls_cfg_ssbd_mask = 1ULL << bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void early_init_amd(struct cpuinfo_x86 *c)
|
||||
|
|
@ -692,6 +713,17 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
|
|||
}
|
||||
}
|
||||
|
||||
static void init_amd_zn(struct cpuinfo_x86 *c)
|
||||
{
|
||||
set_cpu_cap(c, X86_FEATURE_ZEN);
|
||||
/*
|
||||
* Fix erratum 1076: CPB feature bit not being set in CPUID. It affects
|
||||
* all up to and including B1.
|
||||
*/
|
||||
if (c->x86_model <= 1 && c->x86_mask <= 1)
|
||||
set_cpu_cap(c, X86_FEATURE_CPB);
|
||||
}
|
||||
|
||||
static void init_amd(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 dummy;
|
||||
|
|
@ -722,6 +754,7 @@ static void init_amd(struct cpuinfo_x86 *c)
|
|||
case 0x10: init_amd_gh(c); break;
|
||||
case 0x12: init_amd_ln(c); break;
|
||||
case 0x15: init_amd_bd(c); break;
|
||||
case 0x17: init_amd_zn(c); break;
|
||||
}
|
||||
|
||||
/* Enable workaround for FXSAVE leak */
|
||||
|
|
@ -791,8 +824,9 @@ static void init_amd(struct cpuinfo_x86 *c)
|
|||
if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM))
|
||||
set_cpu_cap(c, X86_FEATURE_3DNOWPREFETCH);
|
||||
|
||||
/* AMD CPUs don't reset SS attributes on SYSRET */
|
||||
set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
|
||||
/* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
|
||||
if (!cpu_has(c, X86_FEATURE_XENPV))
|
||||
set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@
|
|||
#include <linux/utsname.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/prctl.h>
|
||||
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
#include <asm/cmdline.h>
|
||||
#include <asm/bugs.h>
|
||||
#include <asm/processor.h>
|
||||
|
|
@ -24,8 +26,31 @@
|
|||
#include <asm/pgtable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/e820.h>
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void);
|
||||
static void __init ssb_select_mitigation(void);
|
||||
static void __init l1tf_select_mitigation(void);
|
||||
|
||||
/*
|
||||
* Our boot-time value of the SPEC_CTRL MSR. We read it once so that any
|
||||
* writes to SPEC_CTRL contain whatever reserved bits have been set.
|
||||
*/
|
||||
u64 x86_spec_ctrl_base;
|
||||
EXPORT_SYMBOL_GPL(x86_spec_ctrl_base);
|
||||
|
||||
/*
|
||||
* The vendor and possibly platform specific bits which can be modified in
|
||||
* x86_spec_ctrl_base.
|
||||
*/
|
||||
static u64 x86_spec_ctrl_mask = SPEC_CTRL_IBRS;
|
||||
|
||||
/*
|
||||
* AMD specific MSR info for Speculative Store Bypass control.
|
||||
* x86_amd_ls_cfg_ssbd_mask is initialized in identify_boot_cpu().
|
||||
*/
|
||||
u64 x86_amd_ls_cfg_base;
|
||||
u64 x86_amd_ls_cfg_ssbd_mask;
|
||||
|
||||
void __init check_bugs(void)
|
||||
{
|
||||
|
|
@ -36,9 +61,29 @@ void __init check_bugs(void)
|
|||
print_cpu_info(&boot_cpu_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the SPEC_CTRL MSR to account for reserved bits which may
|
||||
* have unknown values. AMD64_LS_CFG MSR is cached in the early AMD
|
||||
* init code as it is not enumerated and depends on the family.
|
||||
*/
|
||||
if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
|
||||
rdmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
|
||||
|
||||
/* Allow STIBP in MSR_SPEC_CTRL if supported */
|
||||
if (boot_cpu_has(X86_FEATURE_STIBP))
|
||||
x86_spec_ctrl_mask |= SPEC_CTRL_STIBP;
|
||||
|
||||
/* Select the proper spectre mitigation before patching alternatives */
|
||||
spectre_v2_select_mitigation();
|
||||
|
||||
/*
|
||||
* Select proper mitigation for any exposure to the Speculative Store
|
||||
* Bypass vulnerability.
|
||||
*/
|
||||
ssb_select_mitigation();
|
||||
|
||||
l1tf_select_mitigation();
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
* Check whether we are able to run this kernel safely on SMP.
|
||||
|
|
@ -94,6 +139,73 @@ static const char *spectre_v2_strings[] = {
|
|||
|
||||
static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
|
||||
|
||||
void
|
||||
x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
|
||||
{
|
||||
u64 msrval, guestval, hostval = x86_spec_ctrl_base;
|
||||
struct thread_info *ti = current_thread_info();
|
||||
|
||||
/* Is MSR_SPEC_CTRL implemented ? */
|
||||
if (static_cpu_has(X86_FEATURE_MSR_SPEC_CTRL)) {
|
||||
/*
|
||||
* Restrict guest_spec_ctrl to supported values. Clear the
|
||||
* modifiable bits in the host base value and or the
|
||||
* modifiable bits from the guest value.
|
||||
*/
|
||||
guestval = hostval & ~x86_spec_ctrl_mask;
|
||||
guestval |= guest_spec_ctrl & x86_spec_ctrl_mask;
|
||||
|
||||
/* SSBD controlled in MSR_SPEC_CTRL */
|
||||
if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD))
|
||||
hostval |= ssbd_tif_to_spec_ctrl(ti->flags);
|
||||
|
||||
if (hostval != guestval) {
|
||||
msrval = setguest ? guestval : hostval;
|
||||
wrmsrl(MSR_IA32_SPEC_CTRL, msrval);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If SSBD is not handled in MSR_SPEC_CTRL on AMD, update
|
||||
* MSR_AMD64_L2_CFG or MSR_VIRT_SPEC_CTRL if supported.
|
||||
*/
|
||||
if (!static_cpu_has(X86_FEATURE_LS_CFG_SSBD) &&
|
||||
!static_cpu_has(X86_FEATURE_VIRT_SSBD))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the host has SSBD mitigation enabled, force it in the host's
|
||||
* virtual MSR value. If its not permanently enabled, evaluate
|
||||
* current's TIF_SSBD thread flag.
|
||||
*/
|
||||
if (static_cpu_has(X86_FEATURE_SPEC_STORE_BYPASS_DISABLE))
|
||||
hostval = SPEC_CTRL_SSBD;
|
||||
else
|
||||
hostval = ssbd_tif_to_spec_ctrl(ti->flags);
|
||||
|
||||
/* Sanitize the guest value */
|
||||
guestval = guest_virt_spec_ctrl & SPEC_CTRL_SSBD;
|
||||
|
||||
if (hostval != guestval) {
|
||||
unsigned long tif;
|
||||
|
||||
tif = setguest ? ssbd_spec_ctrl_to_tif(guestval) :
|
||||
ssbd_spec_ctrl_to_tif(hostval);
|
||||
|
||||
speculative_store_bypass_update(tif);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(x86_virt_spec_ctrl);
|
||||
|
||||
static void x86_amd_ssb_disable(void)
|
||||
{
|
||||
u64 msrval = x86_amd_ls_cfg_base | x86_amd_ls_cfg_ssbd_mask;
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_VIRT_SSBD))
|
||||
wrmsrl(MSR_AMD64_VIRT_SPEC_CTRL, SPEC_CTRL_SSBD);
|
||||
else if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD))
|
||||
wrmsrl(MSR_AMD64_LS_CFG, msrval);
|
||||
}
|
||||
|
||||
#ifdef RETPOLINE
|
||||
static bool spectre_v2_bad_module;
|
||||
|
|
@ -162,8 +274,7 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
|
|||
if (cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
|
||||
return SPECTRE_V2_CMD_NONE;
|
||||
else {
|
||||
ret = cmdline_find_option(boot_command_line, "spectre_v2", arg,
|
||||
sizeof(arg));
|
||||
ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
|
||||
if (ret < 0)
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
|
||||
|
|
@ -184,8 +295,7 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
|
|||
cmd == SPECTRE_V2_CMD_RETPOLINE_AMD ||
|
||||
cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC) &&
|
||||
!IS_ENABLED(CONFIG_RETPOLINE)) {
|
||||
pr_err("%s selected but not compiled in. Switching to AUTO select\n",
|
||||
mitigation_options[i].option);
|
||||
pr_err("%s selected but not compiled in. Switching to AUTO select\n", mitigation_options[i].option);
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
}
|
||||
|
||||
|
|
@ -203,23 +313,6 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
|
|||
return cmd;
|
||||
}
|
||||
|
||||
/* Check for Skylake-like CPUs (for RSB handling) */
|
||||
static bool __init is_skylake_era(void)
|
||||
{
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
|
||||
boot_cpu_data.x86 == 6) {
|
||||
switch (boot_cpu_data.x86_model) {
|
||||
case INTEL_FAM6_SKYLAKE_MOBILE:
|
||||
case INTEL_FAM6_SKYLAKE_DESKTOP:
|
||||
case INTEL_FAM6_SKYLAKE_X:
|
||||
case INTEL_FAM6_KABYLAKE_MOBILE:
|
||||
case INTEL_FAM6_KABYLAKE_DESKTOP:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void)
|
||||
{
|
||||
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
|
||||
|
|
@ -255,14 +348,14 @@ static void __init spectre_v2_select_mitigation(void)
|
|||
goto retpoline_auto;
|
||||
break;
|
||||
}
|
||||
pr_err("kernel not compiled with retpoline; no mitigation available!");
|
||||
pr_err("Spectre mitigation: kernel not compiled with retpoline; no mitigation available!");
|
||||
return;
|
||||
|
||||
retpoline_auto:
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
|
||||
retpoline_amd:
|
||||
if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) {
|
||||
pr_err("LFENCE not serializing. Switching to generic retpoline\n");
|
||||
pr_err("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n");
|
||||
goto retpoline_generic;
|
||||
}
|
||||
mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD :
|
||||
|
|
@ -280,52 +373,359 @@ static void __init spectre_v2_select_mitigation(void)
|
|||
pr_info("%s\n", spectre_v2_strings[mode]);
|
||||
|
||||
/*
|
||||
* If neither SMEP or KPTI are available, there is a risk of
|
||||
* hitting userspace addresses in the RSB after a context switch
|
||||
* from a shallow call stack to a deeper one. To prevent this fill
|
||||
* the entire RSB, even when using IBRS.
|
||||
* If spectre v2 protection has been enabled, unconditionally fill
|
||||
* RSB during a context switch; this protects against two independent
|
||||
* issues:
|
||||
*
|
||||
* Skylake era CPUs have a separate issue with *underflow* of the
|
||||
* RSB, when they will predict 'ret' targets from the generic BTB.
|
||||
* The proper mitigation for this is IBRS. If IBRS is not supported
|
||||
* or deactivated in favour of retpolines the RSB fill on context
|
||||
* switch is required.
|
||||
* - RSB underflow (and switch to BTB) on Skylake+
|
||||
* - SpectreRSB variant of spectre v2 on X86_BUG_SPECTRE_V2 CPUs
|
||||
*/
|
||||
if ((!boot_cpu_has(X86_FEATURE_KAISER) &&
|
||||
!boot_cpu_has(X86_FEATURE_SMEP)) || is_skylake_era()) {
|
||||
setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
|
||||
pr_info("Filling RSB on context switch\n");
|
||||
setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
|
||||
pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
|
||||
|
||||
/* Initialize Indirect Branch Prediction Barrier if supported */
|
||||
if (boot_cpu_has(X86_FEATURE_IBPB)) {
|
||||
setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
|
||||
pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Retpoline means the kernel is safe because it has no indirect
|
||||
* branches. But firmware isn't, so use IBRS to protect that.
|
||||
*/
|
||||
if (boot_cpu_has(X86_FEATURE_IBRS)) {
|
||||
setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
|
||||
pr_info("Enabling Restricted Speculation for firmware calls\n");
|
||||
}
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "Speculative Store Bypass: " fmt
|
||||
|
||||
static enum ssb_mitigation ssb_mode = SPEC_STORE_BYPASS_NONE;
|
||||
|
||||
/* The kernel command line selection */
|
||||
enum ssb_mitigation_cmd {
|
||||
SPEC_STORE_BYPASS_CMD_NONE,
|
||||
SPEC_STORE_BYPASS_CMD_AUTO,
|
||||
SPEC_STORE_BYPASS_CMD_ON,
|
||||
SPEC_STORE_BYPASS_CMD_PRCTL,
|
||||
SPEC_STORE_BYPASS_CMD_SECCOMP,
|
||||
};
|
||||
|
||||
static const char *ssb_strings[] = {
|
||||
[SPEC_STORE_BYPASS_NONE] = "Vulnerable",
|
||||
[SPEC_STORE_BYPASS_DISABLE] = "Mitigation: Speculative Store Bypass disabled",
|
||||
[SPEC_STORE_BYPASS_PRCTL] = "Mitigation: Speculative Store Bypass disabled via prctl",
|
||||
[SPEC_STORE_BYPASS_SECCOMP] = "Mitigation: Speculative Store Bypass disabled via prctl and seccomp",
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char *option;
|
||||
enum ssb_mitigation_cmd cmd;
|
||||
} ssb_mitigation_options[] = {
|
||||
{ "auto", SPEC_STORE_BYPASS_CMD_AUTO }, /* Platform decides */
|
||||
{ "on", SPEC_STORE_BYPASS_CMD_ON }, /* Disable Speculative Store Bypass */
|
||||
{ "off", SPEC_STORE_BYPASS_CMD_NONE }, /* Don't touch Speculative Store Bypass */
|
||||
{ "prctl", SPEC_STORE_BYPASS_CMD_PRCTL }, /* Disable Speculative Store Bypass via prctl */
|
||||
{ "seccomp", SPEC_STORE_BYPASS_CMD_SECCOMP }, /* Disable Speculative Store Bypass via prctl and seccomp */
|
||||
};
|
||||
|
||||
static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
|
||||
{
|
||||
enum ssb_mitigation_cmd cmd = SPEC_STORE_BYPASS_CMD_AUTO;
|
||||
char arg[20];
|
||||
int ret, i;
|
||||
|
||||
if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable")) {
|
||||
return SPEC_STORE_BYPASS_CMD_NONE;
|
||||
} else {
|
||||
ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable",
|
||||
arg, sizeof(arg));
|
||||
if (ret < 0)
|
||||
return SPEC_STORE_BYPASS_CMD_AUTO;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ssb_mitigation_options); i++) {
|
||||
if (!match_option(arg, ret, ssb_mitigation_options[i].option))
|
||||
continue;
|
||||
|
||||
cmd = ssb_mitigation_options[i].cmd;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(ssb_mitigation_options)) {
|
||||
pr_err("unknown option (%s). Switching to AUTO select\n", arg);
|
||||
return SPEC_STORE_BYPASS_CMD_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static enum ssb_mitigation __init __ssb_select_mitigation(void)
|
||||
{
|
||||
enum ssb_mitigation mode = SPEC_STORE_BYPASS_NONE;
|
||||
enum ssb_mitigation_cmd cmd;
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_SSBD))
|
||||
return mode;
|
||||
|
||||
cmd = ssb_parse_cmdline();
|
||||
if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS) &&
|
||||
(cmd == SPEC_STORE_BYPASS_CMD_NONE ||
|
||||
cmd == SPEC_STORE_BYPASS_CMD_AUTO))
|
||||
return mode;
|
||||
|
||||
switch (cmd) {
|
||||
case SPEC_STORE_BYPASS_CMD_AUTO:
|
||||
case SPEC_STORE_BYPASS_CMD_SECCOMP:
|
||||
/*
|
||||
* Choose prctl+seccomp as the default mode if seccomp is
|
||||
* enabled.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_SECCOMP))
|
||||
mode = SPEC_STORE_BYPASS_SECCOMP;
|
||||
else
|
||||
mode = SPEC_STORE_BYPASS_PRCTL;
|
||||
break;
|
||||
case SPEC_STORE_BYPASS_CMD_ON:
|
||||
mode = SPEC_STORE_BYPASS_DISABLE;
|
||||
break;
|
||||
case SPEC_STORE_BYPASS_CMD_PRCTL:
|
||||
mode = SPEC_STORE_BYPASS_PRCTL;
|
||||
break;
|
||||
case SPEC_STORE_BYPASS_CMD_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have three CPU feature flags that are in play here:
|
||||
* - X86_BUG_SPEC_STORE_BYPASS - CPU is susceptible.
|
||||
* - X86_FEATURE_SSBD - CPU is able to turn off speculative store bypass
|
||||
* - X86_FEATURE_SPEC_STORE_BYPASS_DISABLE - engage the mitigation
|
||||
*/
|
||||
if (mode == SPEC_STORE_BYPASS_DISABLE) {
|
||||
setup_force_cpu_cap(X86_FEATURE_SPEC_STORE_BYPASS_DISABLE);
|
||||
/*
|
||||
* Intel uses the SPEC CTRL MSR Bit(2) for this, while AMD uses
|
||||
* a completely different MSR and bit dependent on family.
|
||||
*/
|
||||
switch (boot_cpu_data.x86_vendor) {
|
||||
case X86_VENDOR_INTEL:
|
||||
x86_spec_ctrl_base |= SPEC_CTRL_SSBD;
|
||||
x86_spec_ctrl_mask |= SPEC_CTRL_SSBD;
|
||||
wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
|
||||
break;
|
||||
case X86_VENDOR_AMD:
|
||||
x86_amd_ssb_disable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void ssb_select_mitigation(void)
|
||||
{
|
||||
ssb_mode = __ssb_select_mitigation();
|
||||
|
||||
if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
|
||||
pr_info("%s\n", ssb_strings[ssb_mode]);
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "Speculation prctl: " fmt
|
||||
|
||||
static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||
{
|
||||
bool update;
|
||||
|
||||
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL &&
|
||||
ssb_mode != SPEC_STORE_BYPASS_SECCOMP)
|
||||
return -ENXIO;
|
||||
|
||||
switch (ctrl) {
|
||||
case PR_SPEC_ENABLE:
|
||||
/* If speculation is force disabled, enable is not allowed */
|
||||
if (task_spec_ssb_force_disable(task))
|
||||
return -EPERM;
|
||||
task_clear_spec_ssb_disable(task);
|
||||
update = test_and_clear_tsk_thread_flag(task, TIF_SSBD);
|
||||
break;
|
||||
case PR_SPEC_DISABLE:
|
||||
task_set_spec_ssb_disable(task);
|
||||
update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
|
||||
break;
|
||||
case PR_SPEC_FORCE_DISABLE:
|
||||
task_set_spec_ssb_disable(task);
|
||||
task_set_spec_ssb_force_disable(task);
|
||||
update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If being set on non-current task, delay setting the CPU
|
||||
* mitigation until it is next scheduled.
|
||||
*/
|
||||
if (task == current && update)
|
||||
speculative_store_bypass_update_current();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
|
||||
unsigned long ctrl)
|
||||
{
|
||||
switch (which) {
|
||||
case PR_SPEC_STORE_BYPASS:
|
||||
return ssb_prctl_set(task, ctrl);
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECCOMP
|
||||
void arch_seccomp_spec_mitigate(struct task_struct *task)
|
||||
{
|
||||
if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP)
|
||||
ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ssb_prctl_get(struct task_struct *task)
|
||||
{
|
||||
switch (ssb_mode) {
|
||||
case SPEC_STORE_BYPASS_DISABLE:
|
||||
return PR_SPEC_DISABLE;
|
||||
case SPEC_STORE_BYPASS_SECCOMP:
|
||||
case SPEC_STORE_BYPASS_PRCTL:
|
||||
if (task_spec_ssb_force_disable(task))
|
||||
return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
|
||||
if (task_spec_ssb_disable(task))
|
||||
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
|
||||
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
|
||||
default:
|
||||
if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
|
||||
return PR_SPEC_ENABLE;
|
||||
return PR_SPEC_NOT_AFFECTED;
|
||||
}
|
||||
}
|
||||
|
||||
int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
|
||||
{
|
||||
switch (which) {
|
||||
case PR_SPEC_STORE_BYPASS:
|
||||
return ssb_prctl_get(task);
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
void x86_spec_ctrl_setup_ap(void)
|
||||
{
|
||||
if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
|
||||
wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
|
||||
|
||||
if (ssb_mode == SPEC_STORE_BYPASS_DISABLE)
|
||||
x86_amd_ssb_disable();
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "L1TF: " fmt
|
||||
static void __init l1tf_select_mitigation(void)
|
||||
{
|
||||
u64 half_pa;
|
||||
|
||||
if (!boot_cpu_has_bug(X86_BUG_L1TF))
|
||||
return;
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS == 2
|
||||
pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n");
|
||||
return;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is extremely unlikely to happen because almost all
|
||||
* systems have far more MAX_PA/2 than RAM can be fit into
|
||||
* DIMM slots.
|
||||
*/
|
||||
half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT;
|
||||
if (e820_any_mapped(half_pa, ULLONG_MAX - half_pa, E820_RAM)) {
|
||||
pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n");
|
||||
pr_info("You may make it effective by booting the kernel with mem=%llu parameter.\n",
|
||||
half_pa);
|
||||
pr_info("However, doing so will make a part of your RAM unusable.\n");
|
||||
pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html might help you decide.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV);
|
||||
}
|
||||
#undef pr_fmt
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
ssize_t cpu_show_meltdown(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
||||
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
|
||||
char *buf, unsigned int bug)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN))
|
||||
if (!boot_cpu_has_bug(bug))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
if (boot_cpu_has(X86_FEATURE_KAISER))
|
||||
return sprintf(buf, "Mitigation: PTI\n");
|
||||
|
||||
switch (bug) {
|
||||
case X86_BUG_CPU_MELTDOWN:
|
||||
if (boot_cpu_has(X86_FEATURE_KAISER))
|
||||
return sprintf(buf, "Mitigation: PTI\n");
|
||||
|
||||
break;
|
||||
|
||||
case X86_BUG_SPECTRE_V1:
|
||||
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
||||
|
||||
case X86_BUG_SPECTRE_V2:
|
||||
return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
|
||||
boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
|
||||
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
|
||||
spectre_v2_module_string());
|
||||
|
||||
case X86_BUG_SPEC_STORE_BYPASS:
|
||||
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
|
||||
|
||||
case X86_BUG_L1TF:
|
||||
if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
|
||||
return sprintf(buf, "Mitigation: Page Table Inversion\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v1(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_CPU_MELTDOWN);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v2(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_SPECTRE_V1);
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s%s\n", spectre_v2_strings[spectre_v2_enabled],
|
||||
spectre_v2_module_string());
|
||||
ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_SPECTRE_V2);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_SPEC_STORE_BYPASS);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_L1TF);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@
|
|||
#include <asm/pat.h>
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/microcode_intel.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
#include <asm/uv/uv.h>
|
||||
|
|
@ -674,6 +676,40 @@ static void apply_forced_caps(struct cpuinfo_x86 *c)
|
|||
}
|
||||
}
|
||||
|
||||
static void init_speculation_control(struct cpuinfo_x86 *c)
|
||||
{
|
||||
/*
|
||||
* The Intel SPEC_CTRL CPUID bit implies IBRS and IBPB support,
|
||||
* and they also have a different bit for STIBP support. Also,
|
||||
* a hypervisor might have set the individual AMD bits even on
|
||||
* Intel CPUs, for finer-grained selection of what's available.
|
||||
*/
|
||||
if (cpu_has(c, X86_FEATURE_SPEC_CTRL)) {
|
||||
set_cpu_cap(c, X86_FEATURE_IBRS);
|
||||
set_cpu_cap(c, X86_FEATURE_IBPB);
|
||||
set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL);
|
||||
}
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_INTEL_STIBP))
|
||||
set_cpu_cap(c, X86_FEATURE_STIBP);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD))
|
||||
set_cpu_cap(c, X86_FEATURE_SSBD);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_AMD_IBRS)) {
|
||||
set_cpu_cap(c, X86_FEATURE_IBRS);
|
||||
set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL);
|
||||
}
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_AMD_IBPB))
|
||||
set_cpu_cap(c, X86_FEATURE_IBPB);
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_AMD_STIBP)) {
|
||||
set_cpu_cap(c, X86_FEATURE_STIBP);
|
||||
set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
void get_cpu_cap(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
|
@ -695,6 +731,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
|
|||
cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
|
||||
c->x86_capability[CPUID_7_0_EBX] = ebx;
|
||||
c->x86_capability[CPUID_7_ECX] = ecx;
|
||||
c->x86_capability[CPUID_7_EDX] = edx;
|
||||
}
|
||||
|
||||
/* Extended state features: level 0x0000000d */
|
||||
|
|
@ -765,6 +802,14 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
|
|||
c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
|
||||
|
||||
init_scattered_cpuid_features(c);
|
||||
init_speculation_control(c);
|
||||
|
||||
/*
|
||||
* Clear/Set all flags overridden by options, after probe.
|
||||
* This needs to happen each time we re-probe, which may happen
|
||||
* several times during CPU initialization.
|
||||
*/
|
||||
apply_forced_caps(c);
|
||||
}
|
||||
|
||||
static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
|
||||
|
|
@ -793,6 +838,95 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
|
|||
#endif
|
||||
}
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_no_speculation[] = {
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CEDARVIEW, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CLOVERVIEW, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_LINCROFT, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PENWELL, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PINEVIEW, X86_FEATURE_ANY },
|
||||
{ X86_VENDOR_CENTAUR, 5 },
|
||||
{ X86_VENDOR_INTEL, 5 },
|
||||
{ X86_VENDOR_NSC, 5 },
|
||||
{ X86_VENDOR_ANY, 4 },
|
||||
{}
|
||||
};
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_no_meltdown[] = {
|
||||
{ X86_VENDOR_AMD },
|
||||
{}
|
||||
};
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = {
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PINEVIEW },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_LINCROFT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PENWELL },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CLOVERVIEW },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CEDARVIEW },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
|
||||
{ X86_VENDOR_CENTAUR, 5, },
|
||||
{ X86_VENDOR_INTEL, 5, },
|
||||
{ X86_VENDOR_NSC, 5, },
|
||||
{ X86_VENDOR_AMD, 0x12, },
|
||||
{ X86_VENDOR_AMD, 0x11, },
|
||||
{ X86_VENDOR_AMD, 0x10, },
|
||||
{ X86_VENDOR_AMD, 0xf, },
|
||||
{ X86_VENDOR_ANY, 4, },
|
||||
{}
|
||||
};
|
||||
|
||||
static const __initconst struct x86_cpu_id cpu_no_l1tf[] = {
|
||||
/* in addition to cpu_no_speculation */
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MOOREFIELD },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GEMINI_LAKE },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
|
||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
|
||||
{}
|
||||
};
|
||||
|
||||
static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 ia32_cap = 0;
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_ARCH_CAPABILITIES))
|
||||
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
|
||||
|
||||
if (!x86_match_cpu(cpu_no_spec_store_bypass) &&
|
||||
!(ia32_cap & ARCH_CAP_SSB_NO))
|
||||
setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
|
||||
|
||||
if (x86_match_cpu(cpu_no_speculation))
|
||||
return;
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
|
||||
|
||||
if (x86_match_cpu(cpu_no_meltdown))
|
||||
return;
|
||||
|
||||
/* Rogue Data Cache Load? No! */
|
||||
if (ia32_cap & ARCH_CAP_RDCL_NO)
|
||||
return;
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
|
||||
|
||||
if (x86_match_cpu(cpu_no_l1tf))
|
||||
return;
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_L1TF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do minimum CPU detection early.
|
||||
* Fields really needed: vendor, cpuid_level, family, model, mask,
|
||||
|
|
@ -839,11 +973,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
|
|||
|
||||
setup_force_cpu_cap(X86_FEATURE_ALWAYS);
|
||||
|
||||
if (c->x86_vendor != X86_VENDOR_AMD)
|
||||
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
|
||||
cpu_set_bug_bits(c);
|
||||
|
||||
fpu__init_system(c);
|
||||
|
||||
|
|
@ -1132,6 +1262,7 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
|
|||
enable_sep_cpu();
|
||||
#endif
|
||||
mtrr_ap_init();
|
||||
x86_spec_ctrl_setup_ap();
|
||||
}
|
||||
|
||||
struct msr_range {
|
||||
|
|
|
|||
|
|
@ -46,4 +46,7 @@ extern const struct cpu_dev *const __x86_cpu_dev_start[],
|
|||
|
||||
extern void get_cpu_cap(struct cpuinfo_x86 *c);
|
||||
extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
|
||||
|
||||
extern void x86_spec_ctrl_setup_ap(void);
|
||||
|
||||
#endif /* ARCH_X86_CPU_H */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <asm/msr.h>
|
||||
#include <asm/bugs.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/intel-family.h>
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#include <linux/topology.h>
|
||||
|
|
@ -25,6 +26,65 @@
|
|||
#include <asm/apic.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Early microcode releases for the Spectre v2 mitigation were broken.
|
||||
* Information taken from;
|
||||
* - https://newsroom.intel.com/wp-content/uploads/sites/11/2018/03/microcode-update-guidance.pdf
|
||||
* - https://kb.vmware.com/s/article/52345
|
||||
* - Microcode revisions observed in the wild
|
||||
* - Release note from 20180108 microcode release
|
||||
*/
|
||||
struct sku_microcode {
|
||||
u8 model;
|
||||
u8 stepping;
|
||||
u32 microcode;
|
||||
};
|
||||
static const struct sku_microcode spectre_bad_microcodes[] = {
|
||||
{ INTEL_FAM6_KABYLAKE_DESKTOP, 0x0B, 0x80 },
|
||||
{ INTEL_FAM6_KABYLAKE_DESKTOP, 0x0A, 0x80 },
|
||||
{ INTEL_FAM6_KABYLAKE_DESKTOP, 0x09, 0x80 },
|
||||
{ INTEL_FAM6_KABYLAKE_MOBILE, 0x0A, 0x80 },
|
||||
{ INTEL_FAM6_KABYLAKE_MOBILE, 0x09, 0x80 },
|
||||
{ INTEL_FAM6_SKYLAKE_X, 0x03, 0x0100013e },
|
||||
{ INTEL_FAM6_SKYLAKE_X, 0x04, 0x0200003c },
|
||||
{ INTEL_FAM6_BROADWELL_CORE, 0x04, 0x28 },
|
||||
{ INTEL_FAM6_BROADWELL_GT3E, 0x01, 0x1b },
|
||||
{ INTEL_FAM6_BROADWELL_XEON_D, 0x02, 0x14 },
|
||||
{ INTEL_FAM6_BROADWELL_XEON_D, 0x03, 0x07000011 },
|
||||
{ INTEL_FAM6_BROADWELL_X, 0x01, 0x0b000025 },
|
||||
{ INTEL_FAM6_HASWELL_ULT, 0x01, 0x21 },
|
||||
{ INTEL_FAM6_HASWELL_GT3E, 0x01, 0x18 },
|
||||
{ INTEL_FAM6_HASWELL_CORE, 0x03, 0x23 },
|
||||
{ INTEL_FAM6_HASWELL_X, 0x02, 0x3b },
|
||||
{ INTEL_FAM6_HASWELL_X, 0x04, 0x10 },
|
||||
{ INTEL_FAM6_IVYBRIDGE_X, 0x04, 0x42a },
|
||||
/* Observed in the wild */
|
||||
{ INTEL_FAM6_SANDYBRIDGE_X, 0x06, 0x61b },
|
||||
{ INTEL_FAM6_SANDYBRIDGE_X, 0x07, 0x712 },
|
||||
};
|
||||
|
||||
static bool bad_spectre_microcode(struct cpuinfo_x86 *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We know that the hypervisor lie to us on the microcode version so
|
||||
* we may as well hope that it is running the correct version.
|
||||
*/
|
||||
if (cpu_has(c, X86_FEATURE_HYPERVISOR))
|
||||
return false;
|
||||
|
||||
if (c->x86 != 6)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) {
|
||||
if (c->x86_model == spectre_bad_microcodes[i].model &&
|
||||
c->x86_mask == spectre_bad_microcodes[i].stepping)
|
||||
return (c->microcode <= spectre_bad_microcodes[i].microcode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void early_init_intel(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 misc_enable;
|
||||
|
|
@ -51,6 +111,22 @@ static void early_init_intel(struct cpuinfo_x86 *c)
|
|||
rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
|
||||
}
|
||||
|
||||
/* Now if any of them are set, check the blacklist and clear the lot */
|
||||
if ((cpu_has(c, X86_FEATURE_SPEC_CTRL) ||
|
||||
cpu_has(c, X86_FEATURE_INTEL_STIBP) ||
|
||||
cpu_has(c, X86_FEATURE_IBRS) || cpu_has(c, X86_FEATURE_IBPB) ||
|
||||
cpu_has(c, X86_FEATURE_STIBP)) && bad_spectre_microcode(c)) {
|
||||
pr_warn("Intel Spectre v2 broken microcode detected; disabling Speculation Control\n");
|
||||
setup_clear_cpu_cap(X86_FEATURE_IBRS);
|
||||
setup_clear_cpu_cap(X86_FEATURE_IBPB);
|
||||
setup_clear_cpu_cap(X86_FEATURE_STIBP);
|
||||
setup_clear_cpu_cap(X86_FEATURE_SPEC_CTRL);
|
||||
setup_clear_cpu_cap(X86_FEATURE_MSR_SPEC_CTRL);
|
||||
setup_clear_cpu_cap(X86_FEATURE_INTEL_STIBP);
|
||||
setup_clear_cpu_cap(X86_FEATURE_SSBD);
|
||||
setup_clear_cpu_cap(X86_FEATURE_SPEC_CTRL_SSBD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Atom erratum AAE44/AAF40/AAG38/AAH41:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2294,9 +2294,6 @@ static ssize_t store_int_with_restart(struct device *s,
|
|||
if (check_interval == old_check_interval)
|
||||
return ret;
|
||||
|
||||
if (check_interval < 1)
|
||||
check_interval = 1;
|
||||
|
||||
mutex_lock(&mce_sysfs_mutex);
|
||||
mce_restart();
|
||||
mutex_unlock(&mce_sysfs_mutex);
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *e
|
|||
u64 prev_count, new_count, delta;
|
||||
int shift;
|
||||
|
||||
if (event->hw.idx >= UNCORE_PMC_IDX_FIXED)
|
||||
if (event->hw.idx == UNCORE_PMC_IDX_FIXED)
|
||||
shift = 64 - uncore_fixed_ctr_bits(box);
|
||||
else
|
||||
shift = 64 - uncore_perf_ctr_bits(box);
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ static void nhmex_uncore_msr_enable_event(struct intel_uncore_box *box, struct p
|
|||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
if (hwc->idx >= UNCORE_PMC_IDX_FIXED)
|
||||
if (hwc->idx == UNCORE_PMC_IDX_FIXED)
|
||||
wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0);
|
||||
else if (box->pmu->type->event_mask & NHMEX_PMON_CTL_EN_BIT0)
|
||||
wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
|
||||
|
|
|
|||
26
arch/x86/kernel/irqflags.S
Normal file
26
arch/x86/kernel/irqflags.S
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm-generic/export.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/*
|
||||
* unsigned long native_save_fl(void)
|
||||
*/
|
||||
ENTRY(native_save_fl)
|
||||
pushf
|
||||
pop %_ASM_AX
|
||||
ret
|
||||
ENDPROC(native_save_fl)
|
||||
EXPORT_SYMBOL(native_save_fl)
|
||||
|
||||
/*
|
||||
* void native_restore_fl(unsigned long flags)
|
||||
* %eax/%rdi: flags
|
||||
*/
|
||||
ENTRY(native_restore_fl)
|
||||
push %_ASM_ARG1
|
||||
popf
|
||||
ret
|
||||
ENDPROC(native_restore_fl)
|
||||
EXPORT_SYMBOL(native_restore_fl)
|
||||
|
|
@ -394,7 +394,6 @@ int __copy_instruction(u8 *dest, u8 *src)
|
|||
newdisp = (u8 *) src + (s64) insn.displacement.value - (u8 *) dest;
|
||||
if ((s64) (s32) newdisp != newdisp) {
|
||||
pr_err("Kprobes error: new displacement does not fit into s32 (%llx)\n", newdisp);
|
||||
pr_err("\tSrc: %p, Dest: %p, old disp: %x\n", src, dest, insn.displacement.value);
|
||||
return 0;
|
||||
}
|
||||
disp = (u8 *) dest + insn_offset_displacement(&insn);
|
||||
|
|
@ -610,8 +609,7 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
|
|||
* Raise a BUG or we'll continue in an endless reentering loop
|
||||
* and eventually a stack overflow.
|
||||
*/
|
||||
printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
|
||||
p->addr);
|
||||
pr_err("Unrecoverable kprobe detected.\n");
|
||||
dump_kprobe(p);
|
||||
BUG();
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ static void free_ldt_struct(struct ldt_struct *ldt)
|
|||
* we do not have to muck with descriptors here, that is
|
||||
* done in switch_mm() as needed.
|
||||
*/
|
||||
int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||
int init_new_context_ldt(struct task_struct *tsk, struct mm_struct *mm)
|
||||
{
|
||||
struct ldt_struct *new_ldt;
|
||||
struct mm_struct *old_mm;
|
||||
|
|
@ -160,7 +160,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
|||
*
|
||||
* 64bit: Don't touch the LDT register - we're already in the next thread.
|
||||
*/
|
||||
void destroy_context(struct mm_struct *mm)
|
||||
void destroy_context_ldt(struct mm_struct *mm)
|
||||
{
|
||||
free_ldt_struct(mm->context.ldt);
|
||||
mm->context.ldt = NULL;
|
||||
|
|
|
|||
|
|
@ -97,10 +97,12 @@ unsigned paravirt_patch_call(void *insnbuf,
|
|||
struct branch *b = insnbuf;
|
||||
unsigned long delta = (unsigned long)target - (addr+5);
|
||||
|
||||
if (tgt_clobbers & ~site_clobbers)
|
||||
return len; /* target would clobber too much for this site */
|
||||
if (len < 5)
|
||||
if (len < 5) {
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
WARN_ONCE("Failing to patch indirect CALL in %ps\n", (void *)addr);
|
||||
#endif
|
||||
return len; /* call too long for patch site */
|
||||
}
|
||||
|
||||
b->opcode = 0xe8; /* call */
|
||||
b->delta = delta;
|
||||
|
|
@ -115,8 +117,12 @@ unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
|
|||
struct branch *b = insnbuf;
|
||||
unsigned long delta = (unsigned long)target - (addr+5);
|
||||
|
||||
if (len < 5)
|
||||
if (len < 5) {
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
WARN_ONCE("Failing to patch indirect JMP in %ps\n", (void *)addr);
|
||||
#endif
|
||||
return len; /* call too long for patch site */
|
||||
}
|
||||
|
||||
b->opcode = 0xe9; /* jmp */
|
||||
b->delta = delta;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <asm/tlbflush.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/vm86.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
/*
|
||||
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
|
||||
|
|
@ -116,11 +117,6 @@ void flush_thread(void)
|
|||
fpu__clear(&tsk->thread.fpu);
|
||||
}
|
||||
|
||||
static void hard_disable_TSC(void)
|
||||
{
|
||||
cr4_set_bits(X86_CR4_TSD);
|
||||
}
|
||||
|
||||
void disable_TSC(void)
|
||||
{
|
||||
preempt_disable();
|
||||
|
|
@ -129,15 +125,10 @@ void disable_TSC(void)
|
|||
* Must flip the CPU state synchronously with
|
||||
* TIF_NOTSC in the current running context.
|
||||
*/
|
||||
hard_disable_TSC();
|
||||
cr4_set_bits(X86_CR4_TSD);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static void hard_enable_TSC(void)
|
||||
{
|
||||
cr4_clear_bits(X86_CR4_TSD);
|
||||
}
|
||||
|
||||
static void enable_TSC(void)
|
||||
{
|
||||
preempt_disable();
|
||||
|
|
@ -146,7 +137,7 @@ static void enable_TSC(void)
|
|||
* Must flip the CPU state synchronously with
|
||||
* TIF_NOTSC in the current running context.
|
||||
*/
|
||||
hard_enable_TSC();
|
||||
cr4_clear_bits(X86_CR4_TSD);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
|
|
@ -174,48 +165,199 @@ int set_tsc_mode(unsigned int val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
||||
struct tss_struct *tss)
|
||||
static inline void switch_to_bitmap(struct tss_struct *tss,
|
||||
struct thread_struct *prev,
|
||||
struct thread_struct *next,
|
||||
unsigned long tifp, unsigned long tifn)
|
||||
{
|
||||
struct thread_struct *prev, *next;
|
||||
|
||||
prev = &prev_p->thread;
|
||||
next = &next_p->thread;
|
||||
|
||||
if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^
|
||||
test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) {
|
||||
unsigned long debugctl = get_debugctlmsr();
|
||||
|
||||
debugctl &= ~DEBUGCTLMSR_BTF;
|
||||
if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP))
|
||||
debugctl |= DEBUGCTLMSR_BTF;
|
||||
|
||||
update_debugctlmsr(debugctl);
|
||||
}
|
||||
|
||||
if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
|
||||
test_tsk_thread_flag(next_p, TIF_NOTSC)) {
|
||||
/* prev and next are different */
|
||||
if (test_tsk_thread_flag(next_p, TIF_NOTSC))
|
||||
hard_disable_TSC();
|
||||
else
|
||||
hard_enable_TSC();
|
||||
}
|
||||
|
||||
if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
|
||||
if (tifn & _TIF_IO_BITMAP) {
|
||||
/*
|
||||
* Copy the relevant range of the IO bitmap.
|
||||
* Normally this is 128 bytes or less:
|
||||
*/
|
||||
memcpy(tss->io_bitmap, next->io_bitmap_ptr,
|
||||
max(prev->io_bitmap_max, next->io_bitmap_max));
|
||||
} else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
|
||||
} else if (tifp & _TIF_IO_BITMAP) {
|
||||
/*
|
||||
* Clear any possible leftover bits:
|
||||
*/
|
||||
memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
struct ssb_state {
|
||||
struct ssb_state *shared_state;
|
||||
raw_spinlock_t lock;
|
||||
unsigned int disable_state;
|
||||
unsigned long local_state;
|
||||
};
|
||||
|
||||
#define LSTATE_SSB 0
|
||||
|
||||
static DEFINE_PER_CPU(struct ssb_state, ssb_state);
|
||||
|
||||
void speculative_store_bypass_ht_init(void)
|
||||
{
|
||||
struct ssb_state *st = this_cpu_ptr(&ssb_state);
|
||||
unsigned int this_cpu = smp_processor_id();
|
||||
unsigned int cpu;
|
||||
|
||||
st->local_state = 0;
|
||||
|
||||
/*
|
||||
* Shared state setup happens once on the first bringup
|
||||
* of the CPU. It's not destroyed on CPU hotunplug.
|
||||
*/
|
||||
if (st->shared_state)
|
||||
return;
|
||||
|
||||
raw_spin_lock_init(&st->lock);
|
||||
|
||||
/*
|
||||
* Go over HT siblings and check whether one of them has set up the
|
||||
* shared state pointer already.
|
||||
*/
|
||||
for_each_cpu(cpu, topology_sibling_cpumask(this_cpu)) {
|
||||
if (cpu == this_cpu)
|
||||
continue;
|
||||
|
||||
if (!per_cpu(ssb_state, cpu).shared_state)
|
||||
continue;
|
||||
|
||||
/* Link it to the state of the sibling: */
|
||||
st->shared_state = per_cpu(ssb_state, cpu).shared_state;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* First HT sibling to come up on the core. Link shared state of
|
||||
* the first HT sibling to itself. The siblings on the same core
|
||||
* which come up later will see the shared state pointer and link
|
||||
* themself to the state of this CPU.
|
||||
*/
|
||||
st->shared_state = st;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logic is: First HT sibling enables SSBD for both siblings in the core
|
||||
* and last sibling to disable it, disables it for the whole core. This how
|
||||
* MSR_SPEC_CTRL works in "hardware":
|
||||
*
|
||||
* CORE_SPEC_CTRL = THREAD0_SPEC_CTRL | THREAD1_SPEC_CTRL
|
||||
*/
|
||||
static __always_inline void amd_set_core_ssb_state(unsigned long tifn)
|
||||
{
|
||||
struct ssb_state *st = this_cpu_ptr(&ssb_state);
|
||||
u64 msr = x86_amd_ls_cfg_base;
|
||||
|
||||
if (!static_cpu_has(X86_FEATURE_ZEN)) {
|
||||
msr |= ssbd_tif_to_amd_ls_cfg(tifn);
|
||||
wrmsrl(MSR_AMD64_LS_CFG, msr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tifn & _TIF_SSBD) {
|
||||
/*
|
||||
* Since this can race with prctl(), block reentry on the
|
||||
* same CPU.
|
||||
*/
|
||||
if (__test_and_set_bit(LSTATE_SSB, &st->local_state))
|
||||
return;
|
||||
|
||||
msr |= x86_amd_ls_cfg_ssbd_mask;
|
||||
|
||||
raw_spin_lock(&st->shared_state->lock);
|
||||
/* First sibling enables SSBD: */
|
||||
if (!st->shared_state->disable_state)
|
||||
wrmsrl(MSR_AMD64_LS_CFG, msr);
|
||||
st->shared_state->disable_state++;
|
||||
raw_spin_unlock(&st->shared_state->lock);
|
||||
} else {
|
||||
if (!__test_and_clear_bit(LSTATE_SSB, &st->local_state))
|
||||
return;
|
||||
|
||||
raw_spin_lock(&st->shared_state->lock);
|
||||
st->shared_state->disable_state--;
|
||||
if (!st->shared_state->disable_state)
|
||||
wrmsrl(MSR_AMD64_LS_CFG, msr);
|
||||
raw_spin_unlock(&st->shared_state->lock);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static __always_inline void amd_set_core_ssb_state(unsigned long tifn)
|
||||
{
|
||||
u64 msr = x86_amd_ls_cfg_base | ssbd_tif_to_amd_ls_cfg(tifn);
|
||||
|
||||
wrmsrl(MSR_AMD64_LS_CFG, msr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static __always_inline void amd_set_ssb_virt_state(unsigned long tifn)
|
||||
{
|
||||
/*
|
||||
* SSBD has the same definition in SPEC_CTRL and VIRT_SPEC_CTRL,
|
||||
* so ssbd_tif_to_spec_ctrl() just works.
|
||||
*/
|
||||
wrmsrl(MSR_AMD64_VIRT_SPEC_CTRL, ssbd_tif_to_spec_ctrl(tifn));
|
||||
}
|
||||
|
||||
static __always_inline void intel_set_ssb_state(unsigned long tifn)
|
||||
{
|
||||
u64 msr = x86_spec_ctrl_base | ssbd_tif_to_spec_ctrl(tifn);
|
||||
|
||||
wrmsrl(MSR_IA32_SPEC_CTRL, msr);
|
||||
}
|
||||
|
||||
static __always_inline void __speculative_store_bypass_update(unsigned long tifn)
|
||||
{
|
||||
if (static_cpu_has(X86_FEATURE_VIRT_SSBD))
|
||||
amd_set_ssb_virt_state(tifn);
|
||||
else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD))
|
||||
amd_set_core_ssb_state(tifn);
|
||||
else
|
||||
intel_set_ssb_state(tifn);
|
||||
}
|
||||
|
||||
void speculative_store_bypass_update(unsigned long tif)
|
||||
{
|
||||
preempt_disable();
|
||||
__speculative_store_bypass_update(tif);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
||||
struct tss_struct *tss)
|
||||
{
|
||||
struct thread_struct *prev, *next;
|
||||
unsigned long tifp, tifn;
|
||||
|
||||
prev = &prev_p->thread;
|
||||
next = &next_p->thread;
|
||||
|
||||
tifn = READ_ONCE(task_thread_info(next_p)->flags);
|
||||
tifp = READ_ONCE(task_thread_info(prev_p)->flags);
|
||||
switch_to_bitmap(tss, prev, next, tifp, tifn);
|
||||
|
||||
propagate_user_return_notify(prev_p, next_p);
|
||||
|
||||
if ((tifp & _TIF_BLOCKSTEP || tifn & _TIF_BLOCKSTEP) &&
|
||||
arch_has_block_step()) {
|
||||
unsigned long debugctl, msk;
|
||||
|
||||
rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
|
||||
debugctl &= ~DEBUGCTLMSR_BTF;
|
||||
msk = tifn & _TIF_BLOCKSTEP;
|
||||
debugctl |= (msk >> TIF_BLOCKSTEP) << DEBUGCTLMSR_BTF_SHIFT;
|
||||
wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
|
||||
}
|
||||
|
||||
if ((tifp ^ tifn) & _TIF_NOTSC)
|
||||
cr4_toggle_bits(X86_CR4_TSD);
|
||||
|
||||
if ((tifp ^ tifn) & _TIF_SSBD)
|
||||
__speculative_store_bypass_update(tifn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -250,6 +250,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
|
|||
start_thread_common(regs, new_ip, new_sp,
|
||||
__USER_CS, __USER_DS, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(start_thread);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp)
|
||||
|
|
|
|||
|
|
@ -851,6 +851,12 @@ void __init setup_arch(char **cmdline_p)
|
|||
memblock_reserve(__pa_symbol(_text),
|
||||
(unsigned long)__bss_stop - (unsigned long)_text);
|
||||
|
||||
/*
|
||||
* Make sure page 0 is always reserved because on systems with
|
||||
* L1TF its contents can be leaked to user processes.
|
||||
*/
|
||||
memblock_reserve(0, PAGE_SIZE);
|
||||
|
||||
early_reserve_initrd();
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@
|
|||
#include <asm/i8259.h>
|
||||
#include <asm/realmode.h>
|
||||
#include <asm/misc.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
/* Number of siblings per CPU package */
|
||||
int smp_num_siblings = 1;
|
||||
|
|
@ -217,6 +218,8 @@ static void notrace start_secondary(void *unused)
|
|||
*/
|
||||
check_tsc_sync_target();
|
||||
|
||||
speculative_store_bypass_ht_init();
|
||||
|
||||
/*
|
||||
* Lock vector_lock and initialize the vectors on this cpu
|
||||
* before setting the cpu online. We must set it online with
|
||||
|
|
@ -1209,6 +1212,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
|
|||
set_mtrr_aps_delayed_init();
|
||||
|
||||
smp_quirk_init_udelay();
|
||||
|
||||
speculative_store_bypass_ht_init();
|
||||
}
|
||||
|
||||
void arch_enable_nonboot_cpus_begin(void)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include <asm/desc.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/kvm_para.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
#include <asm/virtext.h>
|
||||
#include "trace.h"
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
#include <asm/kexec.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/irq_remapping.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
#include "trace.h"
|
||||
#include "pmu.h"
|
||||
|
|
@ -6843,6 +6843,8 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
|
|||
HRTIMER_MODE_REL);
|
||||
vmx->nested.preemption_timer.function = vmx_preemption_timer_fn;
|
||||
|
||||
vmx->nested.vpid02 = allocate_vpid();
|
||||
|
||||
vmx->nested.vmxon = true;
|
||||
|
||||
skip_emulated_instruction(vcpu);
|
||||
|
|
@ -8887,10 +8889,8 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
|
|||
goto free_vmcs;
|
||||
}
|
||||
|
||||
if (nested) {
|
||||
if (nested)
|
||||
nested_vmx_setup_ctls_msrs(vmx);
|
||||
vmx->nested.vpid02 = allocate_vpid();
|
||||
}
|
||||
|
||||
vmx->nested.posted_intr_nv = -1;
|
||||
vmx->nested.current_vmptr = -1ull;
|
||||
|
|
@ -8899,7 +8899,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
|
|||
return &vmx->vcpu;
|
||||
|
||||
free_vmcs:
|
||||
free_vpid(vmx->nested.vpid02);
|
||||
free_loaded_vmcs(vmx->loaded_vmcs);
|
||||
free_msrs:
|
||||
kfree(vmx->guest_msrs);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <linux/swap.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/bootmem.h> /* for max_low_pfn */
|
||||
#include <linux/swapfile.h>
|
||||
#include <linux/swapops.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/e820.h>
|
||||
|
|
@ -767,3 +769,26 @@ void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache)
|
|||
__cachemode2pte_tbl[cache] = __cm_idx2pte(entry);
|
||||
__pte2cachemode_tbl[entry] = cache;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SWAP
|
||||
unsigned long max_swapfile_size(void)
|
||||
{
|
||||
unsigned long pages;
|
||||
|
||||
pages = generic_max_swapfile_size();
|
||||
|
||||
if (boot_cpu_has_bug(X86_BUG_L1TF)) {
|
||||
/* Limit the swap file size to MAX_PA/2 for L1TF workaround */
|
||||
unsigned long long l1tf_limit = l1tf_pfn_limit();
|
||||
/*
|
||||
* We encode swap offsets also with 3 bits below those for pfn
|
||||
* which makes the usable limit higher.
|
||||
*/
|
||||
#if CONFIG_PGTABLE_LEVELS > 2
|
||||
l1tf_limit <<= PAGE_SHIFT - SWP_OFFSET_FIRST_BIT;
|
||||
#endif
|
||||
pages = min_t(unsigned long long, l1tf_limit, pages);
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -125,24 +125,29 @@ static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long addr)
|
|||
|
||||
static void clear_pmd_presence(pmd_t *pmd, bool clear, pmdval_t *old)
|
||||
{
|
||||
pmd_t new_pmd;
|
||||
pmdval_t v = pmd_val(*pmd);
|
||||
if (clear) {
|
||||
*old = v & _PAGE_PRESENT;
|
||||
v &= ~_PAGE_PRESENT;
|
||||
} else /* presume this has been called with clear==true previously */
|
||||
v |= *old;
|
||||
set_pmd(pmd, __pmd(v));
|
||||
*old = v;
|
||||
new_pmd = pmd_mknotpresent(*pmd);
|
||||
} else {
|
||||
/* Presume this has been called with clear==true previously */
|
||||
new_pmd = __pmd(*old);
|
||||
}
|
||||
set_pmd(pmd, new_pmd);
|
||||
}
|
||||
|
||||
static void clear_pte_presence(pte_t *pte, bool clear, pteval_t *old)
|
||||
{
|
||||
pteval_t v = pte_val(*pte);
|
||||
if (clear) {
|
||||
*old = v & _PAGE_PRESENT;
|
||||
v &= ~_PAGE_PRESENT;
|
||||
} else /* presume this has been called with clear==true previously */
|
||||
v |= *old;
|
||||
set_pte_atomic(pte, __pte(v));
|
||||
*old = v;
|
||||
/* Nothing should care about address */
|
||||
pte_clear(&init_mm, 0, pte);
|
||||
} else {
|
||||
/* Presume this has been called with clear==true previously */
|
||||
set_pte_atomic(pte, __pte(*old));
|
||||
}
|
||||
}
|
||||
|
||||
static int clear_page_presence(struct kmmio_fault_page *f, bool clear)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user