mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
Merge branch 'linux-linaro-lsk-v4.4' into linux-linaro-lsk-v4.4-android
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Conflicts:
fs/f2fs/extent_cache.c
Pick changes from AOSP Change-Id: Icd8a85ac0c19a8aa25cd2591a12b4e9b85bdf1c5
("f2fs: catch up to v4.14-rc1")
fs/f2fs/namei.c
Pick changes from AOSP F2FS backport commit 7d5c08fd91
("f2fs: backport from (4c1fad64 - Merge tag 'for-f2fs-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs)")
This commit is contained in:
commit
24740dab5c
|
|
@ -58,6 +58,6 @@ Example:
|
|||
interrupts = <0 35 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dmahost 12 0 1>,
|
||||
<&dmahost 13 0 1 0>;
|
||||
<&dmahost 13 1 0>;
|
||||
dma-names = "rx", "rx";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ data_err=ignore(*) Just print an error message if an error occurs
|
|||
data_err=abort Abort the journal if an error occurs in a file
|
||||
data buffer in ordered mode.
|
||||
|
||||
grpid Give objects the same group ID as their creator.
|
||||
grpid New objects have the group ID of their parent.
|
||||
bsdgroups
|
||||
|
||||
nogrpid (*) New objects have the group ID of their creator.
|
||||
|
|
|
|||
|
|
@ -2571,8 +2571,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
norandmaps Don't use address space randomization. Equivalent to
|
||||
echo 0 > /proc/sys/kernel/randomize_va_space
|
||||
|
||||
noreplace-paravirt [X86,IA-64,PV_OPS] Don't patch paravirt_ops
|
||||
|
||||
noreplace-smp [X86-32,SMP] Don't replace SMP instructions
|
||||
with UP alternatives
|
||||
|
||||
|
|
|
|||
90
Documentation/speculation.txt
Normal file
90
Documentation/speculation.txt
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
This document explains potential effects of speculation, and how undesirable
|
||||
effects can be mitigated portably using common APIs.
|
||||
|
||||
===========
|
||||
Speculation
|
||||
===========
|
||||
|
||||
To improve performance and minimize average latencies, many contemporary CPUs
|
||||
employ speculative execution techniques such as branch prediction, performing
|
||||
work which may be discarded at a later stage.
|
||||
|
||||
Typically speculative execution cannot be observed from architectural state,
|
||||
such as the contents of registers. However, in some cases it is possible to
|
||||
observe its impact on microarchitectural state, such as the presence or
|
||||
absence of data in caches. Such state may form side-channels which can be
|
||||
observed to extract secret information.
|
||||
|
||||
For example, in the presence of branch prediction, it is possible for bounds
|
||||
checks to be ignored by code which is speculatively executed. Consider the
|
||||
following code:
|
||||
|
||||
int load_array(int *array, unsigned int index)
|
||||
{
|
||||
if (index >= MAX_ARRAY_ELEMS)
|
||||
return 0;
|
||||
else
|
||||
return array[index];
|
||||
}
|
||||
|
||||
Which, on arm64, may be compiled to an assembly sequence such as:
|
||||
|
||||
CMP <index>, #MAX_ARRAY_ELEMS
|
||||
B.LT less
|
||||
MOV <returnval>, #0
|
||||
RET
|
||||
less:
|
||||
LDR <returnval>, [<array>, <index>]
|
||||
RET
|
||||
|
||||
It is possible that a CPU mis-predicts the conditional branch, and
|
||||
speculatively loads array[index], even if index >= MAX_ARRAY_ELEMS. This
|
||||
value will subsequently be discarded, but the speculated load may affect
|
||||
microarchitectural state which can be subsequently measured.
|
||||
|
||||
More complex sequences involving multiple dependent memory accesses may
|
||||
result in sensitive information being leaked. Consider the following
|
||||
code, building on the prior example:
|
||||
|
||||
int load_dependent_arrays(int *arr1, int *arr2, int index)
|
||||
{
|
||||
int val1, val2,
|
||||
|
||||
val1 = load_array(arr1, index);
|
||||
val2 = load_array(arr2, val1);
|
||||
|
||||
return val2;
|
||||
}
|
||||
|
||||
Under speculation, the first call to load_array() may return the value
|
||||
of an out-of-bounds address, while the second call will influence
|
||||
microarchitectural state dependent on this value. This may provide an
|
||||
arbitrary read primitive.
|
||||
|
||||
====================================
|
||||
Mitigating speculation side-channels
|
||||
====================================
|
||||
|
||||
The kernel provides a generic API to ensure that bounds checks are
|
||||
respected even under speculation. Architectures which are affected by
|
||||
speculation-based side-channels are expected to implement these
|
||||
primitives.
|
||||
|
||||
The array_index_nospec() helper in <linux/nospec.h> can be used to
|
||||
prevent information from being leaked via side-channels.
|
||||
|
||||
A call to array_index_nospec(index, size) returns a sanitized index
|
||||
value that is bounded to [0, size) even under cpu speculation
|
||||
conditions.
|
||||
|
||||
This can be used to protect the earlier load_array() example:
|
||||
|
||||
int load_array(int *array, unsigned int index)
|
||||
{
|
||||
if (index >= MAX_ARRAY_ELEMS)
|
||||
return 0;
|
||||
else {
|
||||
index = array_index_nospec(index, MAX_ARRAY_ELEMS);
|
||||
return array[index];
|
||||
}
|
||||
}
|
||||
8
Makefile
8
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 114
|
||||
SUBLEVEL = 120
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
@ -87,10 +87,12 @@ endif
|
|||
ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
|
||||
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
|
||||
quiet=silent_
|
||||
tools_silent=s
|
||||
endif
|
||||
else # make-3.8x
|
||||
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
|
||||
quiet=silent_
|
||||
tools_silent=-s
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
@ -1548,11 +1550,11 @@ image_name:
|
|||
# Clear a bunch of variables before executing the submake
|
||||
tools/: FORCE
|
||||
$(Q)mkdir -p $(objtree)/tools
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
|
||||
|
||||
tools/%: FORCE
|
||||
$(Q)mkdir -p $(objtree)/tools
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
|
||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
|
||||
|
||||
# Single targets
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -143,7 +143,8 @@ struct pci_iommu_arena
|
|||
};
|
||||
|
||||
#if defined(CONFIG_ALPHA_SRM) && \
|
||||
(defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA))
|
||||
(defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA) || \
|
||||
defined(CONFIG_ALPHA_AVANTI))
|
||||
# define NEED_SRM_SAVE_RESTORE
|
||||
#else
|
||||
# undef NEED_SRM_SAVE_RESTORE
|
||||
|
|
|
|||
|
|
@ -273,12 +273,13 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
|
|||
application calling fork. */
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
childti->pcb.unique = regs->r20;
|
||||
else
|
||||
regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */
|
||||
childti->pcb.usp = usp ?: rdusp();
|
||||
*childregs = *regs;
|
||||
childregs->r0 = 0;
|
||||
childregs->r19 = 0;
|
||||
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
|
||||
regs->r20 = 0;
|
||||
stack = ((struct switch_stack *) regs) - 1;
|
||||
*childstack = *stack;
|
||||
childstack->r26 = (unsigned long) ret_from_fork;
|
||||
|
|
|
|||
|
|
@ -807,7 +807,8 @@ mcasp0: mcasp@48038000 {
|
|||
reg = <0x48038000 0x2000>,
|
||||
<0x46000000 0x400000>;
|
||||
reg-names = "mpu", "dat";
|
||||
interrupts = <80>, <81>;
|
||||
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "tx", "rx";
|
||||
status = "disabled";
|
||||
dmas = <&edma 8>,
|
||||
|
|
@ -821,7 +822,8 @@ mcasp1: mcasp@4803C000 {
|
|||
reg = <0x4803C000 0x2000>,
|
||||
<0x46400000 0x400000>;
|
||||
reg-names = "mpu", "dat";
|
||||
interrupts = <82>, <83>;
|
||||
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "tx", "rx";
|
||||
status = "disabled";
|
||||
dmas = <&edma 10>,
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ codec: sgtl5000@2a {
|
|||
reg = <0x2a>;
|
||||
VDDA-supply = <®_3p3v>;
|
||||
VDDIO-supply = <®_3p3v>;
|
||||
clocks = <&sys_mclk 1>;
|
||||
clocks = <&sys_mclk>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ codec: sgtl5000@a {
|
|||
reg = <0x0a>;
|
||||
VDDA-supply = <®_3p3v>;
|
||||
VDDIO-supply = <®_3p3v>;
|
||||
clocks = <&sys_mclk 1>;
|
||||
clocks = <&sys_mclk>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -844,14 +844,12 @@ usbhshost: usbhshost@4a064000 {
|
|||
usbhsohci: ohci@4a064800 {
|
||||
compatible = "ti,ohci-omap3";
|
||||
reg = <0x4a064800 0x400>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
usbhsehci: ehci@4a064c00 {
|
||||
compatible = "ti,ehci-omap";
|
||||
reg = <0x4a064c00 0x400>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -461,6 +461,7 @@ ohci: ohci@ec300000 {
|
|||
compatible = "samsung,exynos4210-ohci";
|
||||
reg = <0xec300000 0x100>;
|
||||
interrupts = <23>;
|
||||
interrupt-parent = <&vic1>;
|
||||
clocks = <&clocks CLK_USB_HOST>;
|
||||
clock-names = "usbhost";
|
||||
#address-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ serial@e0000000 {
|
|||
spi0: spi@e0100000 {
|
||||
status = "okay";
|
||||
num-cs = <3>;
|
||||
cs-gpios = <&gpio1 7 0>, <&spics 0>, <&spics 1>;
|
||||
cs-gpios = <&gpio1 7 0>, <&spics 0 0>, <&spics 1 0>;
|
||||
|
||||
stmpe610@0 {
|
||||
compatible = "st,stmpe610";
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ serial@b4100000 {
|
|||
reg = <0xb4100000 0x1000>;
|
||||
interrupts = <0 105 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dwdma0 0x600 0 0 1>, /* 0xC << 11 */
|
||||
<&dwdma0 0x680 0 1 0>; /* 0xD << 7 */
|
||||
dmas = <&dwdma0 12 0 1>,
|
||||
<&dwdma0 13 1 0>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ cf@b2800000 {
|
|||
reg = <0xb2800000 0x1000>;
|
||||
interrupts = <0 29 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dwdma0 0 0 0 0>;
|
||||
dmas = <&dwdma0 0 0 0>;
|
||||
dma-names = "data";
|
||||
};
|
||||
|
||||
|
|
@ -288,8 +288,8 @@ spi0: spi@e0100000 {
|
|||
#size-cells = <0>;
|
||||
interrupts = <0 31 0x4>;
|
||||
status = "disabled";
|
||||
dmas = <&dwdma0 0x2000 0 0 0>, /* 0x4 << 11 */
|
||||
<&dwdma0 0x0280 0 0 0>; /* 0x5 << 7 */
|
||||
dmas = <&dwdma0 4 0 0>,
|
||||
<&dwdma0 5 0 0>;
|
||||
dma-names = "tx", "rx";
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ i2c@d0200000 {
|
|||
rtc@fc900000 {
|
||||
compatible = "st,spear600-rtc";
|
||||
reg = <0xfc900000 0x1000>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <10>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
#include "stih407-clock.dtsi"
|
||||
#include "stih407-family.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
/ {
|
||||
soc {
|
||||
sti-display-subsystem {
|
||||
|
|
@ -112,7 +113,7 @@ sti-hdmi@8d04000 {
|
|||
<&clk_s_d2_quadfs 0>,
|
||||
<&clk_s_d2_quadfs 1>;
|
||||
|
||||
hdmi,hpd-gpio = <&pio5 3>;
|
||||
hdmi,hpd-gpio = <&pio5 3 GPIO_ACTIVE_LOW>;
|
||||
reset-names = "hdmi";
|
||||
resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
|
||||
ddc = <&hdmiddc>;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "stih410-clock.dtsi"
|
||||
#include "stih407-family.dtsi"
|
||||
#include "stih410-pinctrl.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
/ {
|
||||
aliases {
|
||||
bdisp0 = &bdisp0;
|
||||
|
|
@ -203,7 +204,7 @@ sti-hdmi@8d04000 {
|
|||
<&clk_s_d2_quadfs 0>,
|
||||
<&clk_s_d2_quadfs 1>;
|
||||
|
||||
hdmi,hpd-gpio = <&pio5 3>;
|
||||
hdmi,hpd-gpio = <&pio5 3 GPIO_ACTIVE_LOW>;
|
||||
reset-names = "hdmi";
|
||||
resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
|
||||
ddc = <&hdmiddc>;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
|||
|
||||
ret = kvm_psci_call(vcpu);
|
||||
if (ret < 0) {
|
||||
kvm_inject_undefined(vcpu);
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +54,16 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
|||
|
||||
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
{
|
||||
kvm_inject_undefined(vcpu);
|
||||
/*
|
||||
* "If an SMC instruction executed at Non-secure EL1 is
|
||||
* trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
|
||||
* Trap exception, not a Secure Monitor Call exception [...]"
|
||||
*
|
||||
* We need to advance the PC after the trap, as it would
|
||||
* otherwise return to the same address...
|
||||
*/
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,11 @@
|
|||
.pushsection .text.fixup,"ax"
|
||||
.align 4
|
||||
9001: mov r4, #-EFAULT
|
||||
#ifdef CONFIG_CPU_SW_DOMAIN_PAN
|
||||
ldr r5, [sp, #9*4] @ *err_ptr
|
||||
#else
|
||||
ldr r5, [sp, #8*4] @ *err_ptr
|
||||
#endif
|
||||
str r4, [r5]
|
||||
ldmia sp, {r1, r2} @ retrieve dst, len
|
||||
add r2, r2, r1
|
||||
|
|
|
|||
|
|
@ -73,6 +73,25 @@ phys_addr_t omap_secure_ram_mempool_base(void)
|
|||
return omap_secure_memblock_base;
|
||||
}
|
||||
|
||||
u32 omap3_save_secure_ram(void __iomem *addr, int size)
|
||||
{
|
||||
u32 ret;
|
||||
u32 param[5];
|
||||
|
||||
if (size != OMAP3_SAVE_SECURE_RAM_SZ)
|
||||
return OMAP3_SAVE_SECURE_RAM_SZ;
|
||||
|
||||
param[0] = 4; /* Number of arguments */
|
||||
param[1] = __pa(addr); /* Physical address for saving */
|
||||
param[2] = 0;
|
||||
param[3] = 1;
|
||||
param[4] = 1;
|
||||
|
||||
ret = save_secure_ram_context(__pa(param));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* rx51_secure_dispatcher: Routine to dispatch secure PPA API calls
|
||||
* @idx: The PPA API index
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
/* Maximum Secure memory storage size */
|
||||
#define OMAP_SECURE_RAM_STORAGE (88 * SZ_1K)
|
||||
|
||||
#define OMAP3_SAVE_SECURE_RAM_SZ 0x803F
|
||||
|
||||
/* Secure low power HAL API index */
|
||||
#define OMAP4_HAL_SAVESECURERAM_INDEX 0x1a
|
||||
#define OMAP4_HAL_SAVEHW_INDEX 0x1b
|
||||
|
|
@ -64,6 +66,8 @@ extern u32 omap_smc2(u32 id, u32 falg, u32 pargs);
|
|||
extern u32 omap_smc3(u32 id, u32 process, u32 flag, u32 pargs);
|
||||
extern phys_addr_t omap_secure_ram_mempool_base(void);
|
||||
extern int omap_secure_ram_reserve_memblock(void);
|
||||
extern u32 save_secure_ram_context(u32 args_pa);
|
||||
extern u32 omap3_save_secure_ram(void __iomem *save_regs, int size);
|
||||
|
||||
extern u32 rx51_secure_dispatcher(u32 idx, u32 process, u32 flag, u32 nargs,
|
||||
u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
|
|
|
|||
|
|
@ -81,10 +81,6 @@ extern unsigned int omap3_do_wfi_sz;
|
|||
/* ... and its pointer from SRAM after copy */
|
||||
extern void (*omap3_do_wfi_sram)(void);
|
||||
|
||||
/* save_secure_ram_context function pointer and size, for copy to SRAM */
|
||||
extern int save_secure_ram_context(u32 *addr);
|
||||
extern unsigned int save_secure_ram_context_sz;
|
||||
|
||||
extern void omap3_save_scratchpad_contents(void);
|
||||
|
||||
#define PM_RTA_ERRATUM_i608 (1 << 0)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "prm3xxx.h"
|
||||
#include "pm.h"
|
||||
#include "sdrc.h"
|
||||
#include "omap-secure.h"
|
||||
#include "sram.h"
|
||||
#include "control.h"
|
||||
#include "vc.h"
|
||||
|
|
@ -66,7 +67,6 @@ struct power_state {
|
|||
|
||||
static LIST_HEAD(pwrst_list);
|
||||
|
||||
static int (*_omap_save_secure_sram)(u32 *addr);
|
||||
void (*omap3_do_wfi_sram)(void);
|
||||
|
||||
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
|
||||
|
|
@ -121,8 +121,8 @@ static void omap3_save_secure_ram_context(void)
|
|||
* will hang the system.
|
||||
*/
|
||||
pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
|
||||
ret = _omap_save_secure_sram((u32 *)(unsigned long)
|
||||
__pa(omap3_secure_ram_storage));
|
||||
ret = omap3_save_secure_ram(omap3_secure_ram_storage,
|
||||
OMAP3_SAVE_SECURE_RAM_SZ);
|
||||
pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
|
||||
/* Following is for error tracking, it should not happen */
|
||||
if (ret) {
|
||||
|
|
@ -431,15 +431,10 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
|
|||
*
|
||||
* The minimum set of functions is pushed to SRAM for execution:
|
||||
* - omap3_do_wfi for erratum i581 WA,
|
||||
* - save_secure_ram_context for security extensions.
|
||||
*/
|
||||
void omap_push_sram_idle(void)
|
||||
{
|
||||
omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
|
||||
|
||||
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
|
||||
_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
|
||||
save_secure_ram_context_sz);
|
||||
}
|
||||
|
||||
static void __init pm_errata_configure(void)
|
||||
|
|
@ -551,7 +546,7 @@ int __init omap3_pm_init(void)
|
|||
clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
|
||||
if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
|
||||
omap3_secure_ram_storage =
|
||||
kmalloc(0x803F, GFP_KERNEL);
|
||||
kmalloc(OMAP3_SAVE_SECURE_RAM_SZ, GFP_KERNEL);
|
||||
if (!omap3_secure_ram_storage)
|
||||
pr_err("Memory allocation failed when allocating for secure sram context\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -176,17 +176,6 @@ static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
|||
return v;
|
||||
}
|
||||
|
||||
static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
||||
v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
|
||||
v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
|
||||
{
|
||||
am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
|
||||
|
|
@ -357,7 +346,6 @@ struct pwrdm_ops am33xx_pwrdm_operations = {
|
|||
.pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
|
||||
.pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
|
||||
.pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
|
||||
.pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
|
||||
.pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
|
||||
.pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
|
||||
.pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
|
||||
|
|
|
|||
|
|
@ -93,20 +93,13 @@ ENTRY(enable_omap3630_toggle_l2_on_restore)
|
|||
ENDPROC(enable_omap3630_toggle_l2_on_restore)
|
||||
|
||||
/*
|
||||
* Function to call rom code to save secure ram context. This gets
|
||||
* relocated to SRAM, so it can be all in .data section. Otherwise
|
||||
* we need to initialize api_params separately.
|
||||
* Function to call rom code to save secure ram context.
|
||||
*
|
||||
* r0 = physical address of the parameters
|
||||
*/
|
||||
.data
|
||||
.align 3
|
||||
ENTRY(save_secure_ram_context)
|
||||
stmfd sp!, {r4 - r11, lr} @ save registers on stack
|
||||
adr r3, api_params @ r3 points to parameters
|
||||
str r0, [r3,#0x4] @ r0 has sdram address
|
||||
ldr r12, high_mask
|
||||
and r3, r3, r12
|
||||
ldr r12, sram_phy_addr_mask
|
||||
orr r3, r3, r12
|
||||
mov r3, r0 @ physical address of parameters
|
||||
mov r0, #25 @ set service ID for PPA
|
||||
mov r12, r0 @ copy secure service ID in r12
|
||||
mov r1, #0 @ set task id for ROM code in r1
|
||||
|
|
@ -120,18 +113,7 @@ ENTRY(save_secure_ram_context)
|
|||
nop
|
||||
nop
|
||||
ldmfd sp!, {r4 - r11, pc}
|
||||
.align
|
||||
sram_phy_addr_mask:
|
||||
.word SRAM_BASE_P
|
||||
high_mask:
|
||||
.word 0xffff
|
||||
api_params:
|
||||
.word 0x4, 0x0, 0x0, 0x1, 0x1
|
||||
ENDPROC(save_secure_ram_context)
|
||||
ENTRY(save_secure_ram_context_sz)
|
||||
.word . - save_secure_ram_context
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* ======================
|
||||
|
|
|
|||
|
|
@ -132,3 +132,7 @@ static struct platform_driver tosa_bt_driver = {
|
|||
},
|
||||
};
|
||||
module_platform_driver(tosa_bt_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Dmitry Baryshkov");
|
||||
MODULE_DESCRIPTION("Bluetooth built-in chip control");
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ menuconfig ARCH_TEGRA
|
|||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select RESET_CONTROLLER
|
||||
select SOC_BUS
|
||||
select USB_ULPI if USB_PHY
|
||||
select USB_ULPI_VIEWPORT if USB_PHY
|
||||
help
|
||||
This enables support for NVIDIA Tegra based systems.
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ config ARM64
|
|||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_BPF_JIT
|
||||
select HAVE_EBPF_JIT
|
||||
select HAVE_C_RECORDMCOUNT
|
||||
select HAVE_CC_STACKPROTECTOR
|
||||
select HAVE_CMPXCHG_DOUBLE
|
||||
|
|
@ -1017,7 +1018,7 @@ source "fs/Kconfig.binfmt"
|
|||
config COMPAT
|
||||
bool "Kernel support for 32-bit EL0"
|
||||
depends on ARM64_4K_PAGES || EXPERT
|
||||
select COMPAT_BINFMT_ELF
|
||||
select COMPAT_BINFMT_ELF if BINFMT_ELF
|
||||
select HAVE_UID16
|
||||
select OLD_SIGSUSPEND3
|
||||
select COMPAT_OLD_SIGACTION
|
||||
|
|
|
|||
|
|
@ -90,8 +90,6 @@ config ARCH_TEGRA_132_SOC
|
|||
bool "NVIDIA Tegra132 SoC"
|
||||
depends on ARCH_TEGRA
|
||||
select PINCTRL_TEGRA124
|
||||
select USB_ULPI if USB_PHY
|
||||
select USB_ULPI_VIEWPORT if USB_PHY
|
||||
help
|
||||
Enable support for NVIDIA Tegra132 SoC, based on the Denver
|
||||
ARMv8 CPU. The Tegra132 SoC is similar to the Tegra124 SoC,
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ cpu0: cpu@0 {
|
|||
reg = <0x000>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
|
|
@ -70,6 +71,7 @@ cpu2: cpu@100 {
|
|||
reg = <0x100>;
|
||||
enable-method = "psci";
|
||||
cpu-idle-states = <&CPU_SLEEP_0>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
cpu3: cpu@101 {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@
|
|||
|
||||
#include <asm/brk-imm.h>
|
||||
|
||||
#ifdef CONFIG_GENERIC_BUG
|
||||
#define HAVE_ARCH_BUG
|
||||
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
#define _BUGVERBOSE_LOCATION(file, line) __BUGVERBOSE_LOCATION(file, line)
|
||||
#define __BUGVERBOSE_LOCATION(file, line) \
|
||||
|
|
@ -36,28 +33,36 @@
|
|||
#define _BUGVERBOSE_LOCATION(file, line)
|
||||
#endif
|
||||
|
||||
#define _BUG_FLAGS(flags) __BUG_FLAGS(flags)
|
||||
#ifdef CONFIG_GENERIC_BUG
|
||||
|
||||
#define __BUG_FLAGS(flags) asm volatile ( \
|
||||
#define __BUG_ENTRY(flags) \
|
||||
".pushsection __bug_table,\"a\"\n\t" \
|
||||
".align 2\n\t" \
|
||||
"0: .long 1f - 0b\n\t" \
|
||||
_BUGVERBOSE_LOCATION(__FILE__, __LINE__) \
|
||||
".short " #flags "\n\t" \
|
||||
".popsection\n" \
|
||||
\
|
||||
"1: brk %[imm]" \
|
||||
:: [imm] "i" (BUG_BRK_IMM) \
|
||||
)
|
||||
"1: "
|
||||
#else
|
||||
#define __BUG_ENTRY(flags) ""
|
||||
#endif
|
||||
|
||||
#define BUG() do { \
|
||||
_BUG_FLAGS(0); \
|
||||
unreachable(); \
|
||||
#define __BUG_FLAGS(flags) \
|
||||
asm volatile ( \
|
||||
__BUG_ENTRY(flags) \
|
||||
"brk %[imm]" :: [imm] "i" (BUG_BRK_IMM) \
|
||||
);
|
||||
|
||||
|
||||
#define BUG() do { \
|
||||
__BUG_FLAGS(0); \
|
||||
unreachable(); \
|
||||
} while (0)
|
||||
|
||||
#define __WARN_TAINT(taint) _BUG_FLAGS(BUGFLAG_TAINT(taint))
|
||||
#define __WARN_TAINT(taint) \
|
||||
__BUG_FLAGS(BUGFLAG_TAINT(taint))
|
||||
|
||||
#endif /* ! CONFIG_GENERIC_BUG */
|
||||
#define HAVE_ARCH_BUG
|
||||
|
||||
#include <asm-generic/bug.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ static const char *handler[]= {
|
|||
"Error"
|
||||
};
|
||||
|
||||
int show_unhandled_signals = 1;
|
||||
int show_unhandled_signals = 0;
|
||||
|
||||
/*
|
||||
* Dump out the contents of some memory nicely...
|
||||
|
|
|
|||
|
|
@ -15,4 +15,5 @@ obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
|
|||
obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
|
||||
|
||||
# libgcc-style stuff needed in the kernel
|
||||
obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
|
||||
obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o multi3.o \
|
||||
ucmpdi2.o
|
||||
|
|
|
|||
|
|
@ -9,10 +9,18 @@ typedef int word_type __attribute__ ((mode (__word__)));
|
|||
struct DWstruct {
|
||||
int high, low;
|
||||
};
|
||||
|
||||
struct TWstruct {
|
||||
long long high, low;
|
||||
};
|
||||
#elif defined(__LITTLE_ENDIAN)
|
||||
struct DWstruct {
|
||||
int low, high;
|
||||
};
|
||||
|
||||
struct TWstruct {
|
||||
long long low, high;
|
||||
};
|
||||
#else
|
||||
#error I feel sick.
|
||||
#endif
|
||||
|
|
@ -22,4 +30,13 @@ typedef union {
|
|||
long long ll;
|
||||
} DWunion;
|
||||
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6)
|
||||
typedef int ti_type __attribute__((mode(TI)));
|
||||
|
||||
typedef union {
|
||||
struct TWstruct s;
|
||||
ti_type ti;
|
||||
} TWunion;
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_LIBGCC_H */
|
||||
|
|
|
|||
54
arch/mips/lib/multi3.c
Normal file
54
arch/mips/lib/multi3.c
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "libgcc.h"
|
||||
|
||||
/*
|
||||
* GCC 7 suboptimally generates __multi3 calls for mips64r6, so for that
|
||||
* specific case only we'll implement it here.
|
||||
*
|
||||
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
|
||||
*/
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ == 7)
|
||||
|
||||
/* multiply 64-bit values, low 64-bits returned */
|
||||
static inline long long notrace dmulu(long long a, long long b)
|
||||
{
|
||||
long long res;
|
||||
|
||||
asm ("dmulu %0,%1,%2" : "=r" (res) : "r" (a), "r" (b));
|
||||
return res;
|
||||
}
|
||||
|
||||
/* multiply 64-bit unsigned values, high 64-bits of 128-bit result returned */
|
||||
static inline long long notrace dmuhu(long long a, long long b)
|
||||
{
|
||||
long long res;
|
||||
|
||||
asm ("dmuhu %0,%1,%2" : "=r" (res) : "r" (a), "r" (b));
|
||||
return res;
|
||||
}
|
||||
|
||||
/* multiply 128-bit values, low 128-bits returned */
|
||||
ti_type notrace __multi3(ti_type a, ti_type b)
|
||||
{
|
||||
TWunion res, aa, bb;
|
||||
|
||||
aa.ti = a;
|
||||
bb.ti = b;
|
||||
|
||||
/*
|
||||
* a * b = (a.lo * b.lo)
|
||||
* + 2^64 * (a.hi * b.lo + a.lo * b.hi)
|
||||
* [+ 2^128 * (a.hi * b.hi)]
|
||||
*/
|
||||
res.s.low = dmulu(aa.s.low, bb.s.low);
|
||||
res.s.high = dmuhu(aa.s.low, bb.s.low);
|
||||
res.s.high += dmulu(aa.s.high, bb.s.low);
|
||||
res.s.high += dmulu(aa.s.low, bb.s.high);
|
||||
|
||||
return res.ti;
|
||||
}
|
||||
EXPORT_SYMBOL(__multi3);
|
||||
|
||||
#endif /* 64BIT && CPU_MIPSR6 && GCC7 */
|
||||
|
|
@ -437,7 +437,7 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
|
|||
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = 0;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
info.si_addr = (void *) regs->pc;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -302,12 +302,12 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
|
|||
siginfo_t info;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
/* Send a SIGSEGV */
|
||||
info.si_signo = SIGSEGV;
|
||||
/* Send a SIGBUS */
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
/* info.si_code has been set above */
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void __user *)address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
} else {
|
||||
printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
|
||||
show_registers(regs);
|
||||
|
|
|
|||
|
|
@ -129,13 +129,14 @@ config PPC
|
|||
select IRQ_FORCED_THREADING
|
||||
select HAVE_RCU_TABLE_FREE if SMP
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select HAVE_BPF_JIT
|
||||
select HAVE_BPF_JIT if CPU_BIG_ENDIAN
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_CMOS_UPDATE
|
||||
select GENERIC_TIME_VSYSCALL_OLD
|
||||
select GENERIC_CPU_VULNERABILITIES if PPC_BOOK3S_64
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
|
|
|
|||
|
|
@ -209,5 +209,11 @@ exc_##label##_book3e:
|
|||
ori r3,r3,vector_offset@l; \
|
||||
mtspr SPRN_IVOR##vector_number,r3;
|
||||
|
||||
#define RFI_TO_KERNEL \
|
||||
rfi
|
||||
|
||||
#define RFI_TO_USER \
|
||||
rfi
|
||||
|
||||
#endif /* _ASM_POWERPC_EXCEPTION_64E_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,59 @@
|
|||
#define EX_PPR 88 /* SMT thread status register (priority) */
|
||||
#define EX_CTR 96
|
||||
|
||||
/*
|
||||
* Macros for annotating the expected destination of (h)rfid
|
||||
*
|
||||
* The nop instructions allow us to insert one or more instructions to flush the
|
||||
* L1-D cache when returning to userspace or a guest.
|
||||
*/
|
||||
#define RFI_FLUSH_SLOT \
|
||||
RFI_FLUSH_FIXUP_SECTION; \
|
||||
nop; \
|
||||
nop; \
|
||||
nop
|
||||
|
||||
#define RFI_TO_KERNEL \
|
||||
rfid
|
||||
|
||||
#define RFI_TO_USER \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_USER_OR_KERNEL \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define RFI_TO_GUEST \
|
||||
RFI_FLUSH_SLOT; \
|
||||
rfid; \
|
||||
b rfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_KERNEL \
|
||||
hrfid
|
||||
|
||||
#define HRFI_TO_USER \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_USER_OR_KERNEL \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_GUEST \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#define HRFI_TO_UNKNOWN \
|
||||
RFI_FLUSH_SLOT; \
|
||||
hrfid; \
|
||||
b hrfi_flush_fallback
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
#define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \
|
||||
ld r12,PACAKBASE(r13); /* get high part of &label */ \
|
||||
|
|
@ -191,7 +244,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
|
|||
mtspr SPRN_##h##SRR0,r12; \
|
||||
mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \
|
||||
mtspr SPRN_##h##SRR1,r10; \
|
||||
h##rfid; \
|
||||
h##RFI_TO_KERNEL; \
|
||||
b . /* prevent speculative execution */
|
||||
#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
|
||||
__EXCEPTION_PROLOG_PSERIES_1(label, h)
|
||||
|
|
|
|||
|
|
@ -184,4 +184,19 @@ label##3: \
|
|||
FTR_ENTRY_OFFSET label##1b-label##3b; \
|
||||
.popsection;
|
||||
|
||||
#define RFI_FLUSH_FIXUP_SECTION \
|
||||
951: \
|
||||
.pushsection __rfi_flush_fixup,"a"; \
|
||||
.align 2; \
|
||||
952: \
|
||||
FTR_ENTRY_OFFSET 951b-952b; \
|
||||
.popsection;
|
||||
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_POWERPC_FEATURE_FIXUPS_H */
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@
|
|||
#define H_GET_HCA_INFO 0x1B8
|
||||
#define H_GET_PERF_COUNT 0x1BC
|
||||
#define H_MANAGE_TRACE 0x1C0
|
||||
#define H_GET_CPU_CHARACTERISTICS 0x1C8
|
||||
#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
|
||||
#define H_QUERY_INT_STATE 0x1E4
|
||||
#define H_POLL_PENDING 0x1D8
|
||||
|
|
@ -285,7 +286,19 @@
|
|||
#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3
|
||||
#define H_SET_MODE_RESOURCE_LE 4
|
||||
|
||||
/* H_GET_CPU_CHARACTERISTICS return values */
|
||||
#define H_CPU_CHAR_SPEC_BAR_ORI31 (1ull << 63) // IBM bit 0
|
||||
#define H_CPU_CHAR_BCCTRL_SERIALISED (1ull << 62) // IBM bit 1
|
||||
#define H_CPU_CHAR_L1D_FLUSH_ORI30 (1ull << 61) // IBM bit 2
|
||||
#define H_CPU_CHAR_L1D_FLUSH_TRIG2 (1ull << 60) // IBM bit 3
|
||||
#define H_CPU_CHAR_L1D_THREAD_PRIV (1ull << 59) // IBM bit 4
|
||||
|
||||
#define H_CPU_BEHAV_FAVOUR_SECURITY (1ull << 63) // IBM bit 0
|
||||
#define H_CPU_BEHAV_L1D_FLUSH_PR (1ull << 62) // IBM bit 1
|
||||
#define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR (1ull << 61) // IBM bit 2
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments
|
||||
|
|
@ -423,6 +436,11 @@ extern long pseries_big_endian_exceptions(void);
|
|||
|
||||
#endif /* CONFIG_PPC_PSERIES */
|
||||
|
||||
struct h_cpu_char_result {
|
||||
u64 character;
|
||||
u64 behaviour;
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_HVCALL_H */
|
||||
|
|
|
|||
|
|
@ -192,6 +192,16 @@ struct paca_struct {
|
|||
#endif
|
||||
struct kvmppc_host_state kvm_hstate;
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
/*
|
||||
* rfi fallback flush must be in its own cacheline to prevent
|
||||
* other paca data leaking into the L1d
|
||||
*/
|
||||
u64 exrfi[13] __aligned(0x80);
|
||||
void *rfi_flush_fallback_area;
|
||||
u64 l1d_flush_congruence;
|
||||
u64 l1d_flush_sets;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct paca_struct *paca;
|
||||
|
|
|
|||
|
|
@ -323,4 +323,18 @@ static inline long plapr_set_watchpoint0(unsigned long dawr0, unsigned long dawr
|
|||
return plpar_set_mode(0, H_SET_MODE_RESOURCE_SET_DAWR, dawr0, dawrx0);
|
||||
}
|
||||
|
||||
static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p)
|
||||
{
|
||||
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
||||
long rc;
|
||||
|
||||
rc = plpar_hcall(H_GET_CPU_CHARACTERISTICS, retbuf);
|
||||
if (rc == H_SUCCESS) {
|
||||
p->character = retbuf[0];
|
||||
p->behaviour = retbuf[1];
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */
|
||||
|
|
|
|||
|
|
@ -224,6 +224,16 @@ name: \
|
|||
.globl name; \
|
||||
name:
|
||||
|
||||
#define _KPROBE_TOC(name) \
|
||||
.section ".kprobes.text","a"; \
|
||||
.align 2 ; \
|
||||
.type name,@function; \
|
||||
.globl name; \
|
||||
name: \
|
||||
0: addis r2,r12,(.TOC.-0b)@ha; \
|
||||
addi r2,r2,(.TOC.-0b)@l; \
|
||||
.localentry name,.-name
|
||||
|
||||
#define DOTSYM(a) a
|
||||
|
||||
#else
|
||||
|
|
@ -261,6 +271,8 @@ name: \
|
|||
.type GLUE(.,name),@function; \
|
||||
GLUE(.,name):
|
||||
|
||||
#define _KPROBE_TOC(n) _KPROBE(n)
|
||||
|
||||
#define DOTSYM(a) GLUE(.,a)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,6 +26,19 @@ void initmem_init(void);
|
|||
void setup_panic(void);
|
||||
#define ARCH_PANIC_TIMEOUT 180
|
||||
|
||||
void rfi_flush_enable(bool enable);
|
||||
|
||||
/* These are bit flags */
|
||||
enum l1d_flush_type {
|
||||
L1D_FLUSH_NONE = 0x1,
|
||||
L1D_FLUSH_FALLBACK = 0x2,
|
||||
L1D_FLUSH_ORI = 0x4,
|
||||
L1D_FLUSH_MTTRIG = 0x8,
|
||||
};
|
||||
|
||||
void __init setup_rfi_flush(enum l1d_flush_type, bool enable);
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_SETUP_H */
|
||||
|
|
|
|||
|
|
@ -243,6 +243,10 @@ int main(void)
|
|||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp));
|
||||
DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce));
|
||||
DEFINE(PACA_RFI_FLUSH_FALLBACK_AREA, offsetof(struct paca_struct, rfi_flush_fallback_area));
|
||||
DEFINE(PACA_EXRFI, offsetof(struct paca_struct, exrfi));
|
||||
DEFINE(PACA_L1D_FLUSH_CONGRUENCE, offsetof(struct paca_struct, l1d_flush_congruence));
|
||||
DEFINE(PACA_L1D_FLUSH_SETS, offsetof(struct paca_struct, l1d_flush_sets));
|
||||
#endif
|
||||
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
|
||||
DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
|
||||
|
|
|
|||
|
|
@ -36,6 +36,11 @@
|
|||
#include <asm/hw_irq.h>
|
||||
#include <asm/context_tracking.h>
|
||||
#include <asm/tm.h>
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
#include <asm/exception-64s.h>
|
||||
#else
|
||||
#include <asm/exception-64e.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* System calls.
|
||||
|
|
@ -225,13 +230,23 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
|
|||
ACCOUNT_CPU_USER_EXIT(r11, r12)
|
||||
HMT_MEDIUM_LOW_HAS_PPR
|
||||
ld r13,GPR13(r1) /* only restore r13 if returning to usermode */
|
||||
ld r2,GPR2(r1)
|
||||
ld r1,GPR1(r1)
|
||||
mtlr r4
|
||||
mtcr r5
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
/* exit to kernel */
|
||||
1: ld r2,GPR2(r1)
|
||||
ld r1,GPR1(r1)
|
||||
mtlr r4
|
||||
mtcr r5
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
syscall_error:
|
||||
|
|
@ -353,8 +368,7 @@ tabort_syscall:
|
|||
mtmsrd r10, 1
|
||||
mtspr SPRN_SRR0, r11
|
||||
mtspr SPRN_SRR1, r12
|
||||
|
||||
rfid
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
#endif
|
||||
|
||||
|
|
@ -887,7 +901,7 @@ BEGIN_FTR_SECTION
|
|||
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
ACCOUNT_CPU_USER_EXIT(r2, r4)
|
||||
REST_GPR(13, r1)
|
||||
1:
|
||||
|
||||
mtspr SPRN_SRR1,r3
|
||||
|
||||
ld r2,_CCR(r1)
|
||||
|
|
@ -900,8 +914,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
|||
ld r3,GPR3(r1)
|
||||
ld r4,GPR4(r1)
|
||||
ld r1,GPR1(r1)
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
rfid
|
||||
1: mtspr SPRN_SRR1,r3
|
||||
|
||||
ld r2,_CCR(r1)
|
||||
mtcrf 0xFF,r2
|
||||
ld r2,_NIP(r1)
|
||||
mtspr SPRN_SRR0,r2
|
||||
|
||||
ld r0,GPR0(r1)
|
||||
ld r2,GPR2(r1)
|
||||
ld r3,GPR3(r1)
|
||||
ld r4,GPR4(r1)
|
||||
ld r1,GPR1(r1)
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
|
@ -1077,7 +1105,7 @@ _GLOBAL(enter_rtas)
|
|||
|
||||
mtspr SPRN_SRR0,r5
|
||||
mtspr SPRN_SRR1,r6
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
rtas_return_loc:
|
||||
|
|
@ -1102,7 +1130,7 @@ rtas_return_loc:
|
|||
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
.align 3
|
||||
|
|
@ -1173,7 +1201,7 @@ _GLOBAL(enter_prom)
|
|||
LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE)
|
||||
andc r11,r11,r12
|
||||
mtsrr1 r11
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
||||
1: /* Return from OF */
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
|
|||
mtspr SPRN_SRR0,r10 ; \
|
||||
ld r10,PACAKMSR(r13) ; \
|
||||
mtspr SPRN_SRR1,r10 ; \
|
||||
rfid ; \
|
||||
RFI_TO_KERNEL ; \
|
||||
b . ; /* prevent speculative execution */
|
||||
|
||||
#define SYSCALL_PSERIES_3 \
|
||||
|
|
@ -54,7 +54,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
|
|||
1: mfspr r12,SPRN_SRR1 ; \
|
||||
xori r12,r12,MSR_LE ; \
|
||||
mtspr SPRN_SRR1,r12 ; \
|
||||
rfid ; /* return to userspace */ \
|
||||
RFI_TO_USER ; /* return to userspace */ \
|
||||
b . ; /* prevent speculative execution */
|
||||
|
||||
#if defined(CONFIG_RELOCATABLE)
|
||||
|
|
@ -507,7 +507,7 @@ BEGIN_FTR_SECTION
|
|||
LOAD_HANDLER(r12, machine_check_handle_early)
|
||||
1: mtspr SPRN_SRR0,r12
|
||||
mtspr SPRN_SRR1,r11
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
2:
|
||||
/* Stack overflow. Stay on emergency stack and panic.
|
||||
|
|
@ -601,7 +601,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
|
|||
ld r11,PACA_EXGEN+EX_R11(r13)
|
||||
ld r12,PACA_EXGEN+EX_R12(r13)
|
||||
ld r13,PACA_EXGEN+EX_R13(r13)
|
||||
HRFID
|
||||
HRFI_TO_UNKNOWN
|
||||
b .
|
||||
#endif
|
||||
|
||||
|
|
@ -666,7 +666,7 @@ masked_##_H##interrupt: \
|
|||
ld r10,PACA_EXGEN+EX_R10(r13); \
|
||||
ld r11,PACA_EXGEN+EX_R11(r13); \
|
||||
GET_SCRATCH0(r13); \
|
||||
##_H##rfid; \
|
||||
##_H##RFI_TO_KERNEL; \
|
||||
b .
|
||||
|
||||
MASKED_INTERRUPT()
|
||||
|
|
@ -756,7 +756,7 @@ kvmppc_skip_interrupt:
|
|||
addi r13, r13, 4
|
||||
mtspr SPRN_SRR0, r13
|
||||
GET_SCRATCH0(r13)
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
kvmppc_skip_Hinterrupt:
|
||||
|
|
@ -768,7 +768,7 @@ kvmppc_skip_Hinterrupt:
|
|||
addi r13, r13, 4
|
||||
mtspr SPRN_HSRR0, r13
|
||||
GET_SCRATCH0(r13)
|
||||
hrfid
|
||||
HRFI_TO_KERNEL
|
||||
b .
|
||||
#endif
|
||||
|
||||
|
|
@ -1439,7 +1439,7 @@ machine_check_handle_early:
|
|||
li r3,MSR_ME
|
||||
andc r10,r10,r3 /* Turn off MSR_ME */
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
2:
|
||||
/*
|
||||
|
|
@ -1457,7 +1457,7 @@ machine_check_handle_early:
|
|||
*/
|
||||
bl machine_check_queue_event
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
rfid
|
||||
RFI_TO_USER_OR_KERNEL
|
||||
9:
|
||||
/* Deliver the machine check to host kernel in V mode. */
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
|
|
@ -1503,6 +1503,8 @@ slb_miss_realmode:
|
|||
|
||||
andi. r10,r12,MSR_RI /* check for unrecoverable exception */
|
||||
beq- 2f
|
||||
andi. r10,r12,MSR_PR /* check for user mode (PR != 0) */
|
||||
bne 1f
|
||||
|
||||
.machine push
|
||||
.machine "power4"
|
||||
|
|
@ -1516,7 +1518,23 @@ slb_miss_realmode:
|
|||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
1:
|
||||
.machine push
|
||||
.machine "power4"
|
||||
mtcrf 0x80,r9
|
||||
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
|
||||
.machine pop
|
||||
|
||||
RESTORE_PPR_PACA(PACA_EXSLB, r9)
|
||||
ld r9,PACA_EXSLB+EX_R9(r13)
|
||||
ld r10,PACA_EXSLB+EX_R10(r13)
|
||||
ld r11,PACA_EXSLB+EX_R11(r13)
|
||||
ld r12,PACA_EXSLB+EX_R12(r13)
|
||||
ld r13,PACA_EXSLB+EX_R13(r13)
|
||||
RFI_TO_USER
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
2: mfspr r11,SPRN_SRR0
|
||||
|
|
@ -1525,7 +1543,7 @@ slb_miss_realmode:
|
|||
mtspr SPRN_SRR0,r10
|
||||
ld r10,PACAKMSR(r13)
|
||||
mtspr SPRN_SRR1,r10
|
||||
rfid
|
||||
RFI_TO_KERNEL
|
||||
b .
|
||||
|
||||
unrecov_slb:
|
||||
|
|
@ -1546,6 +1564,92 @@ power4_fixup_nap:
|
|||
blr
|
||||
#endif
|
||||
|
||||
.globl rfi_flush_fallback
|
||||
rfi_flush_fallback:
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
std r12,PACA_EXRFI+EX_R12(r13)
|
||||
std r8,PACA_EXRFI+EX_R13(r13)
|
||||
mfctr r9
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SETS(r13)
|
||||
ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13)
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
addi r12,r12,8
|
||||
mtctr r11
|
||||
DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
|
||||
|
||||
/* order ld/st prior to dcbt stop all streams with flushing */
|
||||
sync
|
||||
1: li r8,0
|
||||
.rept 8 /* 8-way set associative */
|
||||
ldx r11,r10,r8
|
||||
add r8,r8,r12
|
||||
xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not
|
||||
add r8,r8,r11 // Add 0, this creates a dependency on the ldx
|
||||
.endr
|
||||
addi r10,r10,128 /* 128 byte cache line */
|
||||
bdnz 1b
|
||||
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
ld r12,PACA_EXRFI+EX_R12(r13)
|
||||
ld r8,PACA_EXRFI+EX_R13(r13)
|
||||
GET_SCRATCH0(r13);
|
||||
rfid
|
||||
|
||||
.globl hrfi_flush_fallback
|
||||
hrfi_flush_fallback:
|
||||
SET_SCRATCH0(r13);
|
||||
GET_PACA(r13);
|
||||
std r9,PACA_EXRFI+EX_R9(r13)
|
||||
std r10,PACA_EXRFI+EX_R10(r13)
|
||||
std r11,PACA_EXRFI+EX_R11(r13)
|
||||
std r12,PACA_EXRFI+EX_R12(r13)
|
||||
std r8,PACA_EXRFI+EX_R13(r13)
|
||||
mfctr r9
|
||||
ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
|
||||
ld r11,PACA_L1D_FLUSH_SETS(r13)
|
||||
ld r12,PACA_L1D_FLUSH_CONGRUENCE(r13)
|
||||
/*
|
||||
* The load adresses are at staggered offsets within cachelines,
|
||||
* which suits some pipelines better (on others it should not
|
||||
* hurt).
|
||||
*/
|
||||
addi r12,r12,8
|
||||
mtctr r11
|
||||
DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
|
||||
|
||||
/* order ld/st prior to dcbt stop all streams with flushing */
|
||||
sync
|
||||
1: li r8,0
|
||||
.rept 8 /* 8-way set associative */
|
||||
ldx r11,r10,r8
|
||||
add r8,r8,r12
|
||||
xor r11,r11,r11 // Ensure r11 is 0 even if fallback area is not
|
||||
add r8,r8,r11 // Add 0, this creates a dependency on the ldx
|
||||
.endr
|
||||
addi r10,r10,128 /* 128 byte cache line */
|
||||
bdnz 1b
|
||||
|
||||
mtctr r9
|
||||
ld r9,PACA_EXRFI+EX_R9(r13)
|
||||
ld r10,PACA_EXRFI+EX_R10(r13)
|
||||
ld r11,PACA_EXRFI+EX_R11(r13)
|
||||
ld r12,PACA_EXRFI+EX_R12(r13)
|
||||
ld r8,PACA_EXRFI+EX_R13(r13)
|
||||
GET_SCRATCH0(r13);
|
||||
hrfid
|
||||
|
||||
/*
|
||||
* Hash table stuff
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ PPC64_CACHES:
|
|||
* flush all bytes from start through stop-1 inclusive
|
||||
*/
|
||||
|
||||
_KPROBE(flush_icache_range)
|
||||
_KPROBE_TOC(flush_icache_range)
|
||||
BEGIN_FTR_SECTION
|
||||
PURGE_PREFETCHED_INS
|
||||
blr
|
||||
|
|
@ -117,7 +117,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
|
|||
*
|
||||
* flush all bytes from start to stop-1 inclusive
|
||||
*/
|
||||
_GLOBAL(flush_dcache_range)
|
||||
_GLOBAL_TOC(flush_dcache_range)
|
||||
|
||||
/*
|
||||
* Flush the data cache to memory
|
||||
|
|
@ -701,31 +701,3 @@ _GLOBAL(kexec_sequence)
|
|||
li r5,0
|
||||
blr /* image->start(physid, image->start, 0); */
|
||||
#endif /* CONFIG_KEXEC */
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
|
||||
#ifdef CONFIG_MODVERSIONS
|
||||
.weak __crc_TOC.
|
||||
.section "___kcrctab+TOC.","a"
|
||||
.globl __kcrctab_TOC.
|
||||
__kcrctab_TOC.:
|
||||
.llong __crc_TOC.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Export a fake .TOC. since both modpost and depmod will complain otherwise.
|
||||
* Both modpost and depmod strip the leading . so we do the same here.
|
||||
*/
|
||||
.section "__ksymtab_strings","a"
|
||||
__kstrtab_TOC.:
|
||||
.asciz "TOC."
|
||||
|
||||
.section "___ksymtab+TOC.","a"
|
||||
/* This symbol name is important: it's used by modpost to find exported syms */
|
||||
.globl __ksymtab_TOC.
|
||||
__ksymtab_TOC.:
|
||||
.llong 0 /* .value */
|
||||
.llong __kstrtab_TOC.
|
||||
#endif /* ELFv2 */
|
||||
#endif /* MODULES */
|
||||
|
|
|
|||
|
|
@ -326,7 +326,10 @@ static void dedotify_versions(struct modversion_info *vers,
|
|||
}
|
||||
}
|
||||
|
||||
/* Undefined symbols which refer to .funcname, hack to funcname (or .TOC.) */
|
||||
/*
|
||||
* Undefined symbols which refer to .funcname, hack to funcname. Make .TOC.
|
||||
* seem to be defined (value set later).
|
||||
*/
|
||||
static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
|
||||
{
|
||||
unsigned int i;
|
||||
|
|
@ -334,8 +337,11 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
|
|||
for (i = 1; i < numsyms; i++) {
|
||||
if (syms[i].st_shndx == SHN_UNDEF) {
|
||||
char *name = strtab + syms[i].st_name;
|
||||
if (name[0] == '.')
|
||||
if (name[0] == '.') {
|
||||
if (strcmp(name+1, "TOC.") == 0)
|
||||
syms[i].st_shndx = SHN_ABS;
|
||||
syms[i].st_name++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -351,7 +357,7 @@ static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs,
|
|||
numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym);
|
||||
|
||||
for (i = 1; i < numsyms; i++) {
|
||||
if (syms[i].st_shndx == SHN_UNDEF
|
||||
if (syms[i].st_shndx == SHN_ABS
|
||||
&& strcmp(strtab + syms[i].st_name, "TOC.") == 0)
|
||||
return &syms[i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,7 +209,8 @@ void enable_kernel_vsx(void)
|
|||
WARN_ON(preemptible());
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (current->thread.regs && (current->thread.regs->msr & MSR_VSX))
|
||||
if (current->thread.regs &&
|
||||
(current->thread.regs->msr & (MSR_VSX|MSR_VEC|MSR_FP)))
|
||||
giveup_vsx(current);
|
||||
else
|
||||
giveup_vsx(NULL); /* just enable vsx for kernel - force */
|
||||
|
|
@ -231,7 +232,7 @@ void flush_vsx_to_thread(struct task_struct *tsk)
|
|||
{
|
||||
if (tsk->thread.regs) {
|
||||
preempt_disable();
|
||||
if (tsk->thread.regs->msr & MSR_VSX) {
|
||||
if (tsk->thread.regs->msr & (MSR_VSX|MSR_VEC|MSR_FP)) {
|
||||
#ifdef CONFIG_SMP
|
||||
BUG_ON(tsk != current);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/hugetlb.h>
|
||||
#include <linux/memory.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/kdump.h>
|
||||
|
|
@ -835,3 +836,141 @@ static int __init disable_hardlockup_detector(void)
|
|||
}
|
||||
early_initcall(disable_hardlockup_detector);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
static enum l1d_flush_type enabled_flush_types;
|
||||
static void *l1d_flush_fallback_area;
|
||||
static bool no_rfi_flush;
|
||||
bool rfi_flush;
|
||||
|
||||
static int __init handle_no_rfi_flush(char *p)
|
||||
{
|
||||
pr_info("rfi-flush: disabled on command line.");
|
||||
no_rfi_flush = true;
|
||||
return 0;
|
||||
}
|
||||
early_param("no_rfi_flush", handle_no_rfi_flush);
|
||||
|
||||
/*
|
||||
* The RFI flush is not KPTI, but because users will see doco that says to use
|
||||
* nopti we hijack that option here to also disable the RFI flush.
|
||||
*/
|
||||
static int __init handle_no_pti(char *p)
|
||||
{
|
||||
pr_info("rfi-flush: disabling due to 'nopti' on command line.\n");
|
||||
handle_no_rfi_flush(NULL);
|
||||
return 0;
|
||||
}
|
||||
early_param("nopti", handle_no_pti);
|
||||
|
||||
static void do_nothing(void *unused)
|
||||
{
|
||||
/*
|
||||
* We don't need to do the flush explicitly, just enter+exit kernel is
|
||||
* sufficient, the RFI exit handlers will do the right thing.
|
||||
*/
|
||||
}
|
||||
|
||||
void rfi_flush_enable(bool enable)
|
||||
{
|
||||
if (rfi_flush == enable)
|
||||
return;
|
||||
|
||||
if (enable) {
|
||||
do_rfi_flush_fixups(enabled_flush_types);
|
||||
on_each_cpu(do_nothing, NULL, 1);
|
||||
} else
|
||||
do_rfi_flush_fixups(L1D_FLUSH_NONE);
|
||||
|
||||
rfi_flush = enable;
|
||||
}
|
||||
|
||||
static void init_fallback_flush(void)
|
||||
{
|
||||
u64 l1d_size, limit;
|
||||
int cpu;
|
||||
|
||||
l1d_size = ppc64_caches.dsize;
|
||||
limit = min(safe_stack_limit(), ppc64_rma_size);
|
||||
|
||||
/*
|
||||
* Align to L1d size, and size it at 2x L1d size, to catch possible
|
||||
* hardware prefetch runoff. We don't have a recipe for load patterns to
|
||||
* reliably avoid the prefetcher.
|
||||
*/
|
||||
l1d_flush_fallback_area = __va(memblock_alloc_base(l1d_size * 2, l1d_size, limit));
|
||||
memset(l1d_flush_fallback_area, 0, l1d_size * 2);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
/*
|
||||
* The fallback flush is currently coded for 8-way
|
||||
* associativity. Different associativity is possible, but it
|
||||
* will be treated as 8-way and may not evict the lines as
|
||||
* effectively.
|
||||
*
|
||||
* 128 byte lines are mandatory.
|
||||
*/
|
||||
u64 c = l1d_size / 8;
|
||||
|
||||
paca[cpu].rfi_flush_fallback_area = l1d_flush_fallback_area;
|
||||
paca[cpu].l1d_flush_congruence = c;
|
||||
paca[cpu].l1d_flush_sets = c / 128;
|
||||
}
|
||||
}
|
||||
|
||||
void __init setup_rfi_flush(enum l1d_flush_type types, bool enable)
|
||||
{
|
||||
if (types & L1D_FLUSH_FALLBACK) {
|
||||
pr_info("rfi-flush: Using fallback displacement flush\n");
|
||||
init_fallback_flush();
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_ORI)
|
||||
pr_info("rfi-flush: Using ori type flush\n");
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
pr_info("rfi-flush: Using mttrig type flush\n");
|
||||
|
||||
enabled_flush_types = types;
|
||||
|
||||
if (!no_rfi_flush)
|
||||
rfi_flush_enable(enable);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int rfi_flush_set(void *data, u64 val)
|
||||
{
|
||||
if (val == 1)
|
||||
rfi_flush_enable(true);
|
||||
else if (val == 0)
|
||||
rfi_flush_enable(false);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfi_flush_get(void *data, u64 *val)
|
||||
{
|
||||
*val = rfi_flush ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
|
||||
|
||||
static __init int rfi_flush_debugfs_init(void)
|
||||
{
|
||||
debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(rfi_flush_debugfs_init);
|
||||
#endif
|
||||
|
||||
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (rfi_flush)
|
||||
return sprintf(buf, "Mitigation: RFI Flush\n");
|
||||
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
|
|
|||
|
|
@ -73,6 +73,15 @@ SECTIONS
|
|||
/* Read-only data */
|
||||
RODATA
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
. = ALIGN(8);
|
||||
__rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) {
|
||||
__start___rfi_flush_fixup = .;
|
||||
*(__rfi_flush_fixup)
|
||||
__stop___rfi_flush_fixup = .;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXCEPTION_TABLE(0)
|
||||
|
||||
NOTES :kernel :notes
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ _GLOBAL_TOC(kvmppc_hv_entry_trampoline)
|
|||
mtmsrd r0,1 /* clear RI in MSR */
|
||||
mtsrr0 r5
|
||||
mtsrr1 r6
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
kvmppc_call_hv_entry:
|
||||
ld r4, HSTATE_KVM_VCPU(r13)
|
||||
|
|
@ -170,7 +170,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|||
mtsrr0 r8
|
||||
mtsrr1 r7
|
||||
beq cr1, 13f /* machine check */
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
/* On POWER7, we have external interrupts set to use HSRR0/1 */
|
||||
11: mtspr SPRN_HSRR0, r8
|
||||
|
|
@ -965,8 +965,7 @@ BEGIN_FTR_SECTION
|
|||
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
||||
ld r0, VCPU_GPR(R0)(r4)
|
||||
ld r4, VCPU_GPR(R4)(r4)
|
||||
|
||||
hrfid
|
||||
HRFI_TO_GUEST
|
||||
b .
|
||||
|
||||
secondary_too_late:
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@
|
|||
|
||||
#define FUNC(name) name
|
||||
|
||||
#define RFI_TO_KERNEL RFI
|
||||
#define RFI_TO_GUEST RFI
|
||||
|
||||
.macro INTERRUPT_TRAMPOLINE intno
|
||||
|
||||
.global kvmppc_trampoline_\intno
|
||||
|
|
@ -141,7 +144,7 @@ kvmppc_handler_skip_ins:
|
|||
GET_SCRATCH0(r13)
|
||||
|
||||
/* And get back into the code */
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -164,6 +167,6 @@ _GLOBAL_TOC(kvmppc_entry_trampoline)
|
|||
ori r5, r5, MSR_EE
|
||||
mtsrr0 r7
|
||||
mtsrr1 r6
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
|
||||
#include "book3s_segment.S"
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ no_dcbz32_on:
|
|||
PPC_LL r9, SVCPU_R9(r3)
|
||||
PPC_LL r3, (SVCPU_R3)(r3)
|
||||
|
||||
RFI
|
||||
RFI_TO_GUEST
|
||||
kvmppc_handler_trampoline_enter_end:
|
||||
|
||||
|
||||
|
|
@ -389,5 +389,5 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
|
|||
cmpwi r12, BOOK3S_INTERRUPT_DOORBELL
|
||||
beqa BOOK3S_INTERRUPT_DOORBELL
|
||||
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
kvmppc_handler_trampoline_exit_end:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <asm/code-patching.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
|
||||
struct fixup_entry {
|
||||
|
|
@ -113,6 +114,47 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
{
|
||||
unsigned int instrs[3], *dest;
|
||||
long *start, *end;
|
||||
int i;
|
||||
|
||||
start = PTRRELOC(&__start___rfi_flush_fixup),
|
||||
end = PTRRELOC(&__stop___rfi_flush_fixup);
|
||||
|
||||
instrs[0] = 0x60000000; /* nop */
|
||||
instrs[1] = 0x60000000; /* nop */
|
||||
instrs[2] = 0x60000000; /* nop */
|
||||
|
||||
if (types & L1D_FLUSH_FALLBACK)
|
||||
/* b .+16 to fallback flush */
|
||||
instrs[0] = 0x48000010;
|
||||
|
||||
i = 0;
|
||||
if (types & L1D_FLUSH_ORI) {
|
||||
instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
|
||||
instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
|
||||
}
|
||||
|
||||
if (types & L1D_FLUSH_MTTRIG)
|
||||
instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i);
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
|
||||
{
|
||||
long *start, *end;
|
||||
|
|
|
|||
|
|
@ -1381,7 +1381,7 @@ static int collect_events(struct perf_event *group, int max_count,
|
|||
int n = 0;
|
||||
struct perf_event *event;
|
||||
|
||||
if (!is_software_event(group)) {
|
||||
if (group->pmu->task_ctx_nr == perf_hw_context) {
|
||||
if (n >= max_count)
|
||||
return -1;
|
||||
ctrs[n] = group;
|
||||
|
|
@ -1389,7 +1389,7 @@ static int collect_events(struct perf_event *group, int max_count,
|
|||
events[n++] = group->hw.config;
|
||||
}
|
||||
list_for_each_entry(event, &group->sibling_list, group_entry) {
|
||||
if (!is_software_event(event) &&
|
||||
if (event->pmu->task_ctx_nr == perf_hw_context &&
|
||||
event->state != PERF_EVENT_STATE_OFF) {
|
||||
if (n >= max_count)
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -35,13 +35,63 @@
|
|||
#include <asm/opal.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/tm.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include "powernv.h"
|
||||
|
||||
static void pnv_setup_rfi_flush(void)
|
||||
{
|
||||
struct device_node *np, *fw_features;
|
||||
enum l1d_flush_type type;
|
||||
int enable;
|
||||
|
||||
/* Default to fallback in case fw-features are not available */
|
||||
type = L1D_FLUSH_FALLBACK;
|
||||
enable = 1;
|
||||
|
||||
np = of_find_node_by_name(NULL, "ibm,opal");
|
||||
fw_features = of_get_child_by_name(np, "fw-features");
|
||||
of_node_put(np);
|
||||
|
||||
if (fw_features) {
|
||||
np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2");
|
||||
if (np && of_property_read_bool(np, "enabled"))
|
||||
type = L1D_FLUSH_MTTRIG;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
np = of_get_child_by_name(fw_features, "inst-l1d-flush-ori30,30,0");
|
||||
if (np && of_property_read_bool(np, "enabled"))
|
||||
type = L1D_FLUSH_ORI;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
/* Enable unless firmware says NOT to */
|
||||
enable = 2;
|
||||
np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-hv-1-to-0");
|
||||
if (np && of_property_read_bool(np, "disabled"))
|
||||
enable--;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-pr-0-to-1");
|
||||
if (np && of_property_read_bool(np, "disabled"))
|
||||
enable--;
|
||||
|
||||
of_node_put(np);
|
||||
of_node_put(fw_features);
|
||||
}
|
||||
|
||||
setup_rfi_flush(type, enable > 0);
|
||||
}
|
||||
|
||||
static void __init pnv_setup_arch(void)
|
||||
{
|
||||
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
|
||||
|
||||
pnv_setup_rfi_flush();
|
||||
|
||||
/* Initialize SMP */
|
||||
pnv_smp_init();
|
||||
|
||||
|
|
|
|||
|
|
@ -499,6 +499,39 @@ static void __init find_and_init_phbs(void)
|
|||
of_pci_check_probe_only();
|
||||
}
|
||||
|
||||
static void pseries_setup_rfi_flush(void)
|
||||
{
|
||||
struct h_cpu_char_result result;
|
||||
enum l1d_flush_type types;
|
||||
bool enable;
|
||||
long rc;
|
||||
|
||||
/* Enable by default */
|
||||
enable = true;
|
||||
|
||||
rc = plpar_get_cpu_characteristics(&result);
|
||||
if (rc == H_SUCCESS) {
|
||||
types = L1D_FLUSH_NONE;
|
||||
|
||||
if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2)
|
||||
types |= L1D_FLUSH_MTTRIG;
|
||||
if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30)
|
||||
types |= L1D_FLUSH_ORI;
|
||||
|
||||
/* Use fallback if nothing set in hcall */
|
||||
if (types == L1D_FLUSH_NONE)
|
||||
types = L1D_FLUSH_FALLBACK;
|
||||
|
||||
if (!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR))
|
||||
enable = false;
|
||||
} else {
|
||||
/* Default to fallback if case hcall is not available */
|
||||
types = L1D_FLUSH_FALLBACK;
|
||||
}
|
||||
|
||||
setup_rfi_flush(types, enable);
|
||||
}
|
||||
|
||||
static void __init pSeries_setup_arch(void)
|
||||
{
|
||||
set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
|
||||
|
|
@ -515,7 +548,9 @@ static void __init pSeries_setup_arch(void)
|
|||
|
||||
fwnmi_init();
|
||||
|
||||
/* By default, only probe PCI (can be overriden by rtas_pci) */
|
||||
pseries_setup_rfi_flush();
|
||||
|
||||
/* By default, only probe PCI (can be overridden by rtas_pci) */
|
||||
pci_add_flags(PCI_PROBE_ONLY);
|
||||
|
||||
/* Find and initialize PCI host bridges */
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ config S390
|
|||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
|
||||
select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
|
||||
select HAVE_CMPXCHG_DOUBLE
|
||||
select HAVE_CMPXCHG_LOCAL
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid)
|
|||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setgid16, u16, gid)
|
||||
{
|
||||
return sys_setgid((gid_t)gid);
|
||||
return sys_setgid(low2highgid(gid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(s390_setreuid16, u16, ruid, u16, euid)
|
||||
|
|
@ -120,7 +120,7 @@ COMPAT_SYSCALL_DEFINE2(s390_setreuid16, u16, ruid, u16, euid)
|
|||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setuid16, u16, uid)
|
||||
{
|
||||
return sys_setuid((uid_t)uid);
|
||||
return sys_setuid(low2highuid(uid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_setresuid16, u16, ruid, u16, euid, u16, suid)
|
||||
|
|
@ -173,12 +173,12 @@ COMPAT_SYSCALL_DEFINE3(s390_getresgid16, u16 __user *, rgidp,
|
|||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setfsuid16, u16, uid)
|
||||
{
|
||||
return sys_setfsuid((uid_t)uid);
|
||||
return sys_setfsuid(low2highuid(uid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setfsgid16, u16, gid)
|
||||
{
|
||||
return sys_setfsgid((gid_t)gid);
|
||||
return sys_setfsgid(low2highgid(gid));
|
||||
}
|
||||
|
||||
static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sh_eth.h>
|
||||
#include <mach-se/mach/se.h>
|
||||
#include <mach-se/mach/mrshpc.h>
|
||||
#include <asm/machvec.h>
|
||||
|
|
@ -114,6 +115,11 @@ static struct platform_device heartbeat_device = {
|
|||
#if defined(CONFIG_CPU_SUBTYPE_SH7710) ||\
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7712)
|
||||
/* SH771X Ethernet driver */
|
||||
static struct sh_eth_plat_data sh_eth_plat = {
|
||||
.phy = PHY_ID,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
static struct resource sh_eth0_resources[] = {
|
||||
[0] = {
|
||||
.start = SH_ETH0_BASE,
|
||||
|
|
@ -131,7 +137,7 @@ static struct platform_device sh_eth0_device = {
|
|||
.name = "sh771x-ether",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = PHY_ID,
|
||||
.platform_data = &sh_eth_plat,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(sh_eth0_resources),
|
||||
.resource = sh_eth0_resources,
|
||||
|
|
@ -154,7 +160,7 @@ static struct platform_device sh_eth1_device = {
|
|||
.name = "sh771x-ether",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = PHY_ID,
|
||||
.platform_data = &sh_eth_plat,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(sh_eth1_resources),
|
||||
.resource = sh_eth1_resources,
|
||||
|
|
|
|||
|
|
@ -607,7 +607,8 @@ asmlinkage void do_divide_error(unsigned long r4)
|
|||
break;
|
||||
}
|
||||
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
info.si_signo = SIGFPE;
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ config X86
|
|||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_ARCH_WITHIN_STACK_FRAMES
|
||||
select HAVE_BPF_JIT if X86_64
|
||||
select HAVE_EBPF_JIT if X86_64
|
||||
select HAVE_CC_STACKPROTECTOR
|
||||
select HAVE_CMPXCHG_DOUBLE
|
||||
select HAVE_CMPXCHG_LOCAL
|
||||
|
|
@ -1024,7 +1026,7 @@ config X86_MCE_THRESHOLD
|
|||
def_bool y
|
||||
|
||||
config X86_MCE_INJECT
|
||||
depends on X86_MCE
|
||||
depends on X86_MCE && X86_LOCAL_APIC
|
||||
tristate "Machine check injector support"
|
||||
---help---
|
||||
Provide support for injecting machine checks for testing purposes.
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ config X86_DEBUG_FPU
|
|||
|
||||
config PUNIT_ATOM_DEBUG
|
||||
tristate "ATOM Punit debug driver"
|
||||
depends on PCI
|
||||
select DEBUG_FS
|
||||
select IOSF_MBI
|
||||
---help---
|
||||
|
|
|
|||
|
|
@ -71,12 +71,13 @@ GCOV_PROFILE := n
|
|||
$(obj)/bzImage: asflags-y := $(SVGA_MODE)
|
||||
|
||||
quiet_cmd_image = BUILD $@
|
||||
silent_redirect_image = >/dev/null
|
||||
cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \
|
||||
$(obj)/zoffset.h $@
|
||||
$(obj)/zoffset.h $@ $($(quiet)redirect_image)
|
||||
|
||||
$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
|
||||
$(call if_changed,image)
|
||||
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
|
||||
@$(kecho) 'Kernel: $@ is ready' ' (#'`cat .version`')'
|
||||
|
||||
OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S
|
||||
$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
|
||||
|
|
|
|||
|
|
@ -965,7 +965,7 @@ static int helper_rfc4106_encrypt(struct aead_request *req)
|
|||
|
||||
if (sg_is_last(req->src) &&
|
||||
req->src->offset + req->src->length <= PAGE_SIZE &&
|
||||
sg_is_last(req->dst) &&
|
||||
sg_is_last(req->dst) && req->dst->length &&
|
||||
req->dst->offset + req->dst->length <= PAGE_SIZE) {
|
||||
one_entry_in_sg = 1;
|
||||
scatterwalk_start(&src_sg_walk, req->src);
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ static struct shash_alg alg = {
|
|||
.init = poly1305_simd_init,
|
||||
.update = poly1305_simd_update,
|
||||
.final = crypto_poly1305_final,
|
||||
.setkey = crypto_poly1305_setkey,
|
||||
.descsize = sizeof(struct poly1305_simd_desc_ctx),
|
||||
.base = {
|
||||
.cra_name = "poly1305",
|
||||
|
|
|
|||
|
|
@ -55,29 +55,31 @@
|
|||
#define RAB1bl %bl
|
||||
#define RAB2bl %cl
|
||||
|
||||
#define CD0 0x0(%rsp)
|
||||
#define CD1 0x8(%rsp)
|
||||
#define CD2 0x10(%rsp)
|
||||
|
||||
# used only before/after all rounds
|
||||
#define RCD0 %r8
|
||||
#define RCD1 %r9
|
||||
#define RCD2 %r10
|
||||
|
||||
#define RCD0d %r8d
|
||||
#define RCD1d %r9d
|
||||
#define RCD2d %r10d
|
||||
# used only during rounds
|
||||
#define RX0 %r8
|
||||
#define RX1 %r9
|
||||
#define RX2 %r10
|
||||
|
||||
#define RX0 %rbp
|
||||
#define RX1 %r11
|
||||
#define RX2 %r12
|
||||
#define RX0d %r8d
|
||||
#define RX1d %r9d
|
||||
#define RX2d %r10d
|
||||
|
||||
#define RX0d %ebp
|
||||
#define RX1d %r11d
|
||||
#define RX2d %r12d
|
||||
#define RY0 %r11
|
||||
#define RY1 %r12
|
||||
#define RY2 %r13
|
||||
|
||||
#define RY0 %r13
|
||||
#define RY1 %r14
|
||||
#define RY2 %r15
|
||||
|
||||
#define RY0d %r13d
|
||||
#define RY1d %r14d
|
||||
#define RY2d %r15d
|
||||
#define RY0d %r11d
|
||||
#define RY1d %r12d
|
||||
#define RY2d %r13d
|
||||
|
||||
#define RT0 %rdx
|
||||
#define RT1 %rsi
|
||||
|
|
@ -85,6 +87,8 @@
|
|||
#define RT0d %edx
|
||||
#define RT1d %esi
|
||||
|
||||
#define RT1bl %sil
|
||||
|
||||
#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
|
||||
movzbl ab ## bl, tmp2 ## d; \
|
||||
movzbl ab ## bh, tmp1 ## d; \
|
||||
|
|
@ -92,6 +96,11 @@
|
|||
op1##l T0(CTX, tmp2, 4), dst ## d; \
|
||||
op2##l T1(CTX, tmp1, 4), dst ## d;
|
||||
|
||||
#define swap_ab_with_cd(ab, cd, tmp) \
|
||||
movq cd, tmp; \
|
||||
movq ab, cd; \
|
||||
movq tmp, ab;
|
||||
|
||||
/*
|
||||
* Combined G1 & G2 function. Reordered with help of rotates to have moves
|
||||
* at begining.
|
||||
|
|
@ -110,15 +119,15 @@
|
|||
/* G1,2 && G2,2 */ \
|
||||
do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
|
||||
do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
|
||||
xchgq cd ## 0, ab ## 0; \
|
||||
swap_ab_with_cd(ab ## 0, cd ## 0, RT0); \
|
||||
\
|
||||
do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
|
||||
do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
|
||||
xchgq cd ## 1, ab ## 1; \
|
||||
swap_ab_with_cd(ab ## 1, cd ## 1, RT0); \
|
||||
\
|
||||
do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
|
||||
do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
|
||||
xchgq cd ## 2, ab ## 2;
|
||||
swap_ab_with_cd(ab ## 2, cd ## 2, RT0);
|
||||
|
||||
#define enc_round_end(ab, x, y, n) \
|
||||
addl y ## d, x ## d; \
|
||||
|
|
@ -168,6 +177,16 @@
|
|||
decrypt_round3(ba, dc, (n*2)+1); \
|
||||
decrypt_round3(ba, dc, (n*2));
|
||||
|
||||
#define push_cd() \
|
||||
pushq RCD2; \
|
||||
pushq RCD1; \
|
||||
pushq RCD0;
|
||||
|
||||
#define pop_cd() \
|
||||
popq RCD0; \
|
||||
popq RCD1; \
|
||||
popq RCD2;
|
||||
|
||||
#define inpack3(in, n, xy, m) \
|
||||
movq 4*(n)(in), xy ## 0; \
|
||||
xorq w+4*m(CTX), xy ## 0; \
|
||||
|
|
@ -223,11 +242,8 @@ ENTRY(__twofish_enc_blk_3way)
|
|||
* %rdx: src, RIO
|
||||
* %rcx: bool, if true: xor output
|
||||
*/
|
||||
pushq %r15;
|
||||
pushq %r14;
|
||||
pushq %r13;
|
||||
pushq %r12;
|
||||
pushq %rbp;
|
||||
pushq %rbx;
|
||||
|
||||
pushq %rcx; /* bool xor */
|
||||
|
|
@ -235,40 +251,36 @@ ENTRY(__twofish_enc_blk_3way)
|
|||
|
||||
inpack_enc3();
|
||||
|
||||
encrypt_cycle3(RAB, RCD, 0);
|
||||
encrypt_cycle3(RAB, RCD, 1);
|
||||
encrypt_cycle3(RAB, RCD, 2);
|
||||
encrypt_cycle3(RAB, RCD, 3);
|
||||
encrypt_cycle3(RAB, RCD, 4);
|
||||
encrypt_cycle3(RAB, RCD, 5);
|
||||
encrypt_cycle3(RAB, RCD, 6);
|
||||
encrypt_cycle3(RAB, RCD, 7);
|
||||
push_cd();
|
||||
encrypt_cycle3(RAB, CD, 0);
|
||||
encrypt_cycle3(RAB, CD, 1);
|
||||
encrypt_cycle3(RAB, CD, 2);
|
||||
encrypt_cycle3(RAB, CD, 3);
|
||||
encrypt_cycle3(RAB, CD, 4);
|
||||
encrypt_cycle3(RAB, CD, 5);
|
||||
encrypt_cycle3(RAB, CD, 6);
|
||||
encrypt_cycle3(RAB, CD, 7);
|
||||
pop_cd();
|
||||
|
||||
popq RIO; /* dst */
|
||||
popq %rbp; /* bool xor */
|
||||
popq RT1; /* bool xor */
|
||||
|
||||
testb %bpl, %bpl;
|
||||
testb RT1bl, RT1bl;
|
||||
jnz .L__enc_xor3;
|
||||
|
||||
outunpack_enc3(mov);
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
popq %r12;
|
||||
popq %r13;
|
||||
popq %r14;
|
||||
popq %r15;
|
||||
ret;
|
||||
|
||||
.L__enc_xor3:
|
||||
outunpack_enc3(xor);
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
popq %r12;
|
||||
popq %r13;
|
||||
popq %r14;
|
||||
popq %r15;
|
||||
ret;
|
||||
ENDPROC(__twofish_enc_blk_3way)
|
||||
|
||||
|
|
@ -278,35 +290,31 @@ ENTRY(twofish_dec_blk_3way)
|
|||
* %rsi: dst
|
||||
* %rdx: src, RIO
|
||||
*/
|
||||
pushq %r15;
|
||||
pushq %r14;
|
||||
pushq %r13;
|
||||
pushq %r12;
|
||||
pushq %rbp;
|
||||
pushq %rbx;
|
||||
|
||||
pushq %rsi; /* dst */
|
||||
|
||||
inpack_dec3();
|
||||
|
||||
decrypt_cycle3(RAB, RCD, 7);
|
||||
decrypt_cycle3(RAB, RCD, 6);
|
||||
decrypt_cycle3(RAB, RCD, 5);
|
||||
decrypt_cycle3(RAB, RCD, 4);
|
||||
decrypt_cycle3(RAB, RCD, 3);
|
||||
decrypt_cycle3(RAB, RCD, 2);
|
||||
decrypt_cycle3(RAB, RCD, 1);
|
||||
decrypt_cycle3(RAB, RCD, 0);
|
||||
push_cd();
|
||||
decrypt_cycle3(RAB, CD, 7);
|
||||
decrypt_cycle3(RAB, CD, 6);
|
||||
decrypt_cycle3(RAB, CD, 5);
|
||||
decrypt_cycle3(RAB, CD, 4);
|
||||
decrypt_cycle3(RAB, CD, 3);
|
||||
decrypt_cycle3(RAB, CD, 2);
|
||||
decrypt_cycle3(RAB, CD, 1);
|
||||
decrypt_cycle3(RAB, CD, 0);
|
||||
pop_cd();
|
||||
|
||||
popq RIO; /* dst */
|
||||
|
||||
outunpack_dec3();
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
popq %r12;
|
||||
popq %r13;
|
||||
popq %r14;
|
||||
popq %r15;
|
||||
ret;
|
||||
ENDPROC(twofish_dec_blk_3way)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/context_tracking.h>
|
||||
#include <linux/user-return-notifier.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/uprobes.h>
|
||||
|
||||
#include <asm/desc.h>
|
||||
|
|
@ -381,6 +382,7 @@ __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
|
|||
}
|
||||
|
||||
if (likely(nr < IA32_NR_syscalls)) {
|
||||
nr = array_index_nospec(nr, IA32_NR_syscalls);
|
||||
/*
|
||||
* It's possible that a 32-bit syscall implementation
|
||||
* takes a 64-bit parameter but nonetheless assumes that
|
||||
|
|
|
|||
|
|
@ -37,5 +37,4 @@ INDIRECT_THUNK(dx)
|
|||
INDIRECT_THUNK(si)
|
||||
INDIRECT_THUNK(di)
|
||||
INDIRECT_THUNK(bp)
|
||||
INDIRECT_THUNK(sp)
|
||||
#endif /* CONFIG_RETPOLINE */
|
||||
|
|
|
|||
|
|
@ -11,10 +11,12 @@
|
|||
# define __ASM_FORM_COMMA(x) " " #x ","
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
#ifndef __x86_64__
|
||||
/* 32 bit */
|
||||
# define __ASM_SEL(a,b) __ASM_FORM(a)
|
||||
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(a)
|
||||
#else
|
||||
/* 64 bit */
|
||||
# define __ASM_SEL(a,b) __ASM_FORM(b)
|
||||
# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,6 +24,34 @@
|
|||
#define wmb() asm volatile("sfence" ::: "memory")
|
||||
#endif
|
||||
|
||||
/**
|
||||
* array_index_mask_nospec() - generate a mask that is ~0UL when the
|
||||
* bounds check succeeds and 0 otherwise
|
||||
* @index: array element index
|
||||
* @size: number of elements in array
|
||||
*
|
||||
* Returns:
|
||||
* 0 - (index < size)
|
||||
*/
|
||||
static inline unsigned long array_index_mask_nospec(unsigned long index,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
asm ("cmp %1,%2; sbb %0,%0;"
|
||||
:"=r" (mask)
|
||||
:"r"(size),"r" (index)
|
||||
:"cc");
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* Override the default implementation from linux/nospec.h. */
|
||||
#define array_index_mask_nospec array_index_mask_nospec
|
||||
|
||||
/* Prevent speculative execution past this barrier. */
|
||||
#define barrier_nospec() alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC, \
|
||||
"lfence", X86_FEATURE_LFENCE_RDTSC)
|
||||
|
||||
#ifdef CONFIG_X86_PPRO_FENCE
|
||||
#define dma_rmb() rmb()
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -998,7 +998,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
|
|||
static inline int emulate_instruction(struct kvm_vcpu *vcpu,
|
||||
int emulation_type)
|
||||
{
|
||||
return x86_emulate_instruction(vcpu, 0, emulation_type, NULL, 0);
|
||||
return x86_emulate_instruction(vcpu, 0,
|
||||
emulation_type | EMULTYPE_NO_REEXECUTE, NULL, 0);
|
||||
}
|
||||
|
||||
void kvm_enable_efer_bits(u64);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
|
|||
|
||||
extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
|
||||
extern int apply_microcode_amd(int cpu);
|
||||
extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);
|
||||
|
||||
#define PATCH_MAX_SIZE PAGE_SIZE
|
||||
extern u8 amd_ucode_patch[PATCH_MAX_SIZE];
|
||||
|
|
|
|||
|
|
@ -147,8 +147,7 @@ static __always_inline unsigned long long rdtsc_ordered(void)
|
|||
* that some other imaginary CPU is updating continuously with a
|
||||
* time stamp.
|
||||
*/
|
||||
alternative_2("", "mfence", X86_FEATURE_MFENCE_RDTSC,
|
||||
"lfence", X86_FEATURE_LFENCE_RDTSC);
|
||||
barrier_nospec();
|
||||
return rdtsc();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __NOSPEC_BRANCH_H__
|
||||
#define __NOSPEC_BRANCH_H__
|
||||
#ifndef _ASM_X86_NOSPEC_BRANCH_H_
|
||||
#define _ASM_X86_NOSPEC_BRANCH_H_
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/alternative-asm.h>
|
||||
|
|
@ -178,7 +178,7 @@ extern char __indirect_thunk_end[];
|
|||
* On VMEXIT we must ensure that no RSB predictions learned in the guest
|
||||
* can be followed in the host, by overwriting the RSB completely. Both
|
||||
* retpoline and IBRS mitigations for Spectre v2 need this; only on future
|
||||
* CPUs with IBRS_ATT *might* it be avoided.
|
||||
* CPUs with IBRS_ALL *might* it be avoided.
|
||||
*/
|
||||
static inline void vmexit_fill_RSB(void)
|
||||
{
|
||||
|
|
@ -195,4 +195,4 @@ static inline void vmexit_fill_RSB(void)
|
|||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __NOSPEC_BRANCH_H__ */
|
||||
#endif /* _ASM_X86_NOSPEC_BRANCH_H_ */
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ struct cpuinfo_x86 {
|
|||
char x86_vendor_id[16];
|
||||
char x86_model_id[64];
|
||||
/* in KB - valid for CPUS which support this call: */
|
||||
int x86_cache_size;
|
||||
unsigned int x86_cache_size;
|
||||
int x86_cache_alignment; /* In bytes */
|
||||
/* Cache QoS architectural values: */
|
||||
int x86_cache_max_rmid; /* max index */
|
||||
|
|
|
|||
|
|
@ -400,10 +400,11 @@ enum vmcs_field {
|
|||
#define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT (KVM_USER_MEM_SLOTS + 2)
|
||||
|
||||
#define VMX_NR_VPIDS (1 << 16)
|
||||
#define VMX_VPID_EXTENT_INDIVIDUAL_ADDR 0
|
||||
#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1
|
||||
#define VMX_VPID_EXTENT_ALL_CONTEXT 2
|
||||
#define VMX_VPID_EXTENT_SINGLE_NON_GLOBAL 3
|
||||
|
||||
#define VMX_EPT_EXTENT_INDIVIDUAL_ADDR 0
|
||||
#define VMX_EPT_EXTENT_CONTEXT 1
|
||||
#define VMX_EPT_EXTENT_GLOBAL 2
|
||||
#define VMX_EPT_EXTENT_SHIFT 24
|
||||
|
|
@ -420,8 +421,10 @@ enum vmcs_field {
|
|||
#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)
|
||||
|
||||
#define VMX_VPID_INVVPID_BIT (1ull << 0) /* (32 - 32) */
|
||||
#define VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT (1ull << 8) /* (40 - 32) */
|
||||
#define VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT (1ull << 9) /* (41 - 32) */
|
||||
#define VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT (1ull << 10) /* (42 - 32) */
|
||||
#define VMX_VPID_EXTENT_SINGLE_NON_GLOBAL_BIT (1ull << 11) /* (43 - 32) */
|
||||
|
||||
#define VMX_EPT_DEFAULT_GAW 3
|
||||
#define VMX_EPT_MAX_GAW 0x4
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ extern void map_vsyscall(void);
|
|||
*/
|
||||
extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
|
||||
extern bool vsyscall_enabled(void);
|
||||
extern unsigned long vsyscall_pgprot;
|
||||
#else
|
||||
static inline void map_vsyscall(void) {}
|
||||
static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
|
||||
|
|
@ -22,5 +21,6 @@ static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
|
|||
}
|
||||
static inline bool vsyscall_enabled(void) { return false; }
|
||||
#endif
|
||||
extern unsigned long vsyscall_pgprot;
|
||||
|
||||
#endif /* _ASM_X86_VSYSCALL_H */
|
||||
|
|
|
|||
|
|
@ -45,17 +45,6 @@ static int __init setup_noreplace_smp(char *str)
|
|||
}
|
||||
__setup("noreplace-smp", setup_noreplace_smp);
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
static int __initdata_or_module noreplace_paravirt = 0;
|
||||
|
||||
static int __init setup_noreplace_paravirt(char *str)
|
||||
{
|
||||
noreplace_paravirt = 1;
|
||||
return 1;
|
||||
}
|
||||
__setup("noreplace-paravirt", setup_noreplace_paravirt);
|
||||
#endif
|
||||
|
||||
#define DPRINTK(fmt, args...) \
|
||||
do { \
|
||||
if (debug_alternative) \
|
||||
|
|
@ -587,9 +576,6 @@ void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
|
|||
struct paravirt_patch_site *p;
|
||||
char insnbuf[MAX_PATCH_LEN];
|
||||
|
||||
if (noreplace_paravirt)
|
||||
return;
|
||||
|
||||
for (p = start; p < end; p++) {
|
||||
unsigned int used;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/cmdline.h>
|
||||
|
|
@ -89,20 +90,42 @@ static const char *spectre_v2_strings[] = {
|
|||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "Spectre V2 mitigation: " fmt
|
||||
#define pr_fmt(fmt) "Spectre V2 : " fmt
|
||||
|
||||
static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
|
||||
|
||||
|
||||
#ifdef RETPOLINE
|
||||
static bool spectre_v2_bad_module;
|
||||
|
||||
bool retpoline_module_ok(bool has_retpoline)
|
||||
{
|
||||
if (spectre_v2_enabled == SPECTRE_V2_NONE || has_retpoline)
|
||||
return true;
|
||||
|
||||
pr_err("System may be vulnerable to spectre v2\n");
|
||||
spectre_v2_bad_module = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline const char *spectre_v2_module_string(void)
|
||||
{
|
||||
return spectre_v2_bad_module ? " - vulnerable module loaded" : "";
|
||||
}
|
||||
#else
|
||||
static inline const char *spectre_v2_module_string(void) { return ""; }
|
||||
#endif
|
||||
|
||||
static void __init spec2_print_if_insecure(const char *reason)
|
||||
{
|
||||
if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
|
||||
pr_info("%s\n", reason);
|
||||
pr_info("%s selected on command line.\n", reason);
|
||||
}
|
||||
|
||||
static void __init spec2_print_if_secure(const char *reason)
|
||||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
|
||||
pr_info("%s\n", reason);
|
||||
pr_info("%s selected on command line.\n", reason);
|
||||
}
|
||||
|
||||
static inline bool retp_compiler(void)
|
||||
|
|
@ -117,42 +140,68 @@ static inline bool match_option(const char *arg, int arglen, const char *opt)
|
|||
return len == arglen && !strncmp(arg, opt, len);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *option;
|
||||
enum spectre_v2_mitigation_cmd cmd;
|
||||
bool secure;
|
||||
} mitigation_options[] = {
|
||||
{ "off", SPECTRE_V2_CMD_NONE, false },
|
||||
{ "on", SPECTRE_V2_CMD_FORCE, true },
|
||||
{ "retpoline", SPECTRE_V2_CMD_RETPOLINE, false },
|
||||
{ "retpoline,amd", SPECTRE_V2_CMD_RETPOLINE_AMD, false },
|
||||
{ "retpoline,generic", SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
|
||||
{ "auto", SPECTRE_V2_CMD_AUTO, false },
|
||||
};
|
||||
|
||||
static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
|
||||
{
|
||||
char arg[20];
|
||||
int ret;
|
||||
int ret, i;
|
||||
enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
|
||||
|
||||
ret = cmdline_find_option(boot_command_line, "spectre_v2", arg,
|
||||
sizeof(arg));
|
||||
if (ret > 0) {
|
||||
if (match_option(arg, ret, "off")) {
|
||||
goto disable;
|
||||
} else if (match_option(arg, ret, "on")) {
|
||||
spec2_print_if_secure("force enabled on command line.");
|
||||
return SPECTRE_V2_CMD_FORCE;
|
||||
} else if (match_option(arg, ret, "retpoline")) {
|
||||
spec2_print_if_insecure("retpoline selected on command line.");
|
||||
return SPECTRE_V2_CMD_RETPOLINE;
|
||||
} else if (match_option(arg, ret, "retpoline,amd")) {
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
|
||||
pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n");
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
}
|
||||
spec2_print_if_insecure("AMD retpoline selected on command line.");
|
||||
return SPECTRE_V2_CMD_RETPOLINE_AMD;
|
||||
} else if (match_option(arg, ret, "retpoline,generic")) {
|
||||
spec2_print_if_insecure("generic retpoline selected on command line.");
|
||||
return SPECTRE_V2_CMD_RETPOLINE_GENERIC;
|
||||
} else if (match_option(arg, ret, "auto")) {
|
||||
if (cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
|
||||
return SPECTRE_V2_CMD_NONE;
|
||||
else {
|
||||
ret = cmdline_find_option(boot_command_line, "spectre_v2", arg,
|
||||
sizeof(arg));
|
||||
if (ret < 0)
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
|
||||
if (!match_option(arg, ret, mitigation_options[i].option))
|
||||
continue;
|
||||
cmd = mitigation_options[i].cmd;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(mitigation_options)) {
|
||||
pr_err("unknown option (%s). Switching to AUTO select\n",
|
||||
mitigation_options[i].option);
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
|
||||
if ((cmd == SPECTRE_V2_CMD_RETPOLINE ||
|
||||
cmd == SPECTRE_V2_CMD_RETPOLINE_AMD ||
|
||||
cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC) &&
|
||||
!IS_ENABLED(CONFIG_RETPOLINE)) {
|
||||
pr_err("%s selected but not compiled in. Switching to AUTO select\n",
|
||||
mitigation_options[i].option);
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
disable:
|
||||
spec2_print_if_insecure("disabled on command line.");
|
||||
return SPECTRE_V2_CMD_NONE;
|
||||
}
|
||||
|
||||
if (cmd == SPECTRE_V2_CMD_RETPOLINE_AMD &&
|
||||
boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
|
||||
pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n");
|
||||
return SPECTRE_V2_CMD_AUTO;
|
||||
}
|
||||
|
||||
if (mitigation_options[i].secure)
|
||||
spec2_print_if_secure(mitigation_options[i].option);
|
||||
else
|
||||
spec2_print_if_insecure(mitigation_options[i].option);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* Check for Skylake-like CPUs (for RSB handling) */
|
||||
|
|
@ -190,10 +239,10 @@ static void __init spectre_v2_select_mitigation(void)
|
|||
return;
|
||||
|
||||
case SPECTRE_V2_CMD_FORCE:
|
||||
/* FALLTRHU */
|
||||
case SPECTRE_V2_CMD_AUTO:
|
||||
goto retpoline_auto;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RETPOLINE))
|
||||
goto retpoline_auto;
|
||||
break;
|
||||
case SPECTRE_V2_CMD_RETPOLINE_AMD:
|
||||
if (IS_ENABLED(CONFIG_RETPOLINE))
|
||||
goto retpoline_amd;
|
||||
|
|
@ -268,7 +317,7 @@ ssize_t cpu_show_spectre_v1(struct device *dev,
|
|||
{
|
||||
if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v2(struct device *dev,
|
||||
|
|
@ -277,6 +326,7 @@ ssize_t cpu_show_spectre_v2(struct device *dev,
|
|||
if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
|
||||
return sprintf(buf, "Not affected\n");
|
||||
|
||||
return sprintf(buf, "%s\n", spectre_v2_strings[spectre_v2_enabled]);
|
||||
return sprintf(buf, "%s%s\n", spectre_v2_strings[spectre_v2_enabled],
|
||||
spectre_v2_module_string());
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -955,7 +955,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
|
|||
int i;
|
||||
|
||||
c->loops_per_jiffy = loops_per_jiffy;
|
||||
c->x86_cache_size = -1;
|
||||
c->x86_cache_size = 0;
|
||||
c->x86_vendor = X86_VENDOR_UNKNOWN;
|
||||
c->x86_model = c->x86_mask = 0; /* So far unknown... */
|
||||
c->x86_vendor_id[0] = '\0'; /* Unset */
|
||||
|
|
|
|||
|
|
@ -152,7 +152,6 @@ static void raise_mce(struct mce *m)
|
|||
if (context == MCJ_CTX_RANDOM)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
if (m->inject_flags & (MCJ_IRQ_BROADCAST | MCJ_NMI_BROADCAST)) {
|
||||
unsigned long start;
|
||||
int cpu;
|
||||
|
|
@ -193,9 +192,7 @@ static void raise_mce(struct mce *m)
|
|||
raise_local();
|
||||
put_cpu();
|
||||
put_online_cpus();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
} else {
|
||||
preempt_disable();
|
||||
raise_local();
|
||||
preempt_enable();
|
||||
|
|
|
|||
|
|
@ -131,6 +131,9 @@ static size_t compute_container_size(u8 *data, u32 total_size)
|
|||
return size;
|
||||
}
|
||||
|
||||
static enum ucode_state
|
||||
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size);
|
||||
|
||||
/*
|
||||
* Early load occurs before we can vmalloc(). So we look for the microcode
|
||||
* patch container file in initrd, traverse equivalent cpu table, look for a
|
||||
|
|
@ -438,7 +441,7 @@ int __init save_microcode_in_initrd_amd(void)
|
|||
eax = cpuid_eax(0x00000001);
|
||||
eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
|
||||
|
||||
ret = load_microcode_amd(smp_processor_id(), eax, container, container_size);
|
||||
ret = load_microcode_amd(true, eax, container, container_size);
|
||||
if (ret != UCODE_OK)
|
||||
retval = -EINVAL;
|
||||
|
||||
|
|
@ -854,7 +857,8 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
|
|||
return UCODE_OK;
|
||||
}
|
||||
|
||||
enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
|
||||
static enum ucode_state
|
||||
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
|
||||
{
|
||||
enum ucode_state ret;
|
||||
|
||||
|
|
@ -868,8 +872,8 @@ enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t s
|
|||
|
||||
#ifdef CONFIG_X86_32
|
||||
/* save BSP's matching patch for early load */
|
||||
if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
|
||||
struct ucode_patch *p = find_patch(cpu);
|
||||
if (save) {
|
||||
struct ucode_patch *p = find_patch(0);
|
||||
if (p) {
|
||||
memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
|
||||
memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data),
|
||||
|
|
@ -901,11 +905,12 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
|
|||
{
|
||||
char fw_name[36] = "amd-ucode/microcode_amd.bin";
|
||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
||||
bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
|
||||
enum ucode_state ret = UCODE_NFOUND;
|
||||
const struct firmware *fw;
|
||||
|
||||
/* reload ucode container only on the boot cpu */
|
||||
if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index)
|
||||
if (!refresh_fw || !bsp)
|
||||
return UCODE_OK;
|
||||
|
||||
if (c->x86 >= 0x15)
|
||||
|
|
@ -922,7 +927,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
|
|||
goto fw_release;
|
||||
}
|
||||
|
||||
ret = load_microcode_amd(cpu, c->x86, fw->data, fw->size);
|
||||
ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size);
|
||||
|
||||
fw_release:
|
||||
release_firmware(fw);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
static struct microcode_ops *microcode_ops;
|
||||
|
||||
static bool dis_ucode_ldr;
|
||||
static bool dis_ucode_ldr = true;
|
||||
|
||||
static int __init disable_loader(char *str)
|
||||
{
|
||||
|
|
@ -81,6 +81,7 @@ struct cpu_info_ctx {
|
|||
|
||||
static bool __init check_loader_disabled_bsp(void)
|
||||
{
|
||||
u32 a, b, c, d;
|
||||
#ifdef CONFIG_X86_32
|
||||
const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
|
||||
const char *opt = "dis_ucode_ldr";
|
||||
|
|
@ -93,8 +94,20 @@ static bool __init check_loader_disabled_bsp(void)
|
|||
bool *res = &dis_ucode_ldr;
|
||||
#endif
|
||||
|
||||
if (cmdline_find_option_bool(cmdline, option))
|
||||
*res = true;
|
||||
a = 1;
|
||||
c = 0;
|
||||
native_cpuid(&a, &b, &c, &d);
|
||||
|
||||
/*
|
||||
* CPUID(1).ECX[31]: reserved for hypervisor use. This is still not
|
||||
* completely accurate as xen pv guests don't see that CPUID bit set but
|
||||
* that's good enough as they don't land on the BSP path anyway.
|
||||
*/
|
||||
if (c & BIT(31))
|
||||
return *res;
|
||||
|
||||
if (cmdline_find_option_bool(cmdline, option) <= 0)
|
||||
*res = false;
|
||||
|
||||
return *res;
|
||||
}
|
||||
|
|
@ -122,9 +135,7 @@ void __init load_ucode_bsp(void)
|
|||
{
|
||||
int vendor;
|
||||
unsigned int family;
|
||||
|
||||
if (check_loader_disabled_bsp())
|
||||
return;
|
||||
bool intel = true;
|
||||
|
||||
if (!have_cpuid_p())
|
||||
return;
|
||||
|
|
@ -134,16 +145,27 @@ void __init load_ucode_bsp(void)
|
|||
|
||||
switch (vendor) {
|
||||
case X86_VENDOR_INTEL:
|
||||
if (family >= 6)
|
||||
load_ucode_intel_bsp();
|
||||
if (family < 6)
|
||||
return;
|
||||
break;
|
||||
|
||||
case X86_VENDOR_AMD:
|
||||
if (family >= 0x10)
|
||||
load_ucode_amd_bsp(family);
|
||||
if (family < 0x10)
|
||||
return;
|
||||
intel = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_loader_disabled_bsp())
|
||||
return;
|
||||
|
||||
if (intel)
|
||||
load_ucode_intel_bsp();
|
||||
else
|
||||
load_ucode_amd_bsp(family);
|
||||
}
|
||||
|
||||
static bool check_loader_disabled_ap(void)
|
||||
|
|
@ -162,9 +184,6 @@ void load_ucode_ap(void)
|
|||
if (check_loader_disabled_ap())
|
||||
return;
|
||||
|
||||
if (!have_cpuid_p())
|
||||
return;
|
||||
|
||||
vendor = x86_vendor();
|
||||
family = x86_family();
|
||||
|
||||
|
|
|
|||
|
|
@ -1075,7 +1075,7 @@ static struct microcode_ops microcode_intel_ops = {
|
|||
|
||||
static int __init calc_llc_size_per_core(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 llc_size = c->x86_cache_size * 1024;
|
||||
u64 llc_size = c->x86_cache_size * 1024ULL;
|
||||
|
||||
do_div(llc_size, c->x86_max_cores);
|
||||
|
||||
|
|
|
|||
|
|
@ -188,8 +188,8 @@ static void release_pmc_hardware(void) {}
|
|||
|
||||
static bool check_hw_exists(void)
|
||||
{
|
||||
u64 val, val_fail, val_new= ~0;
|
||||
int i, reg, reg_fail, ret = 0;
|
||||
u64 val, val_fail = -1, val_new= ~0;
|
||||
int i, reg, reg_fail = -1, ret = 0;
|
||||
int bios_fail = 0;
|
||||
int reg_safe = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/coredump.h>
|
||||
#include <linux/kaiser.h>
|
||||
|
||||
#include <asm-generic/sizes.h>
|
||||
#include <asm/perf_event.h>
|
||||
|
|
@ -67,6 +68,23 @@ static size_t buf_size(struct page *page)
|
|||
return 1 << (PAGE_SHIFT + page_private(page));
|
||||
}
|
||||
|
||||
static void bts_buffer_free_aux(void *data)
|
||||
{
|
||||
#ifdef CONFIG_PAGE_TABLE_ISOLATION
|
||||
struct bts_buffer *buf = data;
|
||||
int nbuf;
|
||||
|
||||
for (nbuf = 0; nbuf < buf->nr_bufs; nbuf++) {
|
||||
struct page *page = buf->buf[nbuf].page;
|
||||
void *kaddr = page_address(page);
|
||||
size_t page_size = buf_size(page);
|
||||
|
||||
kaiser_remove_mapping((unsigned long)kaddr, page_size);
|
||||
}
|
||||
#endif
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static void *
|
||||
bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
|
||||
{
|
||||
|
|
@ -103,29 +121,33 @@ bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
|
|||
buf->real_size = size - size % BTS_RECORD_SIZE;
|
||||
|
||||
for (pg = 0, nbuf = 0, offset = 0, pad = 0; nbuf < buf->nr_bufs; nbuf++) {
|
||||
unsigned int __nr_pages;
|
||||
void *kaddr = pages[pg];
|
||||
size_t page_size;
|
||||
|
||||
page = virt_to_page(kaddr);
|
||||
page_size = buf_size(page);
|
||||
|
||||
if (kaiser_add_mapping((unsigned long)kaddr,
|
||||
page_size, __PAGE_KERNEL) < 0) {
|
||||
buf->nr_bufs = nbuf;
|
||||
bts_buffer_free_aux(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
page = virt_to_page(pages[pg]);
|
||||
__nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
|
||||
buf->buf[nbuf].page = page;
|
||||
buf->buf[nbuf].offset = offset;
|
||||
buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
|
||||
buf->buf[nbuf].size = buf_size(page) - buf->buf[nbuf].displacement;
|
||||
buf->buf[nbuf].size = page_size - buf->buf[nbuf].displacement;
|
||||
pad = buf->buf[nbuf].size % BTS_RECORD_SIZE;
|
||||
buf->buf[nbuf].size -= pad;
|
||||
|
||||
pg += __nr_pages;
|
||||
offset += __nr_pages << PAGE_SHIFT;
|
||||
pg += page_size >> PAGE_SHIFT;
|
||||
offset += page_size;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void bts_buffer_free_aux(void *data)
|
||||
{
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static unsigned long bts_buffer_offset(struct bts_buffer *buf, unsigned int idx)
|
||||
{
|
||||
return buf->buf[idx].offset + buf->buf[idx].displacement;
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
}
|
||||
|
||||
/* Cache size */
|
||||
if (c->x86_cache_size >= 0)
|
||||
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
|
||||
if (c->x86_cache_size)
|
||||
seq_printf(m, "cache size\t: %u KB\n", c->x86_cache_size);
|
||||
|
||||
show_cpuinfo_core(m, c, cpu);
|
||||
show_cpuinfo_misc(m, c);
|
||||
|
|
|
|||
|
|
@ -669,14 +669,17 @@ __PAGE_ALIGNED_BSS
|
|||
initial_pg_pmd:
|
||||
.fill 1024*KPMDS,4,0
|
||||
#else
|
||||
ENTRY(initial_page_table)
|
||||
.globl initial_page_table
|
||||
initial_page_table:
|
||||
.fill 1024,4,0
|
||||
#endif
|
||||
initial_pg_fixmap:
|
||||
.fill 1024,4,0
|
||||
ENTRY(empty_zero_page)
|
||||
.globl empty_zero_page
|
||||
empty_zero_page:
|
||||
.fill 4096,1,0
|
||||
ENTRY(swapper_pg_dir)
|
||||
.globl swapper_pg_dir
|
||||
swapper_pg_dir:
|
||||
.fill 1024,4,0
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -140,6 +140,16 @@ static int map_tboot_page(unsigned long vaddr, unsigned long pfn,
|
|||
return -1;
|
||||
set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
|
||||
pte_unmap(pte);
|
||||
|
||||
/*
|
||||
* PTI poisons low addresses in the kernel page tables in the
|
||||
* name of making them unusable for userspace. To execute
|
||||
* code at such a low address, the poison must be cleared.
|
||||
*
|
||||
* Note: 'pgd' actually gets set in pud_alloc().
|
||||
*/
|
||||
pgd->pgd &= ~_PAGE_NX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ config KVM
|
|||
depends on HAVE_KVM
|
||||
depends on HIGH_RES_TIMERS
|
||||
# for TASKSTATS/TASK_DELAY_ACCT:
|
||||
depends on NET
|
||||
depends on NET && MULTIUSER
|
||||
depends on X86_LOCAL_APIC
|
||||
select PREEMPT_NOTIFIERS
|
||||
select MMU_NOTIFIER
|
||||
select ANON_INODES
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <asm/kvm_emulate.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#include "x86.h"
|
||||
#include "tss.h"
|
||||
|
|
@ -1000,8 +1001,8 @@ static u8 test_cc(unsigned int condition, unsigned long flags)
|
|||
void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf);
|
||||
|
||||
flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;
|
||||
asm("push %[flags]; popf; call *%[fastop]"
|
||||
: "=a"(rc) : [fastop]"r"(fop), [flags]"r"(flags));
|
||||
asm("push %[flags]; popf; " CALL_NOSPEC
|
||||
: "=a"(rc) : [thunk_target]"r"(fop), [flags]"r"(flags));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -4978,6 +4979,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
|||
bool op_prefix = false;
|
||||
bool has_seg_override = false;
|
||||
struct opcode opcode;
|
||||
u16 dummy;
|
||||
struct desc_struct desc;
|
||||
|
||||
ctxt->memop.type = OP_NONE;
|
||||
ctxt->memopp = NULL;
|
||||
|
|
@ -4996,6 +4999,11 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
|||
switch (mode) {
|
||||
case X86EMUL_MODE_REAL:
|
||||
case X86EMUL_MODE_VM86:
|
||||
def_op_bytes = def_ad_bytes = 2;
|
||||
ctxt->ops->get_segment(ctxt, &dummy, &desc, NULL, VCPU_SREG_CS);
|
||||
if (desc.d)
|
||||
def_op_bytes = def_ad_bytes = 4;
|
||||
break;
|
||||
case X86EMUL_MODE_PROT16:
|
||||
def_op_bytes = def_ad_bytes = 2;
|
||||
break;
|
||||
|
|
@ -5290,9 +5298,9 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *))
|
|||
ulong flags = (ctxt->eflags & EFLAGS_MASK) | X86_EFLAGS_IF;
|
||||
if (!(ctxt->d & ByteOp))
|
||||
fop += __ffs(ctxt->dst.bytes) * FASTOP_SIZE;
|
||||
asm("push %[flags]; popf; call *%[fastop]; pushf; pop %[flags]\n"
|
||||
asm("push %[flags]; popf; " CALL_NOSPEC "; pushf; pop %[flags]\n"
|
||||
: "+a"(ctxt->dst.val), "+d"(ctxt->src.val), [flags]"+D"(flags),
|
||||
[fastop]"+S"(fop)
|
||||
[thunk_target]"+S"(fop)
|
||||
: "c"(ctxt->src2.val));
|
||||
ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK);
|
||||
if (!fop) /* exception is returned in fop variable */
|
||||
|
|
|
|||
|
|
@ -247,8 +247,7 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
|
|||
index == RTC_GSI) {
|
||||
if (kvm_apic_match_dest(vcpu, NULL, 0,
|
||||
e->fields.dest_id, e->fields.dest_mode) ||
|
||||
(e->fields.trig_mode == IOAPIC_EDGE_TRIG &&
|
||||
kvm_apic_pending_eoi(vcpu, e->fields.vector)))
|
||||
kvm_apic_pending_eoi(vcpu, e->fields.vector))
|
||||
__set_bit(e->fields.vector,
|
||||
(unsigned long *)eoi_exit_bitmap);
|
||||
}
|
||||
|
|
@ -269,6 +268,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
|||
{
|
||||
unsigned index;
|
||||
bool mask_before, mask_after;
|
||||
int old_remote_irr, old_delivery_status;
|
||||
union kvm_ioapic_redirect_entry *e;
|
||||
|
||||
switch (ioapic->ioregsel) {
|
||||
|
|
@ -291,14 +291,28 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
|||
return;
|
||||
e = &ioapic->redirtbl[index];
|
||||
mask_before = e->fields.mask;
|
||||
/* Preserve read-only fields */
|
||||
old_remote_irr = e->fields.remote_irr;
|
||||
old_delivery_status = e->fields.delivery_status;
|
||||
if (ioapic->ioregsel & 1) {
|
||||
e->bits &= 0xffffffff;
|
||||
e->bits |= (u64) val << 32;
|
||||
} else {
|
||||
e->bits &= ~0xffffffffULL;
|
||||
e->bits |= (u32) val;
|
||||
e->fields.remote_irr = 0;
|
||||
}
|
||||
e->fields.remote_irr = old_remote_irr;
|
||||
e->fields.delivery_status = old_delivery_status;
|
||||
|
||||
/*
|
||||
* Some OSes (Linux, Xen) assume that Remote IRR bit will
|
||||
* be cleared by IOAPIC hardware when the entry is configured
|
||||
* as edge-triggered. This behavior is used to simulate an
|
||||
* explicit EOI on IOAPICs that don't have the EOI register.
|
||||
*/
|
||||
if (e->fields.trig_mode == IOAPIC_EDGE_TRIG)
|
||||
e->fields.remote_irr = 0;
|
||||
|
||||
mask_after = e->fields.mask;
|
||||
if (mask_before != mask_after)
|
||||
kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after);
|
||||
|
|
|
|||
|
|
@ -4503,7 +4503,7 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu)
|
|||
typedef bool (*slot_level_handler) (struct kvm *kvm, unsigned long *rmap);
|
||||
|
||||
/* The caller should hold mmu-lock before calling this function. */
|
||||
static bool
|
||||
static __always_inline bool
|
||||
slot_handle_level_range(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
slot_level_handler fn, int start_level, int end_level,
|
||||
gfn_t start_gfn, gfn_t end_gfn, bool lock_flush_tlb)
|
||||
|
|
@ -4533,7 +4533,7 @@ slot_handle_level_range(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
|||
return flush;
|
||||
}
|
||||
|
||||
static bool
|
||||
static __always_inline bool
|
||||
slot_handle_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
slot_level_handler fn, int start_level, int end_level,
|
||||
bool lock_flush_tlb)
|
||||
|
|
@ -4544,7 +4544,7 @@ slot_handle_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
|||
lock_flush_tlb);
|
||||
}
|
||||
|
||||
static bool
|
||||
static __always_inline bool
|
||||
slot_handle_all_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
slot_level_handler fn, bool lock_flush_tlb)
|
||||
{
|
||||
|
|
@ -4552,7 +4552,7 @@ slot_handle_all_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
|||
PT_MAX_HUGEPAGE_LEVEL, lock_flush_tlb);
|
||||
}
|
||||
|
||||
static bool
|
||||
static __always_inline bool
|
||||
slot_handle_large_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
slot_level_handler fn, bool lock_flush_tlb)
|
||||
{
|
||||
|
|
@ -4560,7 +4560,7 @@ slot_handle_large_level(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
|||
PT_MAX_HUGEPAGE_LEVEL, lock_flush_tlb);
|
||||
}
|
||||
|
||||
static bool
|
||||
static __always_inline bool
|
||||
slot_handle_leaf(struct kvm *kvm, struct kvm_memory_slot *memslot,
|
||||
slot_level_handler fn, bool lock_flush_tlb)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/tboot.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/nospec.h>
|
||||
#include "kvm_cache_regs.h"
|
||||
#include "x86.h"
|
||||
|
||||
|
|
@ -125,6 +126,12 @@ module_param_named(pml, enable_pml, bool, S_IRUGO);
|
|||
|
||||
#define VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE 5
|
||||
|
||||
#define VMX_VPID_EXTENT_SUPPORTED_MASK \
|
||||
(VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT | \
|
||||
VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT | \
|
||||
VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT | \
|
||||
VMX_VPID_EXTENT_SINGLE_NON_GLOBAL_BIT)
|
||||
|
||||
/*
|
||||
* These 2 parameters are used to config the controls for Pause-Loop Exiting:
|
||||
* ple_gap: upper bound on the amount of time between two successive
|
||||
|
|
@ -827,21 +834,18 @@ static const unsigned short vmcs_field_to_offset_table[] = {
|
|||
|
||||
static inline short vmcs_field_to_offset(unsigned long field)
|
||||
{
|
||||
BUILD_BUG_ON(ARRAY_SIZE(vmcs_field_to_offset_table) > SHRT_MAX);
|
||||
const size_t size = ARRAY_SIZE(vmcs_field_to_offset_table);
|
||||
unsigned short offset;
|
||||
|
||||
if (field >= ARRAY_SIZE(vmcs_field_to_offset_table))
|
||||
BUILD_BUG_ON(size > SHRT_MAX);
|
||||
if (field >= size)
|
||||
return -ENOENT;
|
||||
|
||||
/*
|
||||
* FIXME: Mitigation for CVE-2017-5753. To be replaced with a
|
||||
* generic mechanism.
|
||||
*/
|
||||
asm("lfence");
|
||||
|
||||
if (vmcs_field_to_offset_table[field] == 0)
|
||||
field = array_index_nospec(field, size);
|
||||
offset = vmcs_field_to_offset_table[field];
|
||||
if (offset == 0)
|
||||
return -ENOENT;
|
||||
|
||||
return vmcs_field_to_offset_table[field];
|
||||
return offset;
|
||||
}
|
||||
|
||||
static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -2659,8 +2663,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
|
|||
*/
|
||||
if (enable_vpid)
|
||||
vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT |
|
||||
VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT |
|
||||
VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
|
||||
VMX_VPID_EXTENT_SUPPORTED_MASK;
|
||||
else
|
||||
vmx->nested.nested_vmx_vpid_caps = 0;
|
||||
|
||||
|
|
@ -4514,7 +4517,7 @@ static int vmx_cpu_uses_apicv(struct kvm_vcpu *vcpu)
|
|||
return enable_apicv && lapic_in_kernel(vcpu);
|
||||
}
|
||||
|
||||
static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
|
||||
static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
int max_irr;
|
||||
|
|
@ -4525,19 +4528,15 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
|
|||
vmx->nested.pi_pending) {
|
||||
vmx->nested.pi_pending = false;
|
||||
if (!pi_test_and_clear_on(vmx->nested.pi_desc))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
max_irr = find_last_bit(
|
||||
(unsigned long *)vmx->nested.pi_desc->pir, 256);
|
||||
|
||||
if (max_irr == 256)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
vapic_page = kmap(vmx->nested.virtual_apic_page);
|
||||
if (!vapic_page) {
|
||||
WARN_ON(1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
__kvm_apic_update_irr(vmx->nested.pi_desc->pir, vapic_page);
|
||||
kunmap(vmx->nested.virtual_apic_page);
|
||||
|
||||
|
|
@ -4548,7 +4547,6 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
|
|||
vmcs_write16(GUEST_INTR_STATUS, status);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -4595,14 +4593,15 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
|
|||
|
||||
if (is_guest_mode(vcpu) &&
|
||||
vector == vmx->nested.posted_intr_nv) {
|
||||
/* the PIR and ON have been set by L1. */
|
||||
kvm_vcpu_trigger_posted_interrupt(vcpu);
|
||||
/*
|
||||
* If a posted intr is not recognized by hardware,
|
||||
* we will accomplish it in the next vmentry.
|
||||
*/
|
||||
vmx->nested.pi_pending = true;
|
||||
kvm_make_request(KVM_REQ_EVENT, vcpu);
|
||||
/* the PIR and ON have been set by L1. */
|
||||
if (!kvm_vcpu_trigger_posted_interrupt(vcpu))
|
||||
kvm_vcpu_kick(vcpu);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
|
@ -4954,7 +4953,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||
vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
|
||||
}
|
||||
|
||||
vmcs_writel(GUEST_RFLAGS, 0x02);
|
||||
kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
|
||||
kvm_rip_write(vcpu, 0xfff0);
|
||||
|
||||
vmcs_writel(GUEST_GDTR_BASE, 0);
|
||||
|
|
@ -6023,7 +6022,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
|
|||
if (test_bit(KVM_REQ_EVENT, &vcpu->requests))
|
||||
return 1;
|
||||
|
||||
err = emulate_instruction(vcpu, EMULTYPE_NO_REEXECUTE);
|
||||
err = emulate_instruction(vcpu, 0);
|
||||
|
||||
if (err == EMULATE_USER_EXIT) {
|
||||
++vcpu->stat.mmio_exits;
|
||||
|
|
@ -7367,7 +7366,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
|||
|
||||
types = (vmx->nested.nested_vmx_ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6;
|
||||
|
||||
if (!(types & (1UL << type))) {
|
||||
if (type >= 32 || !(types & (1 << type))) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
|
||||
skip_emulated_instruction(vcpu);
|
||||
|
|
@ -7424,9 +7423,10 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
|||
vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
|
||||
type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
|
||||
|
||||
types = (vmx->nested.nested_vmx_vpid_caps >> 8) & 0x7;
|
||||
types = (vmx->nested.nested_vmx_vpid_caps &
|
||||
VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8;
|
||||
|
||||
if (!(types & (1UL << type))) {
|
||||
if (type >= 32 || !(types & (1 << type))) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
|
||||
skip_emulated_instruction(vcpu);
|
||||
|
|
@ -7446,21 +7446,27 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
|
||||
switch (type) {
|
||||
case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
|
||||
case VMX_VPID_EXTENT_SINGLE_CONTEXT:
|
||||
/*
|
||||
* Old versions of KVM use the single-context version so we
|
||||
* have to support it; just treat it the same as all-context.
|
||||
*/
|
||||
case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
|
||||
if (!vpid) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case VMX_VPID_EXTENT_ALL_CONTEXT:
|
||||
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
|
||||
nested_vmx_succeed(vcpu);
|
||||
break;
|
||||
default:
|
||||
/* Trap individual address invalidation invvpid calls */
|
||||
BUG_ON(1);
|
||||
break;
|
||||
WARN_ON_ONCE(1);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
__vmx_flush_tlb(vcpu, vmx->nested.vpid02);
|
||||
nested_vmx_succeed(vcpu);
|
||||
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -8376,13 +8382,13 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
|
|||
"pushf\n\t"
|
||||
"orl $0x200, (%%" _ASM_SP ")\n\t"
|
||||
__ASM_SIZE(push) " $%c[cs]\n\t"
|
||||
"call *%[entry]\n\t"
|
||||
CALL_NOSPEC
|
||||
:
|
||||
#ifdef CONFIG_X86_64
|
||||
[sp]"=&r"(tmp)
|
||||
#endif
|
||||
:
|
||||
[entry]"r"(entry),
|
||||
THUNK_TARGET(entry),
|
||||
[ss]"i"(__KERNEL_DS),
|
||||
[cs]"i"(__KERNEL_CS)
|
||||
);
|
||||
|
|
@ -9239,11 +9245,6 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
|
|||
return false;
|
||||
}
|
||||
msr_bitmap = (unsigned long *)kmap(page);
|
||||
if (!msr_bitmap) {
|
||||
nested_release_page_clean(page);
|
||||
WARN_ON(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nested_cpu_has_virt_x2apic_mode(vmcs12)) {
|
||||
if (nested_cpu_has_apic_reg_virt(vmcs12))
|
||||
|
|
@ -10165,7 +10166,8 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return vmx_complete_nested_posted_interrupt(vcpu);
|
||||
vmx_complete_nested_posted_interrupt(vcpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 vmx_get_preemption_timer_value(struct kvm_vcpu *vcpu)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user