Merge branch 'ib/4.17-xen-kbdfront-runtime-config' into next
Bring in xen-kbdfront changes.
This commit is contained in:
commit
5aff29efbe
|
@ -478,6 +478,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
|
||||
|
|
|
@ -2680,6 +2680,9 @@
|
|||
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.
|
||||
|
@ -4025,6 +4028,48 @@
|
|||
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=
|
||||
|
|
|
@ -10,6 +10,7 @@ Required properties:
|
|||
"brcm,bcm53128"
|
||||
"brcm,bcm5365"
|
||||
"brcm,bcm5395"
|
||||
"brcm,bcm5389"
|
||||
"brcm,bcm5397"
|
||||
"brcm,bcm5398"
|
||||
|
||||
|
|
|
@ -57,6 +57,13 @@ KSZ9031:
|
|||
- txd2-skew-ps : Skew control of TX data 2 pad
|
||||
- txd3-skew-ps : Skew control of TX data 3 pad
|
||||
|
||||
- micrel,force-master:
|
||||
Boolean, force phy to master mode. Only set this option if the phy
|
||||
reference clock provided at CLK125_NDO pin is used as MAC reference
|
||||
clock because the clock jitter in slave mode is to high (errata#2).
|
||||
Attention: The link partner must be configurable as slave otherwise
|
||||
no link will be established.
|
||||
|
||||
Examples:
|
||||
|
||||
mdio {
|
||||
|
|
|
@ -2,7 +2,7 @@ Kernel driver i2c-ocores
|
|||
|
||||
Supported adapters:
|
||||
* OpenCores.org I2C controller by Richard Herveille (see datasheet link)
|
||||
Datasheet: http://www.opencores.org/projects.cgi/web/i2c/overview
|
||||
https://opencores.org/project/i2c/overview
|
||||
|
||||
Author: Peter Korsgaard <jacmet@sunsite.dk>
|
||||
|
||||
|
|
|
@ -300,12 +300,6 @@ unattached instance are:
|
|||
The ioctl calls available on an instance of /dev/ppp attached to a
|
||||
channel are:
|
||||
|
||||
* PPPIOCDETACH detaches the instance from the channel. This ioctl is
|
||||
deprecated since the same effect can be achieved by closing the
|
||||
instance. In order to prevent possible races this ioctl will fail
|
||||
with an EINVAL error if more than one file descriptor refers to this
|
||||
instance (i.e. as a result of dup(), dup2() or fork()).
|
||||
|
||||
* PPPIOCCONNECT connects this channel to a PPP interface. The
|
||||
argument should point to an int containing the interface unit
|
||||
number. It will return an EINVAL error if the channel is already
|
||||
|
|
|
@ -19,6 +19,7 @@ place where this information is gathered.
|
|||
no_new_privs
|
||||
seccomp_filter
|
||||
unshare
|
||||
spec_ctrl
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
|
|
@ -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);
|
30
MAINTAINERS
30
MAINTAINERS
|
@ -2332,7 +2332,7 @@ F: drivers/gpio/gpio-ath79.c
|
|||
F: Documentation/devicetree/bindings/gpio/gpio-ath79.txt
|
||||
|
||||
ATHEROS ATH GENERIC UTILITIES
|
||||
M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
|
||||
M: Kalle Valo <kvalo@codeaurora.org>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/wireless/ath/*
|
||||
|
@ -2347,7 +2347,7 @@ S: Maintained
|
|||
F: drivers/net/wireless/ath/ath5k/
|
||||
|
||||
ATHEROS ATH6KL WIRELESS DRIVER
|
||||
M: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
M: Kalle Valo <kvalo@codeaurora.org>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/ath6kl
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
|
||||
|
@ -5394,7 +5394,6 @@ S: Maintained
|
|||
F: drivers/iommu/exynos-iommu.c
|
||||
|
||||
EZchip NPS platform support
|
||||
M: Elad Kanfi <eladkan@mellanox.com>
|
||||
M: Vineet Gupta <vgupta@synopsys.com>
|
||||
S: Supported
|
||||
F: arch/arc/plat-eznps
|
||||
|
@ -6510,9 +6509,15 @@ F: Documentation/networking/hinic.txt
|
|||
F: drivers/net/ethernet/huawei/hinic/
|
||||
|
||||
HUGETLB FILESYSTEM
|
||||
M: Nadia Yvette Chambers <nyc@holomorphy.com>
|
||||
M: Mike Kravetz <mike.kravetz@oracle.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: fs/hugetlbfs/
|
||||
F: mm/hugetlb.c
|
||||
F: include/linux/hugetlb.h
|
||||
F: Documentation/admin-guide/mm/hugetlbpage.rst
|
||||
F: Documentation/vm/hugetlbfs_reserv.rst
|
||||
F: Documentation/ABI/testing/sysfs-kernel-mm-hugepages
|
||||
|
||||
HVA ST MEDIA DRIVER
|
||||
M: Jean-Christophe Trotin <jean-christophe.trotin@st.com>
|
||||
|
@ -9027,7 +9032,6 @@ Q: http://patchwork.ozlabs.org/project/netdev/list/
|
|||
F: drivers/net/ethernet/mellanox/mlx5/core/en_*
|
||||
|
||||
MELLANOX ETHERNET INNOVA DRIVER
|
||||
M: Ilan Tayari <ilant@mellanox.com>
|
||||
R: Boris Pismenny <borisp@mellanox.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
@ -9037,7 +9041,6 @@ F: drivers/net/ethernet/mellanox/mlx5/core/fpga/*
|
|||
F: include/linux/mlx5/mlx5_ifc_fpga.h
|
||||
|
||||
MELLANOX ETHERNET INNOVA IPSEC DRIVER
|
||||
M: Ilan Tayari <ilant@mellanox.com>
|
||||
R: Boris Pismenny <borisp@mellanox.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
@ -9093,7 +9096,6 @@ F: include/uapi/rdma/mlx4-abi.h
|
|||
|
||||
MELLANOX MLX5 core VPI driver
|
||||
M: Saeed Mahameed <saeedm@mellanox.com>
|
||||
M: Matan Barak <matanb@mellanox.com>
|
||||
M: Leon Romanovsky <leonro@mellanox.com>
|
||||
L: netdev@vger.kernel.org
|
||||
L: linux-rdma@vger.kernel.org
|
||||
|
@ -9104,7 +9106,6 @@ F: drivers/net/ethernet/mellanox/mlx5/core/
|
|||
F: include/linux/mlx5/
|
||||
|
||||
MELLANOX MLX5 IB driver
|
||||
M: Matan Barak <matanb@mellanox.com>
|
||||
M: Leon Romanovsky <leonro@mellanox.com>
|
||||
L: linux-rdma@vger.kernel.org
|
||||
W: http://www.mellanox.com
|
||||
|
@ -9838,7 +9839,6 @@ F: net/netfilter/xt_CONNSECMARK.c
|
|||
F: net/netfilter/xt_SECMARK.c
|
||||
|
||||
NETWORKING [TLS]
|
||||
M: Ilya Lesokhin <ilyal@mellanox.com>
|
||||
M: Aviad Yehezkel <aviadye@mellanox.com>
|
||||
M: Dave Watson <davejwatson@fb.com>
|
||||
L: netdev@vger.kernel.org
|
||||
|
@ -11638,7 +11638,7 @@ S: Maintained
|
|||
F: drivers/media/tuners/qt1010*
|
||||
|
||||
QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
|
||||
M: Kalle Valo <kvalo@qca.qualcomm.com>
|
||||
M: Kalle Valo <kvalo@codeaurora.org>
|
||||
L: ath10k@lists.infradead.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/ath10k
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
|
||||
|
@ -11689,7 +11689,7 @@ S: Maintained
|
|||
F: drivers/media/platform/qcom/venus/
|
||||
|
||||
QUALCOMM WCN36XX WIRELESS DRIVER
|
||||
M: Eugene Krasnikov <k.eugene.e@gmail.com>
|
||||
M: Kalle Valo <kvalo@codeaurora.org>
|
||||
L: wcn36xx@lists.infradead.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/wcn36xx
|
||||
T: git git://github.com/KrasnikovEugene/wcn36xx.git
|
||||
|
@ -15519,6 +15519,14 @@ L: linux-kernel@vger.kernel.org
|
|||
S: Supported
|
||||
F: drivers/char/xillybus/
|
||||
|
||||
XLP9XX I2C DRIVER
|
||||
M: George Cherian <george.cherian@cavium.com>
|
||||
M: Jan Glauber <jglauber@cavium.com>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
W: http://www.cavium.com
|
||||
S: Supported
|
||||
F: drivers/i2c/busses/i2c-xlp9xx.c
|
||||
|
||||
XRA1403 GPIO EXPANDER
|
||||
M: Nandor Han <nandor.han@ge.com>
|
||||
M: Semi Malinen <semi.malinen@ge.com>
|
||||
|
|
11
Makefile
11
Makefile
|
@ -2,7 +2,7 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 17
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION =
|
||||
NAME = Merciless Moray
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -500,6 +500,9 @@ RETPOLINE_CFLAGS_CLANG := -mretpoline-external-thunk
|
|||
RETPOLINE_CFLAGS := $(call cc-option,$(RETPOLINE_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_CFLAGS_CLANG)))
|
||||
export RETPOLINE_CFLAGS
|
||||
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
|
||||
KBUILD_AFLAGS += $(call cc-option,-fno-PIE)
|
||||
|
||||
# check for 'asm goto'
|
||||
ifeq ($(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
|
||||
CC_HAVE_ASM_GOTO := 1
|
||||
|
@ -621,9 +624,9 @@ endif # $(dot-config)
|
|||
# Defaults to vmlinux, but the arch makefile usually adds further targets
|
||||
all: vmlinux
|
||||
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
|
||||
KBUILD_AFLAGS += $(call cc-option,-fno-PIE)
|
||||
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage -fno-tree-loop-im $(call cc-disable-warning,maybe-uninitialized,)
|
||||
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage \
|
||||
$(call cc-option,-fno-tree-loop-im) \
|
||||
$(call cc-disable-warning,maybe-uninitialized,)
|
||||
export CFLAGS_GCOV CFLAGS_KCOV
|
||||
|
||||
# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
|
||||
|
|
|
@ -211,6 +211,7 @@ config ALPHA_EIGER
|
|||
config ALPHA_JENSEN
|
||||
bool "Jensen"
|
||||
depends on BROKEN
|
||||
select DMA_DIRECT_OPS
|
||||
help
|
||||
DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one
|
||||
of the first-generation Alpha systems. A number of these systems
|
||||
|
|
|
@ -2,11 +2,15 @@
|
|||
#ifndef _ALPHA_DMA_MAPPING_H
|
||||
#define _ALPHA_DMA_MAPPING_H
|
||||
|
||||
extern const struct dma_map_ops *dma_ops;
|
||||
extern const struct dma_map_ops alpha_pci_ops;
|
||||
|
||||
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
|
||||
{
|
||||
return dma_ops;
|
||||
#ifdef CONFIG_ALPHA_JENSEN
|
||||
return &dma_direct_ops;
|
||||
#else
|
||||
return &alpha_pci_ops;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ALPHA_DMA_MAPPING_H */
|
||||
|
|
|
@ -37,20 +37,20 @@ unsigned int ioread32(void __iomem *addr)
|
|||
|
||||
void iowrite8(u8 b, void __iomem *addr)
|
||||
{
|
||||
IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
|
||||
mb();
|
||||
IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
|
||||
}
|
||||
|
||||
void iowrite16(u16 b, void __iomem *addr)
|
||||
{
|
||||
IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
|
||||
mb();
|
||||
IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
|
||||
}
|
||||
|
||||
void iowrite32(u32 b, void __iomem *addr)
|
||||
{
|
||||
IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
|
||||
mb();
|
||||
IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ioread8);
|
||||
|
@ -176,26 +176,26 @@ u64 readq(const volatile void __iomem *addr)
|
|||
|
||||
void writeb(u8 b, volatile void __iomem *addr)
|
||||
{
|
||||
__raw_writeb(b, addr);
|
||||
mb();
|
||||
__raw_writeb(b, addr);
|
||||
}
|
||||
|
||||
void writew(u16 b, volatile void __iomem *addr)
|
||||
{
|
||||
__raw_writew(b, addr);
|
||||
mb();
|
||||
__raw_writew(b, addr);
|
||||
}
|
||||
|
||||
void writel(u32 b, volatile void __iomem *addr)
|
||||
{
|
||||
__raw_writel(b, addr);
|
||||
mb();
|
||||
__raw_writel(b, addr);
|
||||
}
|
||||
|
||||
void writeq(u64 b, volatile void __iomem *addr)
|
||||
{
|
||||
__raw_writeq(b, addr);
|
||||
mb();
|
||||
__raw_writeq(b, addr);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(readb);
|
||||
|
|
|
@ -102,36 +102,3 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
|
|||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void *alpha_noop_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t gfp,
|
||||
unsigned long attrs)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (!dev || *dev->dma_mask >= 0xffffffffUL)
|
||||
gfp &= ~GFP_DMA;
|
||||
ret = (void *)__get_free_pages(gfp, get_order(size));
|
||||
if (ret) {
|
||||
memset(ret, 0, size);
|
||||
*dma_handle = virt_to_phys(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int alpha_noop_supported(struct device *dev, u64 mask)
|
||||
{
|
||||
return mask < 0x00ffffffUL ? 0 : 1;
|
||||
}
|
||||
|
||||
const struct dma_map_ops alpha_noop_ops = {
|
||||
.alloc = alpha_noop_alloc_coherent,
|
||||
.free = dma_noop_free_coherent,
|
||||
.map_page = dma_noop_map_page,
|
||||
.map_sg = dma_noop_map_sg,
|
||||
.mapping_error = dma_noop_mapping_error,
|
||||
.dma_supported = alpha_noop_supported,
|
||||
};
|
||||
|
||||
const struct dma_map_ops *dma_ops = &alpha_noop_ops;
|
||||
EXPORT_SYMBOL(dma_ops);
|
||||
|
|
|
@ -950,6 +950,4 @@ const struct dma_map_ops alpha_pci_ops = {
|
|||
.mapping_error = alpha_pci_mapping_error,
|
||||
.dma_supported = alpha_pci_supported,
|
||||
};
|
||||
|
||||
const struct dma_map_ops *dma_ops = &alpha_pci_ops;
|
||||
EXPORT_SYMBOL(dma_ops);
|
||||
EXPORT_SYMBOL(alpha_pci_ops);
|
||||
|
|
|
@ -76,7 +76,7 @@ framebuffer-fe0-lcd0-hdmi {
|
|||
allwinner,pipeline = "de_fe0-de_be0-lcd0-hdmi";
|
||||
clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_HDMI0>,
|
||||
<&ccu CLK_AHB_DE_BE0>, <&ccu CLK_AHB_DE_FE0>,
|
||||
<&ccu CLK_DE_BE0>, <&ccu CLK_AHB_DE_FE0>,
|
||||
<&ccu CLK_DE_BE0>, <&ccu CLK_DE_FE0>,
|
||||
<&ccu CLK_TCON0_CH1>, <&ccu CLK_HDMI>,
|
||||
<&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>;
|
||||
status = "disabled";
|
||||
|
@ -88,7 +88,7 @@ framebuffer-fe0-lcd0 {
|
|||
allwinner,pipeline = "de_fe0-de_be0-lcd0";
|
||||
clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_DE_BE0>,
|
||||
<&ccu CLK_AHB_DE_FE0>, <&ccu CLK_DE_BE0>,
|
||||
<&ccu CLK_AHB_DE_FE0>, <&ccu CLK_TCON0_CH0>,
|
||||
<&ccu CLK_DE_FE0>, <&ccu CLK_TCON0_CH0>,
|
||||
<&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -99,7 +99,7 @@ framebuffer-fe0-lcd0-tve0 {
|
|||
allwinner,pipeline = "de_fe0-de_be0-lcd0-tve0";
|
||||
clocks = <&ccu CLK_AHB_TVE0>, <&ccu CLK_AHB_LCD0>,
|
||||
<&ccu CLK_AHB_DE_BE0>, <&ccu CLK_AHB_DE_FE0>,
|
||||
<&ccu CLK_DE_BE0>, <&ccu CLK_AHB_DE_FE0>,
|
||||
<&ccu CLK_DE_BE0>, <&ccu CLK_DE_FE0>,
|
||||
<&ccu CLK_TCON0_CH1>, <&ccu CLK_DRAM_TVE0>,
|
||||
<&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -117,6 +117,7 @@ &emac {
|
|||
phy-handle = <&int_mii_phy>;
|
||||
phy-mode = "mii";
|
||||
allwinner,leds-active-low;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
|
|
|
@ -51,7 +51,7 @@ / {
|
|||
|
||||
leds {
|
||||
/* The LEDs use PG0~2 pins, which conflict with MMC1 */
|
||||
status = "disbaled";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
|
|||
|
||||
/* All EP93xx devices use the same two GPIO pins for I2C bit-banging */
|
||||
static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
/* Use local offsets on gpiochip/port "G" */
|
||||
GPIO_LOOKUP_IDX("G", 1, NULL, 0,
|
||||
|
|
|
@ -51,7 +51,7 @@ static struct platform_device avila_flash = {
|
|||
};
|
||||
|
||||
static struct gpiod_lookup_table avila_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", AVILA_SDA_PIN,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -70,7 +70,7 @@ static struct platform_device dsmg600_flash = {
|
|||
};
|
||||
|
||||
static struct gpiod_lookup_table dsmg600_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", DSMG600_SDA_PIN,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -56,7 +56,7 @@ static struct platform_device fsg_flash = {
|
|||
};
|
||||
|
||||
static struct gpiod_lookup_table fsg_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", FSG_SDA_PIN,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -124,7 +124,7 @@ static struct platform_device ixdp425_flash_nand = {
|
|||
#endif /* CONFIG_MTD_NAND_PLATFORM */
|
||||
|
||||
static struct gpiod_lookup_table ixdp425_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", IXDP425_SDA_PIN,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -102,7 +102,7 @@ static struct platform_device nas100d_leds = {
|
|||
};
|
||||
|
||||
static struct gpiod_lookup_table nas100d_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NAS100D_SDA_PIN,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -70,7 +70,7 @@ static struct platform_device nslu2_flash = {
|
|||
};
|
||||
|
||||
static struct gpiod_lookup_table nslu2_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NSLU2_SDA_PIN,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -322,7 +322,7 @@ static struct soc_camera_link palmz72_iclink = {
|
|||
};
|
||||
|
||||
static struct gpiod_lookup_table palmz72_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("gpio-pxa", 118, NULL, 0,
|
||||
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -460,7 +460,7 @@ static struct platform_device smc91x_device = {
|
|||
|
||||
/* i2c */
|
||||
static struct gpiod_lookup_table viper_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.1",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("gpio-pxa", VIPER_RTC_I2C_SDA_GPIO,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
@ -789,7 +789,7 @@ static int __init viper_tpm_setup(char *str)
|
|||
__setup("tpm=", viper_tpm_setup);
|
||||
|
||||
struct gpiod_lookup_table viper_tpm_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.2",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("gpio-pxa", VIPER_TPM_I2C_SDA_GPIO,
|
||||
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -327,7 +327,7 @@ static struct platform_device simpad_gpio_leds = {
|
|||
* i2c
|
||||
*/
|
||||
static struct gpiod_lookup_table simpad_i2c_gpiod_table = {
|
||||
.dev_id = "i2c-gpio",
|
||||
.dev_id = "i2c-gpio.0",
|
||||
.table = {
|
||||
GPIO_LOOKUP_IDX("gpio", 21, NULL, 0,
|
||||
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
|
||||
|
|
|
@ -466,12 +466,6 @@ void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
|
|||
void __init dma_contiguous_remap(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dma_mmu_remap_num)
|
||||
return;
|
||||
|
||||
/* call flush_cache_all() since CMA area would be large enough */
|
||||
flush_cache_all();
|
||||
for (i = 0; i < dma_mmu_remap_num; i++) {
|
||||
phys_addr_t start = dma_mmu_remap[i].base;
|
||||
phys_addr_t end = start + dma_mmu_remap[i].size;
|
||||
|
@ -504,15 +498,7 @@ void __init dma_contiguous_remap(void)
|
|||
flush_tlb_kernel_range(__phys_to_virt(start),
|
||||
__phys_to_virt(end));
|
||||
|
||||
/*
|
||||
* All the memory in CMA region will be on ZONE_MOVABLE.
|
||||
* If that zone is considered as highmem, the memory in CMA
|
||||
* region is also considered as highmem even if it's
|
||||
* physical address belong to lowmem. In this case,
|
||||
* re-mapping isn't required.
|
||||
*/
|
||||
if (!is_highmem_idx(ZONE_MOVABLE))
|
||||
iotable_init(&map, 1);
|
||||
iotable_init(&map, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -299,7 +299,6 @@ gpio15: gpio@f702b000 {
|
|||
/* GPIO blocks 16 thru 19 do not appear to be routed to pins */
|
||||
|
||||
dwmmc_0: dwmmc0@f723d000 {
|
||||
max-frequency = <150000000>;
|
||||
cap-mmc-highspeed;
|
||||
mmc-hs200-1_8v;
|
||||
non-removable;
|
||||
|
|
|
@ -117,7 +117,7 @@ static inline void atomic_and(int i, atomic_t *v)
|
|||
/* LSE atomics */
|
||||
" mvn %w[i], %w[i]\n"
|
||||
" stclr %w[i], %[v]")
|
||||
: [i] "+r" (w0), [v] "+Q" (v->counter)
|
||||
: [i] "+&r" (w0), [v] "+Q" (v->counter)
|
||||
: "r" (x1)
|
||||
: __LL_SC_CLOBBERS);
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ static inline int atomic_fetch_and##name(int i, atomic_t *v) \
|
|||
/* LSE atomics */ \
|
||||
" mvn %w[i], %w[i]\n" \
|
||||
" ldclr" #mb " %w[i], %w[i], %[v]") \
|
||||
: [i] "+r" (w0), [v] "+Q" (v->counter) \
|
||||
: [i] "+&r" (w0), [v] "+Q" (v->counter) \
|
||||
: "r" (x1) \
|
||||
: __LL_SC_CLOBBERS, ##cl); \
|
||||
\
|
||||
|
@ -161,7 +161,7 @@ static inline void atomic_sub(int i, atomic_t *v)
|
|||
/* LSE atomics */
|
||||
" neg %w[i], %w[i]\n"
|
||||
" stadd %w[i], %[v]")
|
||||
: [i] "+r" (w0), [v] "+Q" (v->counter)
|
||||
: [i] "+&r" (w0), [v] "+Q" (v->counter)
|
||||
: "r" (x1)
|
||||
: __LL_SC_CLOBBERS);
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ static inline int atomic_sub_return##name(int i, atomic_t *v) \
|
|||
" neg %w[i], %w[i]\n" \
|
||||
" ldadd" #mb " %w[i], w30, %[v]\n" \
|
||||
" add %w[i], %w[i], w30") \
|
||||
: [i] "+r" (w0), [v] "+Q" (v->counter) \
|
||||
: [i] "+&r" (w0), [v] "+Q" (v->counter) \
|
||||
: "r" (x1) \
|
||||
: __LL_SC_CLOBBERS , ##cl); \
|
||||
\
|
||||
|
@ -207,7 +207,7 @@ static inline int atomic_fetch_sub##name(int i, atomic_t *v) \
|
|||
/* LSE atomics */ \
|
||||
" neg %w[i], %w[i]\n" \
|
||||
" ldadd" #mb " %w[i], %w[i], %[v]") \
|
||||
: [i] "+r" (w0), [v] "+Q" (v->counter) \
|
||||
: [i] "+&r" (w0), [v] "+Q" (v->counter) \
|
||||
: "r" (x1) \
|
||||
: __LL_SC_CLOBBERS, ##cl); \
|
||||
\
|
||||
|
@ -314,7 +314,7 @@ static inline void atomic64_and(long i, atomic64_t *v)
|
|||
/* LSE atomics */
|
||||
" mvn %[i], %[i]\n"
|
||||
" stclr %[i], %[v]")
|
||||
: [i] "+r" (x0), [v] "+Q" (v->counter)
|
||||
: [i] "+&r" (x0), [v] "+Q" (v->counter)
|
||||
: "r" (x1)
|
||||
: __LL_SC_CLOBBERS);
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ static inline long atomic64_fetch_and##name(long i, atomic64_t *v) \
|
|||
/* LSE atomics */ \
|
||||
" mvn %[i], %[i]\n" \
|
||||
" ldclr" #mb " %[i], %[i], %[v]") \
|
||||
: [i] "+r" (x0), [v] "+Q" (v->counter) \
|
||||
: [i] "+&r" (x0), [v] "+Q" (v->counter) \
|
||||
: "r" (x1) \
|
||||
: __LL_SC_CLOBBERS, ##cl); \
|
||||
\
|
||||
|
@ -358,7 +358,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)
|
|||
/* LSE atomics */
|
||||
" neg %[i], %[i]\n"
|
||||
" stadd %[i], %[v]")
|
||||
: [i] "+r" (x0), [v] "+Q" (v->counter)
|
||||
: [i] "+&r" (x0), [v] "+Q" (v->counter)
|
||||
: "r" (x1)
|
||||
: __LL_SC_CLOBBERS);
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ static inline long atomic64_sub_return##name(long i, atomic64_t *v) \
|
|||
" neg %[i], %[i]\n" \
|
||||
" ldadd" #mb " %[i], x30, %[v]\n" \
|
||||
" add %[i], %[i], x30") \
|
||||
: [i] "+r" (x0), [v] "+Q" (v->counter) \
|
||||
: [i] "+&r" (x0), [v] "+Q" (v->counter) \
|
||||
: "r" (x1) \
|
||||
: __LL_SC_CLOBBERS, ##cl); \
|
||||
\
|
||||
|
@ -404,7 +404,7 @@ static inline long atomic64_fetch_sub##name(long i, atomic64_t *v) \
|
|||
/* LSE atomics */ \
|
||||
" neg %[i], %[i]\n" \
|
||||
" ldadd" #mb " %[i], %[i], %[v]") \
|
||||
: [i] "+r" (x0), [v] "+Q" (v->counter) \
|
||||
: [i] "+&r" (x0), [v] "+Q" (v->counter) \
|
||||
: "r" (x1) \
|
||||
: __LL_SC_CLOBBERS, ##cl); \
|
||||
\
|
||||
|
@ -435,7 +435,7 @@ static inline long atomic64_dec_if_positive(atomic64_t *v)
|
|||
" sub x30, x30, %[ret]\n"
|
||||
" cbnz x30, 1b\n"
|
||||
"2:")
|
||||
: [ret] "+r" (x0), [v] "+Q" (v->counter)
|
||||
: [ret] "+&r" (x0), [v] "+Q" (v->counter)
|
||||
:
|
||||
: __LL_SC_CLOBBERS, "cc", "memory");
|
||||
|
||||
|
@ -516,7 +516,7 @@ static inline long __cmpxchg_double##name(unsigned long old1, \
|
|||
" eor %[old1], %[old1], %[oldval1]\n" \
|
||||
" eor %[old2], %[old2], %[oldval2]\n" \
|
||||
" orr %[old1], %[old1], %[old2]") \
|
||||
: [old1] "+r" (x0), [old2] "+r" (x1), \
|
||||
: [old1] "+&r" (x0), [old2] "+&r" (x1), \
|
||||
[v] "+Q" (*(unsigned long *)ptr) \
|
||||
: [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \
|
||||
[oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \
|
||||
|
|
|
@ -75,3 +75,11 @@ NOKPROBE_SYMBOL(_mcount);
|
|||
/* arm-smccc */
|
||||
EXPORT_SYMBOL(__arm_smccc_smc);
|
||||
EXPORT_SYMBOL(__arm_smccc_hvc);
|
||||
|
||||
/* tishift.S */
|
||||
extern long long __ashlti3(long long a, int b);
|
||||
EXPORT_SYMBOL(__ashlti3);
|
||||
extern long long __ashrti3(long long a, int b);
|
||||
EXPORT_SYMBOL(__ashrti3);
|
||||
extern long long __lshrti3(long long a, int b);
|
||||
EXPORT_SYMBOL(__lshrti3);
|
||||
|
|
|
@ -1,17 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
|
|
@ -293,6 +293,57 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
|
|||
static void __do_user_fault(struct siginfo *info, unsigned int esr)
|
||||
{
|
||||
current->thread.fault_address = (unsigned long)info->si_addr;
|
||||
|
||||
/*
|
||||
* If the faulting address is in the kernel, we must sanitize the ESR.
|
||||
* From userspace's point of view, kernel-only mappings don't exist
|
||||
* at all, so we report them as level 0 translation faults.
|
||||
* (This is not quite the way that "no mapping there at all" behaves:
|
||||
* an alignment fault not caused by the memory type would take
|
||||
* precedence over translation fault for a real access to empty
|
||||
* space. Unfortunately we can't easily distinguish "alignment fault
|
||||
* not caused by memory type" from "alignment fault caused by memory
|
||||
* type", so we ignore this wrinkle and just return the translation
|
||||
* fault.)
|
||||
*/
|
||||
if (current->thread.fault_address >= TASK_SIZE) {
|
||||
switch (ESR_ELx_EC(esr)) {
|
||||
case ESR_ELx_EC_DABT_LOW:
|
||||
/*
|
||||
* These bits provide only information about the
|
||||
* faulting instruction, which userspace knows already.
|
||||
* We explicitly clear bits which are architecturally
|
||||
* RES0 in case they are given meanings in future.
|
||||
* We always report the ESR as if the fault was taken
|
||||
* to EL1 and so ISV and the bits in ISS[23:14] are
|
||||
* clear. (In fact it always will be a fault to EL1.)
|
||||
*/
|
||||
esr &= ESR_ELx_EC_MASK | ESR_ELx_IL |
|
||||
ESR_ELx_CM | ESR_ELx_WNR;
|
||||
esr |= ESR_ELx_FSC_FAULT;
|
||||
break;
|
||||
case ESR_ELx_EC_IABT_LOW:
|
||||
/*
|
||||
* Claim a level 0 translation fault.
|
||||
* All other bits are architecturally RES0 for faults
|
||||
* reported with that DFSC value, so we clear them.
|
||||
*/
|
||||
esr &= ESR_ELx_EC_MASK | ESR_ELx_IL;
|
||||
esr |= ESR_ELx_FSC_FAULT;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* This should never happen (entry.S only brings us
|
||||
* into this code for insn and data aborts from a lower
|
||||
* exception level). Fail safe by not providing an ESR
|
||||
* context record at all.
|
||||
*/
|
||||
WARN(1, "ESR 0x%x is not DABT or IABT from EL0\n", esr);
|
||||
esr = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
current->thread.fault_code = esr;
|
||||
arm64_force_sig_info(info, esr_to_fault_info(esr)->name, current);
|
||||
}
|
||||
|
|
|
@ -933,13 +933,15 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot)
|
|||
{
|
||||
pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT |
|
||||
pgprot_val(mk_sect_prot(prot)));
|
||||
pud_t new_pud = pfn_pud(__phys_to_pfn(phys), sect_prot);
|
||||
|
||||
/* ioremap_page_range doesn't honour BBM */
|
||||
if (pud_present(READ_ONCE(*pudp)))
|
||||
/* Only allow permission changes for now */
|
||||
if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)),
|
||||
pud_val(new_pud)))
|
||||
return 0;
|
||||
|
||||
BUG_ON(phys & ~PUD_MASK);
|
||||
set_pud(pudp, pfn_pud(__phys_to_pfn(phys), sect_prot));
|
||||
set_pud(pudp, new_pud);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -947,13 +949,15 @@ int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot)
|
|||
{
|
||||
pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT |
|
||||
pgprot_val(mk_sect_prot(prot)));
|
||||
pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), sect_prot);
|
||||
|
||||
/* ioremap_page_range doesn't honour BBM */
|
||||
if (pmd_present(READ_ONCE(*pmdp)))
|
||||
/* Only allow permission changes for now */
|
||||
if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)),
|
||||
pmd_val(new_pmd)))
|
||||
return 0;
|
||||
|
||||
BUG_ON(phys & ~PMD_MASK);
|
||||
set_pmd(pmdp, pfn_pmd(__phys_to_pfn(phys), sect_prot));
|
||||
set_pmd(pmdp, new_pmd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
#define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset))
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MACH_JZ4740) || defined(CONFIG_MACH_JZ4780)
|
||||
#include <asm/mach-jz4740/base.h>
|
||||
#define PORT(offset) (CKSEG1ADDR(JZ4740_UART0_BASE_ADDR) + (4 * offset))
|
||||
#ifdef CONFIG_MACH_INGENIC
|
||||
#define INGENIC_UART0_BASE_ADDR 0x10030000
|
||||
#define PORT(offset) (CKSEG1ADDR(INGENIC_UART0_BASE_ADDR) + (4 * offset))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_XLR
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
dtb-$(CONFIG_FIT_IMAGE_FDT_XILFPGA) += nexys4ddr.dtb
|
||||
|
||||
obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
|
||||
|
|
|
@ -16,3 +16,4 @@ all-$(CONFIG_MIPS_GENERIC) := vmlinux.gz.itb
|
|||
its-y := vmlinux.its.S
|
||||
its-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += board-boston.its.S
|
||||
its-$(CONFIG_FIT_IMAGE_FDT_NI169445) += board-ni169445.its.S
|
||||
its-$(CONFIG_FIT_IMAGE_FDT_XILFPGA) += board-xilfpga.its.S
|
||||
|
|
|
@ -721,6 +721,10 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
|
|||
if (value & ~known_bits)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Setting FRE without FR is not supported. */
|
||||
if ((value & (PR_FP_MODE_FR | PR_FP_MODE_FRE)) == PR_FP_MODE_FRE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Avoid inadvertently triggering emulation */
|
||||
if ((value & PR_FP_MODE_FR) && raw_cpu_has_fpu &&
|
||||
!(raw_current_cpu_data.fpu_id & MIPS_FPIR_F64))
|
||||
|
|
|
@ -463,7 +463,7 @@ static int fpr_get_msa(struct task_struct *target,
|
|||
/*
|
||||
* Copy the floating-point context to the supplied NT_PRFPREG buffer.
|
||||
* Choose the appropriate helper for general registers, and then copy
|
||||
* the FCSR register separately.
|
||||
* the FCSR and FIR registers separately.
|
||||
*/
|
||||
static int fpr_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
|
@ -471,6 +471,7 @@ static int fpr_get(struct task_struct *target,
|
|||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
|
||||
const int fir_pos = fcr31_pos + sizeof(u32);
|
||||
int err;
|
||||
|
||||
if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
|
||||
|
@ -483,6 +484,12 @@ static int fpr_get(struct task_struct *target,
|
|||
err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fpu.fcr31,
|
||||
fcr31_pos, fcr31_pos + sizeof(u32));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&boot_cpu_data.fpu_id,
|
||||
fir_pos, fir_pos + sizeof(u32));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -531,7 +538,8 @@ static int fpr_set_msa(struct task_struct *target,
|
|||
/*
|
||||
* Copy the supplied NT_PRFPREG buffer to the floating-point context.
|
||||
* Choose the appropriate helper for general registers, and then copy
|
||||
* the FCSR register separately.
|
||||
* the FCSR register separately. Ignore the incoming FIR register
|
||||
* contents though, as the register is read-only.
|
||||
*
|
||||
* We optimize for the case where `count % sizeof(elf_fpreg_t) == 0',
|
||||
* which is supposed to have been guaranteed by the kernel before
|
||||
|
@ -545,6 +553,7 @@ static int fpr_set(struct task_struct *target,
|
|||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
|
||||
const int fir_pos = fcr31_pos + sizeof(u32);
|
||||
u32 fcr31;
|
||||
int err;
|
||||
|
||||
|
@ -572,6 +581,11 @@ static int fpr_set(struct task_struct *target,
|
|||
ptrace_setfcr31(target, fcr31);
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
err = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
||||
fir_pos,
|
||||
fir_pos + sizeof(u32));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -793,7 +807,7 @@ long arch_ptrace(struct task_struct *child, long request,
|
|||
fregs = get_fpu_regs(child);
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
if (test_thread_flag(TIF_32BIT_FPREGS)) {
|
||||
if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) {
|
||||
/*
|
||||
* The odd registers are actually the high
|
||||
* order bits of the values stored in the even
|
||||
|
@ -804,7 +818,7 @@ long arch_ptrace(struct task_struct *child, long request,
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
|
||||
tmp = get_fpr64(&fregs[addr - FPR_BASE], 0);
|
||||
break;
|
||||
case PC:
|
||||
tmp = regs->cp0_epc;
|
||||
|
@ -888,7 +902,7 @@ long arch_ptrace(struct task_struct *child, long request,
|
|||
|
||||
init_fp_ctx(child);
|
||||
#ifdef CONFIG_32BIT
|
||||
if (test_thread_flag(TIF_32BIT_FPREGS)) {
|
||||
if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) {
|
||||
/*
|
||||
* The odd registers are actually the high
|
||||
* order bits of the values stored in the even
|
||||
|
|
|
@ -99,7 +99,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
|||
break;
|
||||
}
|
||||
fregs = get_fpu_regs(child);
|
||||
if (test_thread_flag(TIF_32BIT_FPREGS)) {
|
||||
if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) {
|
||||
/*
|
||||
* The odd registers are actually the high
|
||||
* order bits of the values stored in the even
|
||||
|
@ -109,7 +109,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
|||
addr & 1);
|
||||
break;
|
||||
}
|
||||
tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);
|
||||
tmp = get_fpr64(&fregs[addr - FPR_BASE], 0);
|
||||
break;
|
||||
case PC:
|
||||
tmp = regs->cp0_epc;
|
||||
|
@ -212,7 +212,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
|||
sizeof(child->thread.fpu));
|
||||
child->thread.fpu.fcr31 = 0;
|
||||
}
|
||||
if (test_thread_flag(TIF_32BIT_FPREGS)) {
|
||||
if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) {
|
||||
/*
|
||||
* The odd registers are actually the high
|
||||
* order bits of the values stored in the even
|
||||
|
|
|
@ -45,7 +45,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
|
|||
{ "cache", VCPU_STAT(cache_exits), KVM_STAT_VCPU },
|
||||
{ "signal", VCPU_STAT(signal_exits), KVM_STAT_VCPU },
|
||||
{ "interrupt", VCPU_STAT(int_exits), KVM_STAT_VCPU },
|
||||
{ "cop_unsuable", VCPU_STAT(cop_unusable_exits), KVM_STAT_VCPU },
|
||||
{ "cop_unusable", VCPU_STAT(cop_unusable_exits), KVM_STAT_VCPU },
|
||||
{ "tlbmod", VCPU_STAT(tlbmod_exits), KVM_STAT_VCPU },
|
||||
{ "tlbmiss_ld", VCPU_STAT(tlbmiss_ld_exits), KVM_STAT_VCPU },
|
||||
{ "tlbmiss_st", VCPU_STAT(tlbmiss_st_exits), KVM_STAT_VCPU },
|
||||
|
|
|
@ -851,9 +851,12 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
|
|||
/*
|
||||
* Either no secondary cache or the available caches don't have the
|
||||
* subset property so we have to flush the primary caches
|
||||
* explicitly
|
||||
* explicitly.
|
||||
* If we would need IPI to perform an INDEX-type operation, then
|
||||
* we have to use the HIT-type alternative as IPI cannot be used
|
||||
* here due to interrupts possibly being disabled.
|
||||
*/
|
||||
if (size >= dcache_size) {
|
||||
if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
|
||||
r4k_blast_dcache();
|
||||
} else {
|
||||
R4600_HIT_CACHEOP_WAR_IMPL;
|
||||
|
@ -890,7 +893,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
|
|||
return;
|
||||
}
|
||||
|
||||
if (size >= dcache_size) {
|
||||
if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
|
||||
r4k_blast_dcache();
|
||||
} else {
|
||||
R4600_HIT_CACHEOP_WAR_IMPL;
|
||||
|
|
|
@ -9,6 +9,12 @@ config NDS32
|
|||
select CLKSRC_MMIO
|
||||
select CLONE_BACKWARDS
|
||||
select COMMON_CLK
|
||||
select GENERIC_ASHLDI3
|
||||
select GENERIC_ASHRDI3
|
||||
select GENERIC_LSHRDI3
|
||||
select GENERIC_CMPDI2
|
||||
select GENERIC_MULDI3
|
||||
select GENERIC_UCMPDI2
|
||||
select GENERIC_ATOMIC64
|
||||
select GENERIC_CPU_DEVICES
|
||||
select GENERIC_CLOCKEVENTS
|
||||
|
@ -82,6 +88,7 @@ endmenu
|
|||
|
||||
menu "Kernel Features"
|
||||
source "kernel/Kconfig.preempt"
|
||||
source "kernel/Kconfig.freezer"
|
||||
source "mm/Kconfig"
|
||||
source "kernel/Kconfig.hz"
|
||||
endmenu
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
comment "Processor Features"
|
||||
|
||||
config CPU_BIG_ENDIAN
|
||||
bool "Big endian"
|
||||
def_bool !CPU_LITTLE_ENDIAN
|
||||
|
||||
config CPU_LITTLE_ENDIAN
|
||||
def_bool !CPU_BIG_ENDIAN
|
||||
bool "Little endian"
|
||||
default y
|
||||
|
||||
config HWZOL
|
||||
bool "hardware zero overhead loop support"
|
||||
|
|
|
@ -23,9 +23,6 @@ export TEXTADDR
|
|||
# If we have a machine-specific directory, then include it in the build.
|
||||
core-y += arch/nds32/kernel/ arch/nds32/mm/
|
||||
libs-y += arch/nds32/lib/
|
||||
LIBGCC_PATH := \
|
||||
$(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
|
||||
libs-y += $(LIBGCC_PATH)
|
||||
|
||||
ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'
|
||||
BUILTIN_DTB := y
|
||||
|
@ -35,8 +32,12 @@ endif
|
|||
|
||||
ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
KBUILD_CFLAGS += $(call cc-option, -EL)
|
||||
KBUILD_AFLAGS += $(call cc-option, -EL)
|
||||
LDFLAGS += $(call cc-option, -EL)
|
||||
else
|
||||
KBUILD_CFLAGS += $(call cc-option, -EB)
|
||||
KBUILD_AFLAGS += $(call cc-option, -EB)
|
||||
LDFLAGS += $(call cc-option, -EB)
|
||||
endif
|
||||
|
||||
boot := arch/nds32/boot
|
||||
|
|
|
@ -16,6 +16,7 @@ generic-y += dma.h
|
|||
generic-y += emergency-restart.h
|
||||
generic-y += errno.h
|
||||
generic-y += exec.h
|
||||
generic-y += export.h
|
||||
generic-y += fb.h
|
||||
generic-y += fcntl.h
|
||||
generic-y += ftrace.h
|
||||
|
@ -49,6 +50,7 @@ generic-y += switch_to.h
|
|||
generic-y += timex.h
|
||||
generic-y += topology.h
|
||||
generic-y += trace_clock.h
|
||||
generic-y += xor.h
|
||||
generic-y += unaligned.h
|
||||
generic-y += user.h
|
||||
generic-y += vga.h
|
||||
|
|
|
@ -336,7 +336,7 @@
|
|||
#define INT_MASK_mskIDIVZE ( 0x1 << INT_MASK_offIDIVZE )
|
||||
#define INT_MASK_mskDSSIM ( 0x1 << INT_MASK_offDSSIM )
|
||||
|
||||
#define INT_MASK_INITAIAL_VAL 0x10003
|
||||
#define INT_MASK_INITAIAL_VAL (INT_MASK_mskDSSIM|INT_MASK_mskIDIVZE)
|
||||
|
||||
/******************************************************************************
|
||||
* ir15: INT_PEND (Interrupt Pending Register)
|
||||
|
@ -396,6 +396,7 @@
|
|||
#define MMU_CTL_D8KB 1
|
||||
#define MMU_CTL_UNA ( 0x1 << MMU_CTL_offUNA )
|
||||
|
||||
#define MMU_CTL_CACHEABLE_NON 0
|
||||
#define MMU_CTL_CACHEABLE_WB 2
|
||||
#define MMU_CTL_CACHEABLE_WT 3
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ void flush_anon_page(struct vm_area_struct *vma,
|
|||
|
||||
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
|
||||
void flush_kernel_dcache_page(struct page *page);
|
||||
void flush_kernel_vmap_range(void *addr, int size);
|
||||
void invalidate_kernel_vmap_range(void *addr, int size);
|
||||
void flush_icache_range(unsigned long start, unsigned long end);
|
||||
void flush_icache_page(struct vm_area_struct *vma, struct page *page);
|
||||
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&(mapping)->i_pages)
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#ifndef __ASM_NDS32_IO_H
|
||||
#define __ASM_NDS32_IO_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
extern void iounmap(volatile void __iomem *addr);
|
||||
#define __raw_writeb __raw_writeb
|
||||
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
|
||||
|
|
|
@ -27,6 +27,9 @@ extern void copy_user_highpage(struct page *to, struct page *from,
|
|||
unsigned long vaddr, struct vm_area_struct *vma);
|
||||
extern void clear_user_highpage(struct page *page, unsigned long vaddr);
|
||||
|
||||
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
|
||||
struct page *to);
|
||||
void clear_user_page(void *addr, unsigned long vaddr, struct page *page);
|
||||
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
|
||||
#define clear_user_highpage clear_user_highpage
|
||||
#else
|
||||
|
|
|
@ -152,6 +152,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
|
|||
#define PAGE_CACHE_L1 __pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE)
|
||||
#define PAGE_MEMORY __pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
|
||||
#define PAGE_KERNEL __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
|
||||
#define PAGE_SHARED __pgprot(_PAGE_V | _PAGE_M_URW_KRW | _PAGE_D | _PAGE_CACHE_SHRD)
|
||||
#define PAGE_DEVICE __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_G | _PAGE_C_DEV)
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ common_exception_handler:
|
|||
/* interrupt */
|
||||
2:
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
jal arch_trace_hardirqs_off
|
||||
jal trace_hardirqs_off
|
||||
#endif
|
||||
move $r0, $sp
|
||||
sethi $lp, hi20(ret_from_intr)
|
||||
|
|
|
@ -57,14 +57,32 @@ _nodtb:
|
|||
isb
|
||||
mtsr $r4, $L1_PPTB ! load page table pointer\n"
|
||||
|
||||
/* set NTC0 cacheable/writeback, mutliple page size in use */
|
||||
mfsr $r3, $MMU_CTL
|
||||
li $r0, #~MMU_CTL_mskNTC0
|
||||
and $r3, $r3, $r0
|
||||
#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
|
||||
ori $r3, $r3, #(MMU_CTL_mskMPZIU|(MMU_CTL_CACHEABLE_WB << MMU_CTL_offNTC0))
|
||||
#ifdef CONFIG_CPU_DCACHE_DISABLE
|
||||
#define MMU_CTL_NTCC MMU_CTL_CACHEABLE_NON
|
||||
#else
|
||||
ori $r3, $r3, #(MMU_CTL_mskMPZIU|(MMU_CTL_CACHEABLE_WB << MMU_CTL_offNTC0)|MMU_CTL_D8KB)
|
||||
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
#define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WT
|
||||
#else
|
||||
#define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WB
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* set NTC cacheability, mutliple page size in use */
|
||||
mfsr $r3, $MMU_CTL
|
||||
#if CONFIG_MEMORY_START >= 0xc0000000
|
||||
ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC3)
|
||||
#elif CONFIG_MEMORY_START >= 0x80000000
|
||||
ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC2)
|
||||
#elif CONFIG_MEMORY_START >= 0x40000000
|
||||
ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC1)
|
||||
#else
|
||||
ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
|
||||
ori $r3, $r3, #(MMU_CTL_mskMPZIU)
|
||||
#else
|
||||
ori $r3, $r3, #(MMU_CTL_mskMPZIU|MMU_CTL_D8KB)
|
||||
#endif
|
||||
#ifdef CONFIG_HW_SUPPORT_UNALIGNMENT_ACCESS
|
||||
li $r0, #MMU_CTL_UNA
|
||||
|
|
|
@ -293,6 +293,9 @@ void __init setup_arch(char **cmdline_p)
|
|||
/* paging_init() sets up the MMU and marks all pages as reserved */
|
||||
paging_init();
|
||||
|
||||
/* invalidate all TLB entries because the new mapping is created */
|
||||
__nds32__tlbop_flua();
|
||||
|
||||
/* use generic way to parse */
|
||||
parse_early_param();
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ void save_stack_trace(struct stack_trace *trace)
|
|||
{
|
||||
save_stack_trace_tsk(current, trace);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(save_stack_trace);
|
||||
|
||||
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
|
||||
{
|
||||
|
@ -45,3 +46,4 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
|
|||
fpn = (unsigned long *)fpp;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <asm/vdso_timer_info.h>
|
||||
#include <asm/cache_info.h>
|
||||
extern struct cache_info L1_cache_info[2];
|
||||
extern char vdso_start, vdso_end;
|
||||
extern char vdso_start[], vdso_end[];
|
||||
static unsigned long vdso_pages __ro_after_init;
|
||||
static unsigned long timer_mapping_base;
|
||||
|
||||
|
@ -66,16 +66,16 @@ static int __init vdso_init(void)
|
|||
int i;
|
||||
struct page **vdso_pagelist;
|
||||
|
||||
if (memcmp(&vdso_start, "\177ELF", 4)) {
|
||||
if (memcmp(vdso_start, "\177ELF", 4)) {
|
||||
pr_err("vDSO is not a valid ELF object!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Creat a timer io mapping to get clock cycles counter */
|
||||
get_timer_node_info();
|
||||
|
||||
vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
|
||||
vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
|
||||
pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
|
||||
vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
|
||||
vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
|
||||
|
||||
/* Allocate the vDSO pagelist */
|
||||
vdso_pagelist = kcalloc(vdso_pages, sizeof(struct page *), GFP_KERNEL);
|
||||
|
@ -83,7 +83,7 @@ static int __init vdso_init(void)
|
|||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < vdso_pages; i++)
|
||||
vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE);
|
||||
vdso_pagelist[i] = virt_to_page(vdso_start + i * PAGE_SIZE);
|
||||
vdso_spec[1].pages = &vdso_pagelist[0];
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Copyright (C) 2005-2017 Andes Technology Corporation
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/export.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
.text
|
||||
|
@ -16,6 +17,7 @@ ENTRY(copy_page)
|
|||
popm $r2, $r10
|
||||
ret
|
||||
ENDPROC(copy_page)
|
||||
EXPORT_SYMBOL(copy_page)
|
||||
|
||||
ENTRY(clear_page)
|
||||
pushm $r1, $r9
|
||||
|
@ -35,3 +37,4 @@ ENTRY(clear_page)
|
|||
popm $r1, $r9
|
||||
ret
|
||||
ENDPROC(clear_page)
|
||||
EXPORT_SYMBOL(clear_page)
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#define RA(inst) (((inst) >> 15) & 0x1FUL)
|
||||
#define RB(inst) (((inst) >> 10) & 0x1FUL)
|
||||
#define SV(inst) (((inst) >> 8) & 0x3UL)
|
||||
#define IMM(inst) (((inst) >> 0) & 0x3FFFUL)
|
||||
#define IMM(inst) (((inst) >> 0) & 0x7FFFUL)
|
||||
|
||||
#define RA3(inst) (((inst) >> 3) & 0x7UL)
|
||||
#define RT3(inst) (((inst) >> 6) & 0x7UL)
|
||||
|
@ -28,6 +28,9 @@
|
|||
#define RA5(inst) (((inst) >> 0) & 0x1FUL)
|
||||
#define RT4(inst) (((inst) >> 5) & 0xFUL)
|
||||
|
||||
#define GET_IMMSVAL(imm_value) \
|
||||
(((imm_value >> 14) & 0x1) ? (imm_value - 0x8000) : imm_value)
|
||||
|
||||
#define __get8_data(val,addr,err) \
|
||||
__asm__( \
|
||||
"1: lbi.bi %1, [%2], #1\n" \
|
||||
|
@ -467,7 +470,7 @@ static inline int do_32(unsigned long inst, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
if (imm)
|
||||
shift = IMM(inst) * len;
|
||||
shift = GET_IMMSVAL(IMM(inst)) * len;
|
||||
else
|
||||
shift = *idx_to_addr(regs, RB(inst)) << SV(inst);
|
||||
|
||||
|
@ -552,7 +555,7 @@ static struct ctl_table alignment_tbl[3] = {
|
|||
|
||||
static struct ctl_table nds32_sysctl_table[2] = {
|
||||
{
|
||||
.procname = "unaligned_acess",
|
||||
.procname = "unaligned_access",
|
||||
.mode = 0555,
|
||||
.child = alignment_tbl},
|
||||
{}
|
||||
|
|
|
@ -147,6 +147,25 @@ void flush_cache_vunmap(unsigned long start, unsigned long end)
|
|||
cpu_icache_inval_all();
|
||||
}
|
||||
|
||||
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
|
||||
struct page *to)
|
||||
{
|
||||
cpu_dcache_wbinval_page((unsigned long)vaddr);
|
||||
cpu_icache_inval_page((unsigned long)vaddr);
|
||||
copy_page(vto, vfrom);
|
||||
cpu_dcache_wbinval_page((unsigned long)vto);
|
||||
cpu_icache_inval_page((unsigned long)vto);
|
||||
}
|
||||
|
||||
void clear_user_page(void *addr, unsigned long vaddr, struct page *page)
|
||||
{
|
||||
cpu_dcache_wbinval_page((unsigned long)vaddr);
|
||||
cpu_icache_inval_page((unsigned long)vaddr);
|
||||
clear_page(addr);
|
||||
cpu_dcache_wbinval_page((unsigned long)addr);
|
||||
cpu_icache_inval_page((unsigned long)addr);
|
||||
}
|
||||
|
||||
void copy_user_highpage(struct page *to, struct page *from,
|
||||
unsigned long vaddr, struct vm_area_struct *vma)
|
||||
{
|
||||
|
@ -156,11 +175,9 @@ void copy_user_highpage(struct page *to, struct page *from,
|
|||
pto = page_to_phys(to);
|
||||
pfrom = page_to_phys(from);
|
||||
|
||||
local_irq_save(flags);
|
||||
if (aliasing(vaddr, (unsigned long)kfrom))
|
||||
cpu_dcache_wb_page((unsigned long)kfrom);
|
||||
if (aliasing(vaddr, (unsigned long)kto))
|
||||
cpu_dcache_inval_page((unsigned long)kto);
|
||||
local_irq_save(flags);
|
||||
vto = kremap0(vaddr, pto);
|
||||
vfrom = kremap1(vaddr, pfrom);
|
||||
copy_page((void *)vto, (void *)vfrom);
|
||||
|
@ -198,21 +215,25 @@ void flush_dcache_page(struct page *page)
|
|||
if (mapping && !mapping_mapped(mapping))
|
||||
set_bit(PG_dcache_dirty, &page->flags);
|
||||
else {
|
||||
int i, pc;
|
||||
unsigned long vto, kaddr, flags;
|
||||
unsigned long kaddr, flags;
|
||||
|
||||
kaddr = (unsigned long)page_address(page);
|
||||
cpu_dcache_wbinval_page(kaddr);
|
||||
pc = CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE) / PAGE_SIZE;
|
||||
local_irq_save(flags);
|
||||
for (i = 0; i < pc; i++) {
|
||||
vto =
|
||||
kremap0(kaddr + i * PAGE_SIZE, page_to_phys(page));
|
||||
cpu_dcache_wbinval_page(vto);
|
||||
kunmap01(vto);
|
||||
cpu_dcache_wbinval_page(kaddr);
|
||||
if (mapping) {
|
||||
unsigned long vaddr, kto;
|
||||
|
||||
vaddr = page->index << PAGE_SHIFT;
|
||||
if (aliasing(vaddr, kaddr)) {
|
||||
kto = kremap0(vaddr, page_to_phys(page));
|
||||
cpu_dcache_wbinval_page(kto);
|
||||
kunmap01(kto);
|
||||
}
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(flush_dcache_page);
|
||||
|
||||
void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
||||
unsigned long vaddr, void *dst, void *src, int len)
|
||||
|
@ -251,7 +272,7 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
|
|||
void flush_anon_page(struct vm_area_struct *vma,
|
||||
struct page *page, unsigned long vaddr)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long kaddr, flags, ktmp;
|
||||
if (!PageAnon(page))
|
||||
return;
|
||||
|
||||
|
@ -261,7 +282,12 @@ void flush_anon_page(struct vm_area_struct *vma,
|
|||
local_irq_save(flags);
|
||||
if (vma->vm_flags & VM_EXEC)
|
||||
cpu_icache_inval_page(vaddr & PAGE_MASK);
|
||||
cpu_dcache_wbinval_page((unsigned long)page_address(page));
|
||||
kaddr = (unsigned long)page_address(page);
|
||||
if (aliasing(vaddr, kaddr)) {
|
||||
ktmp = kremap0(vaddr, page_to_phys(page));
|
||||
cpu_dcache_wbinval_page(ktmp);
|
||||
kunmap01(ktmp);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
@ -272,6 +298,25 @@ void flush_kernel_dcache_page(struct page *page)
|
|||
cpu_dcache_wbinval_page((unsigned long)page_address(page));
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(flush_kernel_dcache_page);
|
||||
|
||||
void flush_kernel_vmap_range(void *addr, int size)
|
||||
{
|
||||
unsigned long flags;
|
||||
local_irq_save(flags);
|
||||
cpu_dcache_wb_range((unsigned long)addr, (unsigned long)addr + size);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(flush_kernel_vmap_range);
|
||||
|
||||
void invalidate_kernel_vmap_range(void *addr, int size)
|
||||
{
|
||||
unsigned long flags;
|
||||
local_irq_save(flags);
|
||||
cpu_dcache_inval_range((unsigned long)addr, (unsigned long)addr + size);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(invalidate_kernel_vmap_range);
|
||||
|
||||
void flush_icache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
|
@ -283,6 +328,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
|
|||
cpu_cache_wbinval_range(start, end, 1);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(flush_icache_range);
|
||||
|
||||
void flush_icache_page(struct vm_area_struct *vma, struct page *page)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ extern unsigned long phys_initrd_size;
|
|||
* zero-initialized data and COW.
|
||||
*/
|
||||
struct page *empty_zero_page;
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
|
||||
static void __init zone_sizes_init(void)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,27 @@
|
|||
*/
|
||||
#define EX_R3 EX_DAR
|
||||
|
||||
#define STF_ENTRY_BARRIER_SLOT \
|
||||
STF_ENTRY_BARRIER_FIXUP_SECTION; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop
|
||||
|
||||
#define STF_EXIT_BARRIER_SLOT \
|
||||
STF_EXIT_BARRIER_FIXUP_SECTION; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop
|
||||
|
||||
/*
|
||||
* r10 must be free to use, r13 must be paca
|
||||
*/
|
||||
#define INTERRUPT_TO_KERNEL \
|
||||
STF_ENTRY_BARRIER_SLOT
|
||||
|
||||
/*
|
||||
* Macros for annotating the expected destination of (h)rfid
|
||||
*
|
||||
|
@ -90,16 +111,19 @@
|
|||
rfid
|
||||
|
||||
#define RFI_TO_USER \
|
||||
STF_EXIT_BARRIER_SLOT; \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_USER_OR_KERNEL \
|
||||
STF_EXIT_BARRIER_SLOT; \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_GUEST \
|
||||
STF_EXIT_BARRIER_SLOT; \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
@ -108,21 +132,25 @@
|
|||
hrfid
|
||||
|
||||
#define HRFI_TO_USER \
|
||||
STF_EXIT_BARRIER_SLOT; \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_USER_OR_KERNEL \
|
||||
STF_EXIT_BARRIER_SLOT; \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_GUEST \
|
||||
STF_EXIT_BARRIER_SLOT; \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_UNKNOWN \
|
||||
STF_EXIT_BARRIER_SLOT; \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
@ -254,6 +282,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
|
|||
#define __EXCEPTION_PROLOG_1_PRE(area) \
|
||||
OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \
|
||||
OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \
|
||||
INTERRUPT_TO_KERNEL; \
|
||||
SAVE_CTR(r10, area); \
|
||||
mfcr r9;
|
||||
|
||||
|
|
|
@ -187,6 +187,22 @@ label##3: \
|
|||
FTR_ENTRY_OFFSET label##1b-label##3b; \
|
||||
.popsection;
|
||||
|
||||
#define STF_ENTRY_BARRIER_FIXUP_SECTION \
|
||||
953: \
|
||||
.pushsection __stf_entry_barrier_fixup,"a"; \
|
||||
.align 2; \
|
||||
954: \
|
||||
FTR_ENTRY_OFFSET 953b-954b; \
|
||||
.popsection;
|
||||
|
||||
#define STF_EXIT_BARRIER_FIXUP_SECTION \
|
||||
955: \
|
||||
.pushsection __stf_exit_barrier_fixup,"a"; \
|
||||
.align 2; \
|
||||
956: \
|
||||
FTR_ENTRY_OFFSET 955b-956b; \
|
||||
.popsection;
|
||||
|
||||
#define RFI_FLUSH_FIXUP_SECTION \
|
||||
951: \
|
||||
.pushsection __rfi_flush_fixup,"a"; \
|
||||
|
@ -199,6 +215,9 @@ label##3: \
|
|||
#ifndef __ASSEMBLY__
|
||||
#include <linux/types.h>
|
||||
|
||||
extern long stf_barrier_fallback;
|
||||
extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
|
||||
extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
|
||||
extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
|
||||
|
||||
void apply_feature_fixups(void);
|
||||
|
|
|
@ -96,6 +96,7 @@ struct kvmppc_vcore {
|
|||
struct kvm_vcpu *runner;
|
||||
struct kvm *kvm;
|
||||
u64 tb_offset; /* guest timebase - host timebase */
|
||||
u64 tb_offset_applied; /* timebase offset currently in force */
|
||||
ulong lpcr;
|
||||
u32 arch_compat;
|
||||
ulong pcr;
|
||||
|
|
|
@ -12,6 +12,17 @@
|
|||
extern unsigned long powerpc_security_features;
|
||||
extern bool rfi_flush;
|
||||
|
||||
/* These are bit flags */
|
||||
enum stf_barrier_type {
|
||||
STF_BARRIER_NONE = 0x1,
|
||||
STF_BARRIER_FALLBACK = 0x2,
|
||||
STF_BARRIER_EIEIO = 0x4,
|
||||
STF_BARRIER_SYNC_ORI = 0x8,
|
||||
};
|
||||
|
||||
void setup_stf_barrier(void);
|
||||
void do_stf_barrier_fixups(enum stf_barrier_type types);
|
||||
|
||||
static inline void security_ftr_set(unsigned long feature)
|
||||
{
|
||||
powerpc_security_features |= feature;
|
||||
|
|
|
@ -562,6 +562,7 @@ int main(void)
|
|||
OFFSET(VCORE_NAPPING_THREADS, kvmppc_vcore, napping_threads);
|
||||
OFFSET(VCORE_KVM, kvmppc_vcore, kvm);
|
||||
OFFSET(VCORE_TB_OFFSET, kvmppc_vcore, tb_offset);
|
||||
OFFSET(VCORE_TB_OFFSET_APPL, kvmppc_vcore, tb_offset_applied);
|
||||
OFFSET(VCORE_LPCR, kvmppc_vcore, lpcr);
|
||||
OFFSET(VCORE_PCR, kvmppc_vcore, pcr);
|
||||
OFFSET(VCORE_DPDES, kvmppc_vcore, dpdes);
|
||||
|
|
|
@ -28,6 +28,7 @@ _GLOBAL(__setup_cpu_power7)
|
|||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
li r4,(LPCR_LPES1 >> LPCR_LPES_SH)
|
||||
bl __init_LPCR_ISA206
|
||||
|
@ -41,6 +42,7 @@ _GLOBAL(__restore_cpu_power7)
|
|||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
li r4,(LPCR_LPES1 >> LPCR_LPES_SH)
|
||||
bl __init_LPCR_ISA206
|
||||
|
@ -57,6 +59,7 @@ _GLOBAL(__setup_cpu_power8)
|
|||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
ori r3, r3, LPCR_PECEDH
|
||||
li r4,0 /* LPES = 0 */
|
||||
|
@ -78,6 +81,7 @@ _GLOBAL(__restore_cpu_power8)
|
|||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
ori r3, r3, LPCR_PECEDH
|
||||
li r4,0 /* LPES = 0 */
|
||||
|
@ -99,6 +103,7 @@ _GLOBAL(__setup_cpu_power9)
|
|||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PID,r0
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC)
|
||||
or r3, r3, r4
|
||||
|
@ -123,6 +128,7 @@ _GLOBAL(__restore_cpu_power9)
|
|||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PID,r0
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC)
|
||||
or r3, r3, r4
|
||||
|
|
|
@ -101,6 +101,7 @@ static void __restore_cpu_cpufeatures(void)
|
|||
if (hv_mode) {
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_HFSCR, system_registers.hfscr);
|
||||
mtspr(SPRN_PCR, 0);
|
||||
}
|
||||
mtspr(SPRN_FSCR, system_registers.fscr);
|
||||
|
||||
|
|
|
@ -885,7 +885,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
|||
#endif
|
||||
|
||||
|
||||
EXC_REAL_MASKABLE(decrementer, 0x900, 0x80, IRQS_DISABLED)
|
||||
EXC_REAL_OOL_MASKABLE(decrementer, 0x900, 0x80, IRQS_DISABLED)
|
||||
EXC_VIRT_MASKABLE(decrementer, 0x4900, 0x80, 0x900, IRQS_DISABLED)
|
||||
TRAMP_KVM(PACA_EXGEN, 0x900)
|
||||
EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt)
|
||||
|
@ -961,6 +961,7 @@ EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
|
|||
mtctr r13; \
|
||||
GET_PACA(r13); \
|
||||
std r10,PACA_EXGEN+EX_R10(r13); \
|
||||
INTERRUPT_TO_KERNEL; \
|
||||
KVMTEST_PR(0xc00); /* uses r10, branch to do_kvm_0xc00_system_call */ \
|
||||
HMT_MEDIUM; \
|
||||
mfctr r9;
|
||||
|
@ -969,7 +970,8 @@ EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
|
|||
#define SYSCALL_KVMTEST \
|
||||
HMT_MEDIUM; \
|
||||
mr r9,r13; \
|
||||
GET_PACA(r13);
|
||||
GET_PACA(r13); \
|
||||
INTERRUPT_TO_KERNEL;
|
||||
#endif
|
||||
|
||||
#define LOAD_SYSCALL_HANDLER(reg) \
|
||||
|
@ -1507,6 +1509,19 @@ masked_##_H##interrupt: \
|
|||
b .; \
|
||||
MASKED_DEC_HANDLER(_H)
|
||||
|
||||
TRAMP_REAL_BEGIN(stf_barrier_fallback)
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
sync
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ori 31,31,0
|
||||
.rept 14
|
||||
b 1f
|
||||
1:
|
||||
.endr
|
||||
blr
|
||||
|
||||
TRAMP_REAL_BEGIN(rfi_flush_fallback)
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/seq_buf.h>
|
||||
|
||||
#include <asm/debugfs.h>
|
||||
#include <asm/security_features.h>
|
||||
|
||||
|
||||
|
@ -86,3 +87,151 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
|
|||
|
||||
return s.len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store-forwarding barrier support.
|
||||
*/
|
||||
|
||||
static enum stf_barrier_type stf_enabled_flush_types;
|
||||
static bool no_stf_barrier;
|
||||
bool stf_barrier;
|
||||
|
||||
static int __init handle_no_stf_barrier(char *p)
|
||||
{
|
||||
pr_info("stf-barrier: disabled on command line.");
|
||||
no_stf_barrier = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_param("no_stf_barrier", handle_no_stf_barrier);
|
||||
|
||||
/* This is the generic flag used by other architectures */
|
||||
static int __init handle_ssbd(char *p)
|
||||
{
|
||||
if (!p || strncmp(p, "auto", 5) == 0 || strncmp(p, "on", 2) == 0 ) {
|
||||
/* Until firmware tells us, we have the barrier with auto */
|
||||
return 0;
|
||||
} else if (strncmp(p, "off", 3) == 0) {
|
||||
handle_no_stf_barrier(NULL);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("spec_store_bypass_disable", handle_ssbd);
|
||||
|
||||
/* This is the generic flag used by other architectures */
|
||||
static int __init handle_no_ssbd(char *p)
|
||||
{
|
||||
handle_no_stf_barrier(NULL);
|
||||
return 0;
|
||||
}
|
||||
early_param("nospec_store_bypass_disable", handle_no_ssbd);
|
||||
|
||||
static void stf_barrier_enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
do_stf_barrier_fixups(stf_enabled_flush_types);
|
||||
else
|
||||
do_stf_barrier_fixups(STF_BARRIER_NONE);
|
||||
|
||||
stf_barrier = enable;
|
||||
}
|
||||
|
||||
void setup_stf_barrier(void)
|
||||
{
|
||||
enum stf_barrier_type type;
|
||||
bool enable, hv;
|
||||
|
||||
hv = cpu_has_feature(CPU_FTR_HVMODE);
|
||||
|
||||
/* Default to fallback in case fw-features are not available */
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||
type = STF_BARRIER_EIEIO;
|
||||
else if (cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
type = STF_BARRIER_SYNC_ORI;
|
||||
else if (cpu_has_feature(CPU_FTR_ARCH_206))
|
||||
type = STF_BARRIER_FALLBACK;
|
||||
else
|
||||
type = STF_BARRIER_NONE;
|
||||
|
||||
enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
|
||||
(security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) ||
|
||||
(security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && hv));
|
||||
|
||||
if (type == STF_BARRIER_FALLBACK) {
|
||||
pr_info("stf-barrier: fallback barrier available\n");
|
||||
} else if (type == STF_BARRIER_SYNC_ORI) {
|
||||
pr_info("stf-barrier: hwsync barrier available\n");
|
||||
} else if (type == STF_BARRIER_EIEIO) {
|
||||
pr_info("stf-barrier: eieio barrier available\n");
|
||||
}
|
||||
|
||||
stf_enabled_flush_types = type;
|
||||
|
||||
if (!no_stf_barrier)
|
||||
stf_barrier_enable(enable);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (stf_barrier && stf_enabled_flush_types != STF_BARRIER_NONE) {
|
||||
const char *type;
|
||||
switch (stf_enabled_flush_types) {
|
||||
case STF_BARRIER_EIEIO:
|
||||
type = "eieio";
|
||||
break;
|
||||
case STF_BARRIER_SYNC_ORI:
|
||||
type = "hwsync";
|
||||
break;
|
||||
case STF_BARRIER_FALLBACK:
|
||||
type = "fallback";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
}
|
||||
return sprintf(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type);
|
||||
}
|
||||
|
||||
if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
|
||||
!security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int stf_barrier_set(void *data, u64 val)
|
||||
{
|
||||
bool enable;
|
||||
|
||||
if (val == 1)
|
||||
enable = true;
|
||||
else if (val == 0)
|
||||
enable = false;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* Only do anything if we're changing state */
|
||||
if (enable != stf_barrier)
|
||||
stf_barrier_enable(enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stf_barrier_get(void *data, u64 *val)
|
||||
{
|
||||
*val = stf_barrier ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n");
|
||||
|
||||
static __init int stf_barrier_debugfs_init(void)
|
||||
{
|
||||
debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(stf_barrier_debugfs_init);
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
|
|
@ -133,6 +133,20 @@ SECTIONS
|
|||
RO_DATA(PAGE_SIZE)
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
. = ALIGN(8);
|
||||
__stf_entry_barrier_fixup : AT(ADDR(__stf_entry_barrier_fixup) - LOAD_OFFSET) {
|
||||
__start___stf_entry_barrier_fixup = .;
|
||||
*(__stf_entry_barrier_fixup)
|
||||
__stop___stf_entry_barrier_fixup = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) {
|
||||
__start___stf_exit_barrier_fixup = .;
|
||||
*(__stf_exit_barrier_fixup)
|
||||
__stop___stf_exit_barrier_fixup = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) {
|
||||
__start___rfi_flush_fixup = .;
|
||||
|
|
|
@ -162,7 +162,7 @@ static void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
|
|||
if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG))
|
||||
asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
|
||||
: : "r" (addr), "r" (kvm->arch.lpid) : "memory");
|
||||
asm volatile("ptesync": : :"memory");
|
||||
asm volatile("eieio ; tlbsync ; ptesync": : :"memory");
|
||||
}
|
||||
|
||||
static void kvmppc_radix_flush_pwc(struct kvm *kvm, unsigned long addr)
|
||||
|
@ -173,7 +173,7 @@ static void kvmppc_radix_flush_pwc(struct kvm *kvm, unsigned long addr)
|
|||
/* RIC=1 PRS=0 R=1 IS=2 */
|
||||
asm volatile(PPC_TLBIE_5(%0, %1, 1, 0, 1)
|
||||
: : "r" (rb), "r" (kvm->arch.lpid) : "memory");
|
||||
asm volatile("ptesync": : :"memory");
|
||||
asm volatile("eieio ; tlbsync ; ptesync": : :"memory");
|
||||
}
|
||||
|
||||
unsigned long kvmppc_radix_update_pte(struct kvm *kvm, pte_t *ptep,
|
||||
|
@ -584,7 +584,7 @@ int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
|||
|
||||
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
|
||||
if (ptep && pte_present(*ptep)) {
|
||||
old = kvmppc_radix_update_pte(kvm, ptep, _PAGE_PRESENT, 0,
|
||||
old = kvmppc_radix_update_pte(kvm, ptep, ~0UL, 0,
|
||||
gpa, shift);
|
||||
kvmppc_radix_tlbie_page(kvm, gpa, shift);
|
||||
if ((old & _PAGE_DIRTY) && memslot->dirty_bitmap) {
|
||||
|
|
|
@ -2441,6 +2441,7 @@ static void init_vcore_to_run(struct kvmppc_vcore *vc)
|
|||
vc->in_guest = 0;
|
||||
vc->napping_threads = 0;
|
||||
vc->conferring_threads = 0;
|
||||
vc->tb_offset_applied = 0;
|
||||
}
|
||||
|
||||
static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
|
||||
|
|
|
@ -692,6 +692,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
|||
22: ld r8,VCORE_TB_OFFSET(r5)
|
||||
cmpdi r8,0
|
||||
beq 37f
|
||||
std r8, VCORE_TB_OFFSET_APPL(r5)
|
||||
mftb r6 /* current host timebase */
|
||||
add r8,r8,r6
|
||||
mtspr SPRN_TBU40,r8 /* update upper 40 bits */
|
||||
|
@ -940,18 +941,6 @@ FTR_SECTION_ELSE
|
|||
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
|
||||
8:
|
||||
|
||||
/*
|
||||
* Set the decrementer to the guest decrementer.
|
||||
*/
|
||||
ld r8,VCPU_DEC_EXPIRES(r4)
|
||||
/* r8 is a host timebase value here, convert to guest TB */
|
||||
ld r5,HSTATE_KVM_VCORE(r13)
|
||||
ld r6,VCORE_TB_OFFSET(r5)
|
||||
add r8,r8,r6
|
||||
mftb r7
|
||||
subf r3,r7,r8
|
||||
mtspr SPRN_DEC,r3
|
||||
|
||||
ld r5, VCPU_SPRG0(r4)
|
||||
ld r6, VCPU_SPRG1(r4)
|
||||
ld r7, VCPU_SPRG2(r4)
|
||||
|
@ -1005,6 +994,18 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
|
|||
mtspr SPRN_LPCR,r8
|
||||
isync
|
||||
|
||||
/*
|
||||
* Set the decrementer to the guest decrementer.
|
||||
*/
|
||||
ld r8,VCPU_DEC_EXPIRES(r4)
|
||||
/* r8 is a host timebase value here, convert to guest TB */
|
||||
ld r5,HSTATE_KVM_VCORE(r13)
|
||||
ld r6,VCORE_TB_OFFSET_APPL(r5)
|
||||
add r8,r8,r6
|
||||
mftb r7
|
||||
subf r3,r7,r8
|
||||
mtspr SPRN_DEC,r3
|
||||
|
||||
/* Check if HDEC expires soon */
|
||||
mfspr r3, SPRN_HDEC
|
||||
EXTEND_HDEC(r3)
|
||||
|
@ -1597,8 +1598,27 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
|
|||
|
||||
guest_bypass:
|
||||
stw r12, STACK_SLOT_TRAP(r1)
|
||||
mr r3, r12
|
||||
|
||||
/* Save DEC */
|
||||
/* Do this before kvmhv_commence_exit so we know TB is guest TB */
|
||||
ld r3, HSTATE_KVM_VCORE(r13)
|
||||
mfspr r5,SPRN_DEC
|
||||
mftb r6
|
||||
/* On P9, if the guest has large decr enabled, don't sign extend */
|
||||
BEGIN_FTR_SECTION
|
||||
ld r4, VCORE_LPCR(r3)
|
||||
andis. r4, r4, LPCR_LD@h
|
||||
bne 16f
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
||||
extsw r5,r5
|
||||
16: add r5,r5,r6
|
||||
/* r5 is a guest timebase value here, convert to host TB */
|
||||
ld r4,VCORE_TB_OFFSET_APPL(r3)
|
||||
subf r5,r4,r5
|
||||
std r5,VCPU_DEC_EXPIRES(r9)
|
||||
|
||||
/* Increment exit count, poke other threads to exit */
|
||||
mr r3, r12
|
||||
bl kvmhv_commence_exit
|
||||
nop
|
||||
ld r9, HSTATE_KVM_VCPU(r13)
|
||||
|
@ -1639,23 +1659,6 @@ guest_bypass:
|
|||
mtspr SPRN_PURR,r3
|
||||
mtspr SPRN_SPURR,r4
|
||||
|
||||
/* Save DEC */
|
||||
ld r3, HSTATE_KVM_VCORE(r13)
|
||||
mfspr r5,SPRN_DEC
|
||||
mftb r6
|
||||
/* On P9, if the guest has large decr enabled, don't sign extend */
|
||||
BEGIN_FTR_SECTION
|
||||
ld r4, VCORE_LPCR(r3)
|
||||
andis. r4, r4, LPCR_LD@h
|
||||
bne 16f
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
||||
extsw r5,r5
|
||||
16: add r5,r5,r6
|
||||
/* r5 is a guest timebase value here, convert to host TB */
|
||||
ld r4,VCORE_TB_OFFSET(r3)
|
||||
subf r5,r4,r5
|
||||
std r5,VCPU_DEC_EXPIRES(r9)
|
||||
|
||||
BEGIN_FTR_SECTION
|
||||
b 8f
|
||||
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
||||
|
@ -1905,6 +1908,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
|||
cmpwi cr2, r0, 0
|
||||
beq cr2, 4f
|
||||
|
||||
/*
|
||||
* Radix: do eieio; tlbsync; ptesync sequence in case we
|
||||
* interrupted the guest between a tlbie and a ptesync.
|
||||
*/
|
||||
eieio
|
||||
tlbsync
|
||||
ptesync
|
||||
|
||||
/* Radix: Handle the case where the guest used an illegal PID */
|
||||
LOAD_REG_ADDR(r4, mmu_base_pid)
|
||||
lwz r3, VCPU_GUEST_PID(r9)
|
||||
|
@ -2017,9 +2028,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|||
|
||||
27:
|
||||
/* Subtract timebase offset from timebase */
|
||||
ld r8,VCORE_TB_OFFSET(r5)
|
||||
ld r8, VCORE_TB_OFFSET_APPL(r5)
|
||||
cmpdi r8,0
|
||||
beq 17f
|
||||
li r0, 0
|
||||
std r0, VCORE_TB_OFFSET_APPL(r5)
|
||||
mftb r6 /* current guest timebase */
|
||||
subf r8,r8,r6
|
||||
mtspr SPRN_TBU40,r8 /* update upper 40 bits */
|
||||
|
@ -2700,7 +2713,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
|||
add r3, r3, r5
|
||||
ld r4, HSTATE_KVM_VCPU(r13)
|
||||
ld r5, HSTATE_KVM_VCORE(r13)
|
||||
ld r6, VCORE_TB_OFFSET(r5)
|
||||
ld r6, VCORE_TB_OFFSET_APPL(r5)
|
||||
subf r3, r6, r3 /* convert to host TB value */
|
||||
std r3, VCPU_DEC_EXPIRES(r4)
|
||||
|
||||
|
@ -2799,7 +2812,7 @@ END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
|
|||
/* Restore guest decrementer */
|
||||
ld r3, VCPU_DEC_EXPIRES(r4)
|
||||
ld r5, HSTATE_KVM_VCORE(r13)
|
||||
ld r6, VCORE_TB_OFFSET(r5)
|
||||
ld r6, VCORE_TB_OFFSET_APPL(r5)
|
||||
add r3, r3, r6 /* convert host TB to guest TB value */
|
||||
mftb r7
|
||||
subf r3, r7, r3
|
||||
|
@ -3606,12 +3619,9 @@ kvmppc_fix_pmao:
|
|||
*/
|
||||
kvmhv_start_timing:
|
||||
ld r5, HSTATE_KVM_VCORE(r13)
|
||||
lbz r6, VCORE_IN_GUEST(r5)
|
||||
cmpwi r6, 0
|
||||
beq 5f /* if in guest, need to */
|
||||
ld r6, VCORE_TB_OFFSET(r5) /* subtract timebase offset */
|
||||
5: mftb r5
|
||||
subf r5, r6, r5
|
||||
ld r6, VCORE_TB_OFFSET_APPL(r5)
|
||||
mftb r5
|
||||
subf r5, r6, r5 /* subtract current timebase offset */
|
||||
std r3, VCPU_CUR_ACTIVITY(r4)
|
||||
std r5, VCPU_ACTIVITY_START(r4)
|
||||
blr
|
||||
|
@ -3622,15 +3632,12 @@ kvmhv_start_timing:
|
|||
*/
|
||||
kvmhv_accumulate_time:
|
||||
ld r5, HSTATE_KVM_VCORE(r13)
|
||||
lbz r8, VCORE_IN_GUEST(r5)
|
||||
cmpwi r8, 0
|
||||
beq 4f /* if in guest, need to */
|
||||
ld r8, VCORE_TB_OFFSET(r5) /* subtract timebase offset */
|
||||
4: ld r5, VCPU_CUR_ACTIVITY(r4)
|
||||
ld r8, VCORE_TB_OFFSET_APPL(r5)
|
||||
ld r5, VCPU_CUR_ACTIVITY(r4)
|
||||
ld r6, VCPU_ACTIVITY_START(r4)
|
||||
std r3, VCPU_CUR_ACTIVITY(r4)
|
||||
mftb r7
|
||||
subf r7, r8, r7
|
||||
subf r7, r8, r7 /* subtract current timebase offset */
|
||||
std r7, VCPU_ACTIVITY_START(r4)
|
||||
cmpdi r5, 0
|
||||
beqlr
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#define XGLUE(a,b) a##b
|
||||
#define GLUE(a,b) XGLUE(a,b)
|
||||
|
||||
/* Dummy interrupt used when taking interrupts out of a queue in H_CPPR */
|
||||
#define XICS_DUMMY 1
|
||||
|
||||
static void GLUE(X_PFX,ack_pending)(struct kvmppc_xive_vcpu *xc)
|
||||
{
|
||||
u8 cppr;
|
||||
|
@ -205,6 +208,10 @@ static u32 GLUE(X_PFX,scan_interrupts)(struct kvmppc_xive_vcpu *xc,
|
|||
goto skip_ipi;
|
||||
}
|
||||
|
||||
/* If it's the dummy interrupt, continue searching */
|
||||
if (hirq == XICS_DUMMY)
|
||||
goto skip_ipi;
|
||||
|
||||
/* If fetching, update queue pointers */
|
||||
if (scan_type == scan_fetch) {
|
||||
q->idx = idx;
|
||||
|
@ -385,9 +392,76 @@ static void GLUE(X_PFX,push_pending_to_hw)(struct kvmppc_xive_vcpu *xc)
|
|||
__x_writeb(prio, __x_tima + TM_SPC_SET_OS_PENDING);
|
||||
}
|
||||
|
||||
static void GLUE(X_PFX,scan_for_rerouted_irqs)(struct kvmppc_xive *xive,
|
||||
struct kvmppc_xive_vcpu *xc)
|
||||
{
|
||||
unsigned int prio;
|
||||
|
||||
/* For each priority that is now masked */
|
||||
for (prio = xc->cppr; prio < KVMPPC_XIVE_Q_COUNT; prio++) {
|
||||
struct xive_q *q = &xc->queues[prio];
|
||||
struct kvmppc_xive_irq_state *state;
|
||||
struct kvmppc_xive_src_block *sb;
|
||||
u32 idx, toggle, entry, irq, hw_num;
|
||||
struct xive_irq_data *xd;
|
||||
__be32 *qpage;
|
||||
u16 src;
|
||||
|
||||
idx = q->idx;
|
||||
toggle = q->toggle;
|
||||
qpage = READ_ONCE(q->qpage);
|
||||
if (!qpage)
|
||||
continue;
|
||||
|
||||
/* For each interrupt in the queue */
|
||||
for (;;) {
|
||||
entry = be32_to_cpup(qpage + idx);
|
||||
|
||||
/* No more ? */
|
||||
if ((entry >> 31) == toggle)
|
||||
break;
|
||||
irq = entry & 0x7fffffff;
|
||||
|
||||
/* Skip dummies and IPIs */
|
||||
if (irq == XICS_DUMMY || irq == XICS_IPI)
|
||||
goto next;
|
||||
sb = kvmppc_xive_find_source(xive, irq, &src);
|
||||
if (!sb)
|
||||
goto next;
|
||||
state = &sb->irq_state[src];
|
||||
|
||||
/* Has it been rerouted ? */
|
||||
if (xc->server_num == state->act_server)
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* Allright, it *has* been re-routed, kill it from
|
||||
* the queue.
|
||||
*/
|
||||
qpage[idx] = cpu_to_be32((entry & 0x80000000) | XICS_DUMMY);
|
||||
|
||||
/* Find the HW interrupt */
|
||||
kvmppc_xive_select_irq(state, &hw_num, &xd);
|
||||
|
||||
/* If it's not an LSI, set PQ to 11 the EOI will force a resend */
|
||||
if (!(xd->flags & XIVE_IRQ_FLAG_LSI))
|
||||
GLUE(X_PFX,esb_load)(xd, XIVE_ESB_SET_PQ_11);
|
||||
|
||||
/* EOI the source */
|
||||
GLUE(X_PFX,source_eoi)(hw_num, xd);
|
||||
|
||||
next:
|
||||
idx = (idx + 1) & q->msk;
|
||||
if (idx == 0)
|
||||
toggle ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
X_STATIC int GLUE(X_PFX,h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr)
|
||||
{
|
||||
struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
|
||||
struct kvmppc_xive *xive = vcpu->kvm->arch.xive;
|
||||
u8 old_cppr;
|
||||
|
||||
pr_devel("H_CPPR(cppr=%ld)\n", cppr);
|
||||
|
@ -407,14 +481,34 @@ X_STATIC int GLUE(X_PFX,h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr)
|
|||
*/
|
||||
smp_mb();
|
||||
|
||||
/*
|
||||
* We are masking less, we need to look for pending things
|
||||
* to deliver and set VP pending bits accordingly to trigger
|
||||
* a new interrupt otherwise we might miss MFRR changes for
|
||||
* which we have optimized out sending an IPI signal.
|
||||
*/
|
||||
if (cppr > old_cppr)
|
||||
if (cppr > old_cppr) {
|
||||
/*
|
||||
* We are masking less, we need to look for pending things
|
||||
* to deliver and set VP pending bits accordingly to trigger
|
||||
* a new interrupt otherwise we might miss MFRR changes for
|
||||
* which we have optimized out sending an IPI signal.
|
||||
*/
|
||||
GLUE(X_PFX,push_pending_to_hw)(xc);
|
||||
} else {
|
||||
/*
|
||||
* We are masking more, we need to check the queue for any
|
||||
* interrupt that has been routed to another CPU, take
|
||||
* it out (replace it with the dummy) and retrigger it.
|
||||
*
|
||||
* This is necessary since those interrupts may otherwise
|
||||
* never be processed, at least not until this CPU restores
|
||||
* its CPPR.
|
||||
*
|
||||
* This is in theory racy vs. HW adding new interrupts to
|
||||
* the queue. In practice this works because the interesting
|
||||
* cases are when the guest has done a set_xive() to move the
|
||||
* interrupt away, which flushes the xive, followed by the
|
||||
* target CPU doing a H_CPPR. So any new interrupt coming into
|
||||
* the queue must still be routed to us and isn't a source
|
||||
* of concern.
|
||||
*/
|
||||
GLUE(X_PFX,scan_for_rerouted_irqs)(xive, xc);
|
||||
}
|
||||
|
||||
/* Apply new CPPR */
|
||||
xc->hw_cppr = cppr;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/security_features.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
struct fixup_entry {
|
||||
|
@ -117,6 +118,120 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void do_stf_entry_barrier_fixups(enum stf_barrier_type types)
|
||||
{
|
||||
unsigned int instrs[3], *dest;
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___stf_entry_barrier_fixup),
|
||||
end = PTRRELOC(&__stop___stf_entry_barrier_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
|
||||
i = 0;
|
||||
if (types & STF_BARRIER_FALLBACK) {
|
||||
instrs[i++] = 0x7d4802a6; /* mflr r10 */
|
||||
instrs[i++] = 0x60000000; /* branch patched below */
|
||||
instrs[i++] = 0x7d4803a6; /* mtlr r10 */
|
||||
} else if (types & STF_BARRIER_EIEIO) {
|
||||
instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */
|
||||
} else if (types & STF_BARRIER_SYNC_ORI) {
|
||||
instrs[i++] = 0x7c0004ac; /* hwsync */
|
||||
instrs[i++] = 0xe94d0000; /* ld r10,0(r13) */
|
||||
instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
|
||||
}
|
||||
|
||||
for (i = 0; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction(dest, instrs[0]);
|
||||
|
||||
if (types & STF_BARRIER_FALLBACK)
|
||||
patch_branch(dest + 1, (unsigned long)&stf_barrier_fallback,
|
||||
BRANCH_SET_LINK);
|
||||
else
|
||||
patch_instruction(dest + 1, instrs[1]);
|
||||
|
||||
patch_instruction(dest + 2, instrs[2]);
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s barrier)\n", i,
|
||||
(types == STF_BARRIER_NONE) ? "no" :
|
||||
(types == STF_BARRIER_FALLBACK) ? "fallback" :
|
||||
(types == STF_BARRIER_EIEIO) ? "eieio" :
|
||||
(types == (STF_BARRIER_SYNC_ORI)) ? "hwsync"
|
||||
: "unknown");
|
||||
}
|
||||
|
||||
void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
|
||||
{
|
||||
unsigned int instrs[6], *dest;
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___stf_exit_barrier_fixup),
|
||||
end = PTRRELOC(&__stop___stf_exit_barrier_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
instrs[3] = 0x60000000; /* nop */
|
||||
instrs[4] = 0x60000000; /* nop */
|
||||
instrs[5] = 0x60000000; /* nop */
|
||||
|
||||
i = 0;
|
||||
if (types & STF_BARRIER_FALLBACK || types & STF_BARRIER_SYNC_ORI) {
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE)) {
|
||||
instrs[i++] = 0x7db14ba6; /* mtspr 0x131, r13 (HSPRG1) */
|
||||
instrs[i++] = 0x7db04aa6; /* mfspr r13, 0x130 (HSPRG0) */
|
||||
} else {
|
||||
instrs[i++] = 0x7db243a6; /* mtsprg 2,r13 */
|
||||
instrs[i++] = 0x7db142a6; /* mfsprg r13,1 */
|
||||
}
|
||||
instrs[i++] = 0x7c0004ac; /* hwsync */
|
||||
instrs[i++] = 0xe9ad0000; /* ld r13,0(r13) */
|
||||
instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE)) {
|
||||
instrs[i++] = 0x7db14aa6; /* mfspr r13, 0x131 (HSPRG1) */
|
||||
} else {
|
||||
instrs[i++] = 0x7db242a6; /* mfsprg r13,2 */
|
||||
}
|
||||
} else if (types & STF_BARRIER_EIEIO) {
|
||||
instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */
|
||||
}
|
||||
|
||||
for (i = 0; start < end; start++, i++) {
|
||||
dest = (void *)start + *start;
|
||||
|
||||
pr_devel("patching dest %lx\n", (unsigned long)dest);
|
||||
|
||||
patch_instruction(dest, instrs[0]);
|
||||
patch_instruction(dest + 1, instrs[1]);
|
||||
patch_instruction(dest + 2, instrs[2]);
|
||||
patch_instruction(dest + 3, instrs[3]);
|
||||
patch_instruction(dest + 4, instrs[4]);
|
||||
patch_instruction(dest + 5, instrs[5]);
|
||||
}
|
||||
printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i,
|
||||
(types == STF_BARRIER_NONE) ? "no" :
|
||||
(types == STF_BARRIER_FALLBACK) ? "fallback" :
|
||||
(types == STF_BARRIER_EIEIO) ? "eieio" :
|
||||
(types == (STF_BARRIER_SYNC_ORI)) ? "hwsync"
|
||||
: "unknown");
|
||||
}
|
||||
|
||||
|
||||
void do_stf_barrier_fixups(enum stf_barrier_type types)
|
||||
{
|
||||
do_stf_entry_barrier_fixups(types);
|
||||
do_stf_exit_barrier_fixups(types);
|
||||
}
|
||||
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
{
|
||||
unsigned int instrs[3], *dest;
|
||||
|
|
|
@ -131,6 +131,7 @@ static void __init pnv_setup_arch(void)
|
|||
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
|
||||
|
||||
pnv_setup_rfi_flush();
|
||||
setup_stf_barrier();
|
||||
|
||||
/* Initialize SMP */
|
||||
pnv_smp_init();
|
||||
|
|
|
@ -710,6 +710,7 @@ static void __init pSeries_setup_arch(void)
|
|||
fwnmi_init();
|
||||
|
||||
pseries_setup_rfi_flush();
|
||||
setup_stf_barrier();
|
||||
|
||||
/* By default, only probe PCI (can be overridden by rtas_pci) */
|
||||
pci_add_flags(PCI_PROBE_ONLY);
|
||||
|
|
|
@ -578,7 +578,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
|
|||
|
||||
gpa = READ_ONCE(scb_o->itdba) & ~0xffUL;
|
||||
if (gpa && (scb_s->ecb & ECB_TE)) {
|
||||
if (!(gpa & ~0x1fffU)) {
|
||||
if (!(gpa & ~0x1fffUL)) {
|
||||
rc = set_validity_icpt(scb_s, 0x0080U);
|
||||
goto unpin;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ LDFLAGS_purgatory.ro += -z nodefaultlib
|
|||
KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes
|
||||
KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
|
||||
KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding
|
||||
KBUILD_CFLAGS += -c -MD -Os -m64
|
||||
KBUILD_CFLAGS += -c -MD -Os -m64 -msoft-float
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
|
||||
|
||||
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
|
||||
|
|
|
@ -198,7 +198,6 @@
|
|||
#define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation Technology L2 */
|
||||
#define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data Prioritization L3 */
|
||||
#define X86_FEATURE_INVPCID_SINGLE ( 7*32+ 7) /* Effectively INVPCID && CR4.PCIDE=1 */
|
||||
|
||||
#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
|
||||
#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
|
||||
#define X86_FEATURE_SME ( 7*32+10) /* AMD Secure Memory Encryption */
|
||||
|
@ -207,13 +206,19 @@
|
|||
#define X86_FEATURE_RETPOLINE_AMD ( 7*32+13) /* "" AMD Retpoline mitigation for Spectre variant 2 */
|
||||
#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
|
||||
#define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */
|
||||
|
||||
#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_MBA ( 7*32+18) /* Memory Bandwidth Allocation */
|
||||
#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */
|
||||
#define X86_FEATURE_SEV ( 7*32+20) /* AMD Secure Encrypted Virtualization */
|
||||
|
||||
#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 via LS_CFG MSR */
|
||||
#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) */
|
||||
|
||||
/* Virtualization flags: Linux defined, word 8 */
|
||||
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
|
||||
|
@ -274,9 +279,10 @@
|
|||
#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */
|
||||
#define X86_FEATURE_IRPERF (13*32+ 1) /* Instructions Retired Count */
|
||||
#define X86_FEATURE_XSAVEERPTR (13*32+ 2) /* Always save/restore FP error pointers */
|
||||
#define X86_FEATURE_IBPB (13*32+12) /* Indirect Branch Prediction Barrier */
|
||||
#define X86_FEATURE_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */
|
||||
#define X86_FEATURE_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */
|
||||
#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 */
|
||||
|
@ -334,6 +340,7 @@
|
|||
#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_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)
|
||||
|
@ -363,5 +370,6 @@
|
|||
#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 */
|
||||
|
||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||
|
|
|
@ -924,7 +924,7 @@ struct kvm_x86_ops {
|
|||
int (*hardware_setup)(void); /* __init */
|
||||
void (*hardware_unsetup)(void); /* __exit */
|
||||
bool (*cpu_has_accelerated_tpr)(void);
|
||||
bool (*cpu_has_high_real_mode_segbase)(void);
|
||||
bool (*has_emulated_msr)(int index);
|
||||
void (*cpuid_update)(struct kvm_vcpu *vcpu);
|
||||
|
||||
struct kvm *(*vm_alloc)(void);
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#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 */
|
||||
|
@ -68,6 +70,11 @@
|
|||
#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
|
||||
|
@ -340,6 +347,8 @@
|
|||
#define MSR_AMD64_SEV_ENABLED_BIT 0
|
||||
#define MSR_AMD64_SEV_ENABLED BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
|
||||
|
||||
#define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f
|
||||
|
||||
/* Fam 17h MSRs */
|
||||
#define MSR_F17H_IRPERF 0xc00000e9
|
||||
|
||||
|
|
|
@ -217,6 +217,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[];
|
||||
|
||||
|
@ -241,22 +249,27 @@ static inline void vmexit_fill_RSB(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#define alternative_msr_write(_msr, _val, _feature) \
|
||||
asm volatile(ALTERNATIVE("", \
|
||||
"movl %[msr], %%ecx\n\t" \
|
||||
"movl %[val], %%eax\n\t" \
|
||||
"movl $0, %%edx\n\t" \
|
||||
"wrmsr", \
|
||||
_feature) \
|
||||
: : [msr] "i" (_msr), [val] "i" (_val) \
|
||||
: "eax", "ecx", "edx", "memory")
|
||||
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)
|
||||
{
|
||||
alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB,
|
||||
X86_FEATURE_USE_IBPB);
|
||||
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.
|
||||
|
@ -265,14 +278,18 @@ static inline void indirect_branch_prediction_barrier(void)
|
|||
*/
|
||||
#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, SPEC_CTRL_IBRS, \
|
||||
alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \
|
||||
X86_FEATURE_USE_IBRS_FW); \
|
||||
} while (0)
|
||||
|
||||
#define firmware_restrict_branch_speculation_end() \
|
||||
do { \
|
||||
alternative_msr_write(MSR_IA32_SPEC_CTRL, 0, \
|
||||
u64 val = x86_spec_ctrl_base; \
|
||||
\
|
||||
alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \
|
||||
X86_FEATURE_USE_IBRS_FW); \
|
||||
preempt_enable(); \
|
||||
} while (0)
|
||||
|
|
|
@ -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
|
|
@ -79,6 +79,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 */
|
||||
|
@ -105,6 +106,7 @@ struct thread_info {
|
|||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||
#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)
|
||||
|
@ -144,7 +146,7 @@ struct thread_info {
|
|||
|
||||
/* flags to check in __switch_to() */
|
||||
#define _TIF_WORK_CTXSW \
|
||||
(_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP)
|
||||
(_TIF_IO_BITMAP|_TIF_NOCPUID|_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)
|
||||
|
|
|
@ -10,6 +10,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>
|
||||
|
@ -554,6 +555,26 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
|
|||
rdmsrl(MSR_FAM10H_NODE_ID, value);
|
||||
nodes_per_socket = ((value >> 3) & 7) + 1;
|
||||
}
|
||||
|
||||
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_detect_mem_encrypt(struct cpuinfo_x86 *c)
|
||||
|
@ -791,6 +812,7 @@ 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.
|
||||
|
|
|
@ -12,8 +12,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>
|
||||
|
@ -27,6 +29,27 @@
|
|||
#include <asm/intel-family.h>
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void);
|
||||
static void __init ssb_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 __ro_after_init 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 __ro_after_init 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 __ro_after_init x86_amd_ls_cfg_base;
|
||||
u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask;
|
||||
|
||||
void __init check_bugs(void)
|
||||
{
|
||||
|
@ -37,9 +60,27 @@ 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();
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
* Check whether we are able to run this kernel safely on SMP.
|
||||
|
@ -93,7 +134,76 @@ static const char *spectre_v2_strings[] = {
|
|||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "Spectre V2 : " fmt
|
||||
|
||||
static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
|
||||
static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
|
||||
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;
|
||||
|
@ -312,32 +422,289 @@ static void __init spectre_v2_select_mitigation(void)
|
|||
}
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "Speculative Store Bypass: " fmt
|
||||
|
||||
static enum ssb_mitigation ssb_mode __ro_after_init = 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();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
|
||||
char *buf, unsigned int bug)
|
||||
{
|
||||
if (!boot_cpu_has_bug(bug))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
|
||||
switch (bug) {
|
||||
case X86_BUG_CPU_MELTDOWN:
|
||||
if (boot_cpu_has(X86_FEATURE_PTI))
|
||||
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]);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
if (boot_cpu_has(X86_FEATURE_PTI))
|
||||
return sprintf(buf, "Mitigation: PTI\n");
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
return cpu_show_common(dev, attr, buf, X86_BUG_CPU_MELTDOWN);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v1(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_SPECTRE_V1);
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v2(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_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());
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -757,17 +757,32 @@ static void init_speculation_control(struct cpuinfo_x86 *c)
|
|||
* 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.
|
||||
*
|
||||
* We use the AMD bits in 0x8000_0008 EBX as the generic hardware
|
||||
* features, which are visible in /proc/cpuinfo and used by the
|
||||
* kernel. So set those accordingly from the Intel bits.
|
||||
*/
|
||||
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) ||
|
||||
cpu_has(c, X86_FEATURE_VIRT_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)
|
||||
|
@ -927,21 +942,47 @@ static const __initconst struct x86_cpu_id cpu_no_meltdown[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static bool __init cpu_vulnerable_to_meltdown(struct cpuinfo_x86 *c)
|
||||
/* Only list CPUs which speculate but are non susceptible to SSB */
|
||||
static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = {
|
||||
{ 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_AMD, 0x12, },
|
||||
{ X86_VENDOR_AMD, 0x11, },
|
||||
{ X86_VENDOR_AMD, 0x10, },
|
||||
{ X86_VENDOR_AMD, 0xf, },
|
||||
{}
|
||||
};
|
||||
|
||||
static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 ia32_cap = 0;
|
||||
|
||||
if (x86_match_cpu(cpu_no_meltdown))
|
||||
return false;
|
||||
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 (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_meltdown))
|
||||
return;
|
||||
|
||||
/* Rogue Data Cache Load? No! */
|
||||
if (ia32_cap & ARCH_CAP_RDCL_NO)
|
||||
return false;
|
||||
return;
|
||||
|
||||
return true;
|
||||
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -992,12 +1033,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
|
|||
|
||||
setup_force_cpu_cap(X86_FEATURE_ALWAYS);
|
||||
|
||||
if (!x86_match_cpu(cpu_no_speculation)) {
|
||||
if (cpu_vulnerable_to_meltdown(c))
|
||||
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);
|
||||
|
||||
|
@ -1359,6 +1395,7 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
|
|||
#endif
|
||||
mtrr_ap_init();
|
||||
validate_apic_and_package_id(c);
|
||||
x86_spec_ctrl_setup_ap();
|
||||
}
|
||||
|
||||
static __init int setup_noclflush(char *arg)
|
||||
|
|
|
@ -50,4 +50,6 @@ extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
|
|||
|
||||
unsigned int aperfmperf_get_khz(int cpu);
|
||||
|
||||
extern void x86_spec_ctrl_setup_ap(void);
|
||||
|
||||
#endif /* ARCH_X86_CPU_H */
|
||||
|
|
|
@ -188,7 +188,10 @@ static void early_init_intel(struct cpuinfo_x86 *c)
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <asm/switch_to.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/prctl.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
/*
|
||||
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
|
||||
|
@ -278,6 +279,148 @@ static inline void switch_to_bitmap(struct tss_struct *tss,
|
|||
}
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
|
@ -309,6 +452,9 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
|||
|
||||
if ((tifp ^ tifn) & _TIF_NOCPUID)
|
||||
set_cpuid_faulting(!!(tifn & _TIF_NOCPUID));
|
||||
|
||||
if ((tifp ^ tifn) & _TIF_SSBD)
|
||||
__speculative_store_bypass_update(tifn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include <asm/qspinlock.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
/* Number of siblings per CPU package */
|
||||
int smp_num_siblings = 1;
|
||||
|
@ -244,6 +245,8 @@ static void notrace start_secondary(void *unused)
|
|||
*/
|
||||
check_tsc_sync_target();
|
||||
|
||||
speculative_store_bypass_ht_init();
|
||||
|
||||
/*
|
||||
* Lock vector_lock, set CPU online and bring the vector
|
||||
* allocator online. Online must be set with vector_lock held
|
||||
|
@ -1292,6 +1295,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)
|
||||
|
|
|
@ -379,7 +379,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
|
||||
/* cpuid 0x80000008.ebx */
|
||||
const u32 kvm_cpuid_8000_0008_ebx_x86_features =
|
||||
F(IBPB) | F(IBRS);
|
||||
F(AMD_IBPB) | F(AMD_IBRS) | F(VIRT_SSBD);
|
||||
|
||||
/* cpuid 0xC0000001.edx */
|
||||
const u32 kvm_cpuid_C000_0001_edx_x86_features =
|
||||
|
@ -408,7 +408,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
/* cpuid 7.0.edx*/
|
||||
const u32 kvm_cpuid_7_0_edx_x86_features =
|
||||
F(AVX512_4VNNIW) | F(AVX512_4FMAPS) | F(SPEC_CTRL) |
|
||||
F(ARCH_CAPABILITIES);
|
||||
F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES);
|
||||
|
||||
/* all calls to cpuid_count() should be made on the same cpu */
|
||||
get_cpu();
|
||||
|
@ -495,6 +495,11 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
entry->ecx &= ~F(PKU);
|
||||
entry->edx &= kvm_cpuid_7_0_edx_x86_features;
|
||||
cpuid_mask(&entry->edx, CPUID_7_EDX);
|
||||
/*
|
||||
* We emulate ARCH_CAPABILITIES in software even
|
||||
* if the host doesn't support it.
|
||||
*/
|
||||
entry->edx |= F(ARCH_CAPABILITIES);
|
||||
} else {
|
||||
entry->ebx = 0;
|
||||
entry->ecx = 0;
|
||||
|
@ -647,13 +652,20 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
|
|||
g_phys_as = phys_as;
|
||||
entry->eax = g_phys_as | (virt_as << 8);
|
||||
entry->edx = 0;
|
||||
/* IBRS and IBPB aren't necessarily present in hardware cpuid */
|
||||
if (boot_cpu_has(X86_FEATURE_IBPB))
|
||||
entry->ebx |= F(IBPB);
|
||||
if (boot_cpu_has(X86_FEATURE_IBRS))
|
||||
entry->ebx |= F(IBRS);
|
||||
/*
|
||||
* IBRS, IBPB and VIRT_SSBD aren't necessarily present in
|
||||
* hardware cpuid
|
||||
*/
|
||||
if (boot_cpu_has(X86_FEATURE_AMD_IBPB))
|
||||
entry->ebx |= F(AMD_IBPB);
|
||||
if (boot_cpu_has(X86_FEATURE_AMD_IBRS))
|
||||
entry->ebx |= F(AMD_IBRS);
|
||||
if (boot_cpu_has(X86_FEATURE_VIRT_SSBD))
|
||||
entry->ebx |= F(VIRT_SSBD);
|
||||
entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features;
|
||||
cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX);
|
||||
if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD))
|
||||
entry->ebx |= F(VIRT_SSBD);
|
||||
break;
|
||||
}
|
||||
case 0x80000019:
|
||||
|
|
|
@ -1260,12 +1260,16 @@ static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
|
|||
}
|
||||
}
|
||||
|
||||
static int kvm_hv_hypercall_complete(struct kvm_vcpu *vcpu, u64 result)
|
||||
{
|
||||
kvm_hv_hypercall_set_result(vcpu, result);
|
||||
++vcpu->stat.hypercalls;
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
}
|
||||
|
||||
static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_run *run = vcpu->run;
|
||||
|
||||
kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result);
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
return kvm_hv_hypercall_complete(vcpu, vcpu->run->hyperv.u.hcall.result);
|
||||
}
|
||||
|
||||
static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param)
|
||||
|
@ -1350,7 +1354,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
|
|||
/* Hypercall continuation is not supported yet */
|
||||
if (rep_cnt || rep_idx) {
|
||||
ret = HV_STATUS_INVALID_HYPERCALL_CODE;
|
||||
goto set_result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
|
@ -1381,9 +1385,8 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
|
|||
break;
|
||||
}
|
||||
|
||||
set_result:
|
||||
kvm_hv_hypercall_set_result(vcpu, ret);
|
||||
return 1;
|
||||
out:
|
||||
return kvm_hv_hypercall_complete(vcpu, ret);
|
||||
}
|
||||
|
||||
void kvm_hv_init_vm(struct kvm *kvm)
|
||||
|
|
|
@ -1522,11 +1522,23 @@ static bool set_target_expiration(struct kvm_lapic *apic)
|
|||
|
||||
static void advance_periodic_target_expiration(struct kvm_lapic *apic)
|
||||
{
|
||||
apic->lapic_timer.tscdeadline +=
|
||||
nsec_to_cycles(apic->vcpu, apic->lapic_timer.period);
|
||||
ktime_t now = ktime_get();
|
||||
u64 tscl = rdtsc();
|
||||
ktime_t delta;
|
||||
|
||||
/*
|
||||
* Synchronize both deadlines to the same time source or
|
||||
* differences in the periods (caused by differences in the
|
||||
* underlying clocks or numerical approximation errors) will
|
||||
* cause the two to drift apart over time as the errors
|
||||
* accumulate.
|
||||
*/
|
||||
apic->lapic_timer.target_expiration =
|
||||
ktime_add_ns(apic->lapic_timer.target_expiration,
|
||||
apic->lapic_timer.period);
|
||||
delta = ktime_sub(apic->lapic_timer.target_expiration, now);
|
||||
apic->lapic_timer.tscdeadline = kvm_read_l1_tsc(apic->vcpu, tscl) +
|
||||
nsec_to_cycles(apic->vcpu, delta);
|
||||
}
|
||||
|
||||
static void start_sw_period(struct kvm_lapic *apic)
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#include <asm/debugreg.h>
|
||||
#include <asm/kvm_para.h>
|
||||
#include <asm/irq_remapping.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
|
||||
#include <asm/virtext.h>
|
||||
#include "trace.h"
|
||||
|
@ -213,6 +213,12 @@ struct vcpu_svm {
|
|||
} host;
|
||||
|
||||
u64 spec_ctrl;
|
||||
/*
|
||||
* Contains guest-controlled bits of VIRT_SPEC_CTRL, which will be
|
||||
* translated into the appropriate L2_CFG bits on the host to
|
||||
* perform speculative control.
|
||||
*/
|
||||
u64 virt_spec_ctrl;
|
||||
|
||||
u32 *msrpm;
|
||||
|
||||
|
@ -2060,6 +2066,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||
|
||||
vcpu->arch.microcode_version = 0x01000065;
|
||||
svm->spec_ctrl = 0;
|
||||
svm->virt_spec_ctrl = 0;
|
||||
|
||||
if (!init_event) {
|
||||
svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
|
||||
|
@ -4108,11 +4115,18 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
if (!msr_info->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_IBRS))
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS))
|
||||
return 1;
|
||||
|
||||
msr_info->data = svm->spec_ctrl;
|
||||
break;
|
||||
case MSR_AMD64_VIRT_SPEC_CTRL:
|
||||
if (!msr_info->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_VIRT_SSBD))
|
||||
return 1;
|
||||
|
||||
msr_info->data = svm->virt_spec_ctrl;
|
||||
break;
|
||||
case MSR_F15H_IC_CFG: {
|
||||
|
||||
int family, model;
|
||||
|
@ -4203,7 +4217,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
if (!msr->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_IBRS))
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS))
|
||||
return 1;
|
||||
|
||||
/* The STIBP bit doesn't fault even if it's not advertised */
|
||||
|
@ -4230,7 +4244,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|||
break;
|
||||
case MSR_IA32_PRED_CMD:
|
||||
if (!msr->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_IBPB))
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB))
|
||||
return 1;
|
||||
|
||||
if (data & ~PRED_CMD_IBPB)
|
||||
|
@ -4244,6 +4258,16 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|||
break;
|
||||
set_msr_interception(svm->msrpm, MSR_IA32_PRED_CMD, 0, 1);
|
||||
break;
|
||||
case MSR_AMD64_VIRT_SPEC_CTRL:
|
||||
if (!msr->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_VIRT_SSBD))
|
||||
return 1;
|
||||
|
||||
if (data & ~SPEC_CTRL_SSBD)
|
||||
return 1;
|
||||
|
||||
svm->virt_spec_ctrl = data;
|
||||
break;
|
||||
case MSR_STAR:
|
||||
svm->vmcb->save.star = data;
|
||||
break;
|
||||
|
@ -5557,8 +5581,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
* is no need to worry about the conditional branch over the wrmsr
|
||||
* being speculatively taken.
|
||||
*/
|
||||
if (svm->spec_ctrl)
|
||||
native_wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
|
||||
x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
|
||||
|
||||
asm volatile (
|
||||
"push %%" _ASM_BP "; \n\t"
|
||||
|
@ -5652,6 +5675,18 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
#endif
|
||||
);
|
||||
|
||||
/* Eliminate branch target predictions from guest mode */
|
||||
vmexit_fill_RSB();
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
wrmsrl(MSR_GS_BASE, svm->host.gs_base);
|
||||
#else
|
||||
loadsegment(fs, svm->host.fs);
|
||||
#ifndef CONFIG_X86_32_LAZY_GS
|
||||
loadsegment(gs, svm->host.gs);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We do not use IBRS in the kernel. If this vCPU has used the
|
||||
* SPEC_CTRL MSR it may have left it on; save the value and
|
||||
|
@ -5670,20 +5705,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
|
||||
svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
|
||||
|
||||
if (svm->spec_ctrl)
|
||||
native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
|
||||
|
||||
/* Eliminate branch target predictions from guest mode */
|
||||
vmexit_fill_RSB();
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
wrmsrl(MSR_GS_BASE, svm->host.gs_base);
|
||||
#else
|
||||
loadsegment(fs, svm->host.fs);
|
||||
#ifndef CONFIG_X86_32_LAZY_GS
|
||||
loadsegment(gs, svm->host.gs);
|
||||
#endif
|
||||
#endif
|
||||
x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
|
||||
|
||||
reload_tss(vcpu);
|
||||
|
||||
|
@ -5786,7 +5808,7 @@ static bool svm_cpu_has_accelerated_tpr(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool svm_has_high_real_mode_segbase(void)
|
||||
static bool svm_has_emulated_msr(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -7012,7 +7034,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
|
|||
.hardware_enable = svm_hardware_enable,
|
||||
.hardware_disable = svm_hardware_disable,
|
||||
.cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
|
||||
.cpu_has_high_real_mode_segbase = svm_has_high_real_mode_segbase,
|
||||
.has_emulated_msr = svm_has_emulated_msr,
|
||||
|
||||
.vcpu_create = svm_create_vcpu,
|
||||
.vcpu_free = svm_free_vcpu,
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include <asm/apic.h>
|
||||
#include <asm/irq_remapping.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
#include "trace.h"
|
||||
|
@ -3529,7 +3529,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||
return kvm_get_msr_common(vcpu, msr_info);
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
if (!msr_info->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_IBRS) &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
|
||||
return 1;
|
||||
|
||||
|
@ -3648,12 +3647,11 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||
break;
|
||||
case MSR_IA32_SPEC_CTRL:
|
||||
if (!msr_info->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_IBRS) &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
|
||||
return 1;
|
||||
|
||||
/* The STIBP bit doesn't fault even if it's not advertised */
|
||||
if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP))
|
||||
if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD))
|
||||
return 1;
|
||||
|
||||
vmx->spec_ctrl = data;
|
||||
|
@ -3679,7 +3677,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||
break;
|
||||
case MSR_IA32_PRED_CMD:
|
||||
if (!msr_info->host_initiated &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_IBPB) &&
|
||||
!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
|
||||
return 1;
|
||||
|
||||
|
@ -9488,9 +9485,21 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
STACK_FRAME_NON_STANDARD(vmx_handle_external_intr);
|
||||
|
||||
static bool vmx_has_high_real_mode_segbase(void)
|
||||
static bool vmx_has_emulated_msr(int index)
|
||||
{
|
||||
return enable_unrestricted_guest || emulate_invalid_guest_state;
|
||||
switch (index) {
|
||||
case MSR_IA32_SMBASE:
|
||||
/*
|
||||
* We cannot do SMM unless we can run the guest in big
|
||||
* real mode.
|
||||
*/
|
||||
return enable_unrestricted_guest || emulate_invalid_guest_state;
|
||||
case MSR_AMD64_VIRT_SPEC_CTRL:
|
||||
/* This is AMD only. */
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool vmx_mpx_supported(void)
|
||||
|
@ -9722,8 +9731,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
* is no need to worry about the conditional branch over the wrmsr
|
||||
* being speculatively taken.
|
||||
*/
|
||||
if (vmx->spec_ctrl)
|
||||
native_wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
|
||||
x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
|
||||
|
||||
vmx->__launched = vmx->loaded_vmcs->launched;
|
||||
|
||||
|
@ -9871,8 +9879,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
|||
if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
|
||||
vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
|
||||
|
||||
if (vmx->spec_ctrl)
|
||||
native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
|
||||
x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0);
|
||||
|
||||
/* Eliminate branch target predictions from guest mode */
|
||||
vmexit_fill_RSB();
|
||||
|
@ -12632,7 +12639,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
|
|||
.hardware_enable = hardware_enable,
|
||||
.hardware_disable = hardware_disable,
|
||||
.cpu_has_accelerated_tpr = report_flexpriority,
|
||||
.cpu_has_high_real_mode_segbase = vmx_has_high_real_mode_segbase,
|
||||
.has_emulated_msr = vmx_has_emulated_msr,
|
||||
|
||||
.vm_init = vmx_vm_init,
|
||||
.vm_alloc = vmx_vm_alloc,
|
||||
|
|
|
@ -1061,6 +1061,7 @@ static u32 emulated_msrs[] = {
|
|||
MSR_SMI_COUNT,
|
||||
MSR_PLATFORM_INFO,
|
||||
MSR_MISC_FEATURES_ENABLES,
|
||||
MSR_AMD64_VIRT_SPEC_CTRL,
|
||||
};
|
||||
|
||||
static unsigned num_emulated_msrs;
|
||||
|
@ -2906,7 +2907,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||
* fringe case that is not enabled except via specific settings
|
||||
* of the module parameters.
|
||||
*/
|
||||
r = kvm_x86_ops->cpu_has_high_real_mode_segbase();
|
||||
r = kvm_x86_ops->has_emulated_msr(MSR_IA32_SMBASE);
|
||||
break;
|
||||
case KVM_CAP_VAPIC:
|
||||
r = !kvm_x86_ops->cpu_has_accelerated_tpr();
|
||||
|
@ -4606,14 +4607,8 @@ static void kvm_init_msr_list(void)
|
|||
num_msrs_to_save = j;
|
||||
|
||||
for (i = j = 0; i < ARRAY_SIZE(emulated_msrs); i++) {
|
||||
switch (emulated_msrs[i]) {
|
||||
case MSR_IA32_SMBASE:
|
||||
if (!kvm_x86_ops->cpu_has_high_real_mode_segbase())
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!kvm_x86_ops->has_emulated_msr(emulated_msrs[i]))
|
||||
continue;
|
||||
|
||||
if (j < i)
|
||||
emulated_msrs[j] = emulated_msrs[i];
|
||||
|
@ -6676,11 +6671,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
|
|||
unsigned long nr, a0, a1, a2, a3, ret;
|
||||
int op_64_bit;
|
||||
|
||||
if (kvm_hv_hypercall_enabled(vcpu->kvm)) {
|
||||
if (!kvm_hv_hypercall(vcpu))
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
if (kvm_hv_hypercall_enabled(vcpu->kvm))
|
||||
return kvm_hv_hypercall(vcpu);
|
||||
|
||||
nr = kvm_register_read(vcpu, VCPU_REGS_RAX);
|
||||
a0 = kvm_register_read(vcpu, VCPU_REGS_RBX);
|
||||
|
@ -6701,7 +6693,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
|
|||
|
||||
if (kvm_x86_ops->get_cpl(vcpu) != 0) {
|
||||
ret = -KVM_EPERM;
|
||||
goto out_error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (nr) {
|
||||
|
@ -6721,12 +6713,11 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
|
|||
ret = -KVM_ENOSYS;
|
||||
break;
|
||||
}
|
||||
out_error:
|
||||
out:
|
||||
if (!op_64_bit)
|
||||
ret = (u32)ret;
|
||||
kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
|
||||
|
||||
out:
|
||||
++vcpu->stat.hypercalls;
|
||||
return kvm_skip_emulated_instruction(vcpu);
|
||||
}
|
||||
|
@ -7985,6 +7976,7 @@ static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
|
|||
{
|
||||
struct msr_data apic_base_msr;
|
||||
int mmu_reset_needed = 0;
|
||||
int cpuid_update_needed = 0;
|
||||
int pending_vec, max_bits, idx;
|
||||
struct desc_ptr dt;
|
||||
int ret = -EINVAL;
|
||||
|
@ -8023,8 +8015,10 @@ static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
|
|||
vcpu->arch.cr0 = sregs->cr0;
|
||||
|
||||
mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
|
||||
cpuid_update_needed |= ((kvm_read_cr4(vcpu) ^ sregs->cr4) &
|
||||
(X86_CR4_OSXSAVE | X86_CR4_PKE));
|
||||
kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
|
||||
if (sregs->cr4 & (X86_CR4_OSXSAVE | X86_CR4_PKE))
|
||||
if (cpuid_update_needed)
|
||||
kvm_update_cpuid(vcpu);
|
||||
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
|
|
|
@ -334,6 +334,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci_mobile }, /* Lynx LP RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci_mobile }, /* Lynx LP RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci_mobile }, /* Lynx LP RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x9dd3), board_ahci_mobile }, /* Cannon Lake PCH-LP AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue