mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
This is the 4.4.132 stable release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAlr75p0ACgkQONu9yGCS aT7YbhAApRoY4GSubs/BHl0Rp24ElRrfxYzyAuB3BLkiMchnP2/5QvqVP1rUk44s GjceRff2+Ylk8BmgbmynuXYnNuKss8QC+yk0HB5RGu5GkwWWj1XnP/TUkHCaWR0a WeGs2L4anmg5yvf9gHkEjVKBxNTy/xKhGCKqnNEyZ6KE5o3mHigNZl0yW2yNWLSg XItDPGSnanhRwDUZv5j7TBsH5K9YFtjT9m631NiTGF0I0MI5UDnnKvXqjLsO2qxs oHerdOQcMZFCScn1GMSGDpz4kAp/JjQIAnwOsgw92usk2H8i6vGExIOKLGt5Jn/O 3a9hp4cn8dQiZ9oofPC43N3XmH3XfGQnQllkX7Zoh4qB6gheVHwiY0+rH9IDrdkn /Mv6HCMTSGJ7CcLwMRxBqvOKX6DT1iNaw2n2zzOwoLecDYRYn1W6pgOHWKl4uBcd j0xKEf1lUM0WrboOdF3j1slJXgpXXvJOrr7tPABbEKNcaOXdmIttN8CLRG5tV3GP TLH+Qz+xDzYH2chy4RVsCXO9S2gwXgtladXVh4LR913sY+k5J6KWPkmmCmwZD3Z5 txUG13UtAiThrijoRngtz0MDYXyh6Mn/9ylChRcQSYecFD2awGXjORKcWQUXfH1n 2Wq00QC6wNYirpqpGWlS1mi9XGTTpkRgPN0cWV3+QLG3D0lofhU= =bVRt -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlr+roQTHGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0NhNB/91m/l5eYo5M6f+qKJV8Ac2B0gipd1b MLLhy5mwBXOcf2QOBnBZnjx5CU9xrzZeF7jj/+Tc1gpthDunvjkg53eMS+uCAckO Y1se33rElexP71ywltihmEpubqDVpzsHwOgkbVkG+NKr76hQivrzB1mvPopc33bQ ezN9EYhZPCFawcW5lB2ps2L9ljWpUti6TmkIY6DOhJ7gseQ75wVcBtMYn7h8jlni kSCydBPOya5G3gEThq7y6nSS+0fz2mGyk4zayJb/Sod7qla/jZD0QIy4GtYA022I GvupctXHY/QxPWU+mAY3Mc84y0e/KOfUPbuvwyYKywL0Nwh4pBFRDAJi =OCfe -----END PGP SIGNATURE----- Merge tag 'v4.4.132' into linux-linaro-lsk-v4.4 This is the 4.4.132 stable release
This commit is contained in:
commit
0e7fcfff8d
|
|
@ -35,6 +35,15 @@ Optional properties:
|
|||
- ti,palmas-enable-dvfs2: Enable DVFS2. Configure pins for DVFS2 mode.
|
||||
Selection primary or secondary function associated to GPADC_START
|
||||
and SYSEN2 pin/pad for DVFS2 interface
|
||||
- ti,palmas-override-powerhold: This is applicable for PMICs for which
|
||||
GPIO7 is configured in POWERHOLD mode which has higher priority
|
||||
over DEV_ON bit and keeps the PMIC supplies on even after the DEV_ON
|
||||
bit is turned off. This property enables driver to over ride the
|
||||
POWERHOLD value to GPIO7 so as to turn off the PMIC in power off
|
||||
scenarios. So for GPIO7 if ti,palmas-override-powerhold is set
|
||||
then the GPIO_7 field should never be muxed to anything else.
|
||||
It should be set to POWERHOLD by default and only in case of
|
||||
power off scenarios the driver will over ride the mux value.
|
||||
|
||||
This binding uses the following generic properties as defined in
|
||||
pinctrl-bindings.txt:
|
||||
|
|
|
|||
|
|
@ -383,32 +383,6 @@ is not associated with a file:
|
|||
|
||||
or if empty, the mapping is anonymous.
|
||||
|
||||
The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
|
||||
of the individual tasks of a process. In this file you will see a mapping marked
|
||||
as [stack] if that task sees it as a stack. Hence, for the example above, the
|
||||
task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
|
||||
|
||||
08048000-08049000 r-xp 00000000 03:00 8312 /opt/test
|
||||
08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
|
||||
0804a000-0806b000 rw-p 00000000 00:00 0 [heap]
|
||||
a7cb1000-a7cb2000 ---p 00000000 00:00 0
|
||||
a7cb2000-a7eb2000 rw-p 00000000 00:00 0
|
||||
a7eb2000-a7eb3000 ---p 00000000 00:00 0
|
||||
a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack]
|
||||
a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
|
||||
a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
|
||||
a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
|
||||
a800b000-a800e000 rw-p 00000000 00:00 0
|
||||
a800e000-a8022000 r-xp 00000000 03:00 14462 /lib/libpthread.so.0
|
||||
a8022000-a8023000 r--p 00013000 03:00 14462 /lib/libpthread.so.0
|
||||
a8023000-a8024000 rw-p 00014000 03:00 14462 /lib/libpthread.so.0
|
||||
a8024000-a8027000 rw-p 00000000 00:00 0
|
||||
a8027000-a8043000 r-xp 00000000 03:00 8317 /lib/ld-linux.so.2
|
||||
a8043000-a8044000 r--p 0001b000 03:00 8317 /lib/ld-linux.so.2
|
||||
a8044000-a8045000 rw-p 0001c000 03:00 8317 /lib/ld-linux.so.2
|
||||
aff35000-aff4a000 rw-p 00000000 00:00 0
|
||||
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
|
||||
|
||||
The /proc/PID/smaps is an extension based on maps, showing the memory
|
||||
consumption for each of the process's mappings. For each of mappings there
|
||||
is a series of lines such as the following:
|
||||
|
|
|
|||
|
|
@ -2402,6 +2402,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
|
||||
noalign [KNL,ARM]
|
||||
|
||||
noaltinstr [S390] Disables alternative instructions patching
|
||||
(CPU alternatives feature).
|
||||
|
||||
noapic [SMP,APIC] Tells the kernel to not make use of any
|
||||
IOAPICs that may be present in the system.
|
||||
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 126
|
||||
SUBLEVEL = 132
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ accel_pins: pinmux_accel {
|
|||
&audio_codec {
|
||||
status = "okay";
|
||||
|
||||
reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
|
||||
gpio-reset = <&gpio1 16 GPIO_ACTIVE_LOW>;
|
||||
AVDD-supply = <&ldo3_reg>;
|
||||
IOVDD-supply = <&ldo3_reg>;
|
||||
DRVDD-supply = <&ldo3_reg>;
|
||||
|
|
|
|||
|
|
@ -411,6 +411,7 @@ tps659038: tps659038@58 {
|
|||
interrupt-controller;
|
||||
|
||||
ti,system-power-controller;
|
||||
ti,palmas-override-powerhold;
|
||||
|
||||
tps659038_pmic {
|
||||
compatible = "ti,tps659038-pmic";
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pinctrl@fffff400 {
|
|||
atmel,mux-mask = <
|
||||
/* A B C */
|
||||
0xffffffff 0xffe0399f 0xc000001c /* pioA */
|
||||
0x0007ffff 0x8000fe3f 0x00000000 /* pioB */
|
||||
0x0007ffff 0x00047e3f 0x00000000 /* pioB */
|
||||
0x80000000 0x07c0ffff 0xb83fffff /* pioC */
|
||||
0x003fffff 0x003f8000 0x00000000 /* pioD */
|
||||
>;
|
||||
|
|
|
|||
|
|
@ -410,6 +410,8 @@ &i2c1 {
|
|||
tps659038: tps659038@58 {
|
||||
compatible = "ti,tps659038";
|
||||
reg = <0x58>;
|
||||
ti,palmas-override-powerhold;
|
||||
ti,system-power-controller;
|
||||
|
||||
tps659038_pmic {
|
||||
compatible = "ti,tps659038-pmic";
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ &iomuxc {
|
|||
imx53-qsrb {
|
||||
pinctrl_pmic: pmicgrp {
|
||||
fsl,pins = <
|
||||
MX53_PAD_CSI0_DAT5__GPIO5_23 0x1e4 /* IRQ */
|
||||
MX53_PAD_CSI0_DAT5__GPIO5_23 0x1c4 /* IRQ */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ codec: sgtl5000@0a {
|
|||
clocks = <&clks 201>;
|
||||
VDDA-supply = <®_2p5v>;
|
||||
VDDIO-supply = <®_3p3v>;
|
||||
lrclk-strength = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ dcfg: dcfg@1ee0000 {
|
|||
};
|
||||
|
||||
esdhc: esdhc@1560000 {
|
||||
compatible = "fsl,esdhc";
|
||||
compatible = "fsl,ls1021a-esdhc", "fsl,esdhc";
|
||||
reg = <0x0 0x1560000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <0>;
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ &i2c2 {
|
|||
tlv320aic3x: tlv320aic3x@18 {
|
||||
compatible = "ti,tlv320aic3x";
|
||||
reg = <0x18>;
|
||||
reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; /* 60 */
|
||||
gpio-reset = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* 60 */
|
||||
ai3x-gpio-func = <
|
||||
0 /* AIC3X_GPIO1_FUNC_DISABLED */
|
||||
5 /* AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT */
|
||||
|
|
@ -505,7 +505,7 @@ tlv320aic3x: tlv320aic3x@18 {
|
|||
tlv320aic3x_aux: tlv320aic3x@19 {
|
||||
compatible = "ti,tlv320aic3x";
|
||||
reg = <0x19>;
|
||||
reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; /* 60 */
|
||||
gpio-reset = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* 60 */
|
||||
|
||||
AVDD-supply = <&vmmc2>;
|
||||
DRVDD-supply = <&vmmc2>;
|
||||
|
|
|
|||
|
|
@ -1354,7 +1354,7 @@ dbgu: serial@fc069000 {
|
|||
pinctrl@fc06a000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
|
||||
compatible = "atmel,sama5d3-pinctrl", "atmel,at91sam9x5-pinctrl", "simple-bus";
|
||||
ranges = <0xfc068000 0xfc068000 0x100
|
||||
0xfc06a000 0xfc06a000 0x4000>;
|
||||
/* WARNING: revisit as pin spec has changed */
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ static inline int xen_irqs_disabled(struct pt_regs *regs)
|
|||
return raw_irqs_disabled_flags(regs->ARM_cpsr);
|
||||
}
|
||||
|
||||
#define xchg_xen_ulong(ptr, val) atomic64_xchg(container_of((ptr), \
|
||||
#define xchg_xen_ulong(ptr, val) atomic64_xchg(container_of((long long*)(ptr),\
|
||||
atomic64_t, \
|
||||
counter), (val))
|
||||
|
||||
|
|
|
|||
|
|
@ -795,6 +795,8 @@ static struct platform_device da8xx_dsp = {
|
|||
.resource = da8xx_rproc_resources,
|
||||
};
|
||||
|
||||
static bool rproc_mem_inited __initdata;
|
||||
|
||||
#if IS_ENABLED(CONFIG_DA8XX_REMOTEPROC)
|
||||
|
||||
static phys_addr_t rproc_base __initdata;
|
||||
|
|
@ -833,6 +835,8 @@ void __init da8xx_rproc_reserve_cma(void)
|
|||
ret = dma_declare_contiguous(&da8xx_dsp.dev, rproc_size, rproc_base, 0);
|
||||
if (ret)
|
||||
pr_err("%s: dma_declare_contiguous failed %d\n", __func__, ret);
|
||||
else
|
||||
rproc_mem_inited = true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -847,6 +851,12 @@ int __init da8xx_register_rproc(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (!rproc_mem_inited) {
|
||||
pr_warn("%s: memory not reserved for DSP, not registering DSP device\n",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = platform_device_register(&da8xx_dsp);
|
||||
if (ret)
|
||||
pr_err("%s: can't register DSP device: %d\n", __func__, ret);
|
||||
|
|
|
|||
|
|
@ -133,6 +133,9 @@ struct device * __init imx_soc_device_init(void)
|
|||
case MXC_CPU_IMX6UL:
|
||||
soc_id = "i.MX6UL";
|
||||
break;
|
||||
case MXC_CPU_IMX6ULL:
|
||||
soc_id = "i.MX6ULL";
|
||||
break;
|
||||
case MXC_CPU_IMX7D:
|
||||
soc_id = "i.MX7D";
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#define MXC_CPU_IMX6SX 0x62
|
||||
#define MXC_CPU_IMX6Q 0x63
|
||||
#define MXC_CPU_IMX6UL 0x64
|
||||
#define MXC_CPU_IMX6ULL 0x65
|
||||
#define MXC_CPU_IMX7D 0x72
|
||||
|
||||
#define IMX_DDR_TYPE_LPDDR2 1
|
||||
|
|
@ -171,6 +172,11 @@ static inline bool cpu_is_imx6ul(void)
|
|||
return __mxc_cpu_type == MXC_CPU_IMX6UL;
|
||||
}
|
||||
|
||||
static inline bool cpu_is_imx6ull(void)
|
||||
{
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6ULL;
|
||||
}
|
||||
|
||||
static inline bool cpu_is_imx6q(void)
|
||||
{
|
||||
return __mxc_cpu_type == MXC_CPU_IMX6Q;
|
||||
|
|
|
|||
|
|
@ -51,16 +51,16 @@
|
|||
: "memory")
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
||||
futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oparg = (int)(encoded_op << 8) >> 20;
|
||||
int cmparg = (int)(encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret, tmp;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
oparg = 1U << (oparg & 0x1f);
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@
|
|||
* TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area.
|
||||
*/
|
||||
#define VA_BITS (CONFIG_ARM64_VA_BITS)
|
||||
#define VA_START (UL(0xffffffffffffffff) << VA_BITS)
|
||||
#define PAGE_OFFSET (UL(0xffffffffffffffff) << (VA_BITS - 1))
|
||||
#define VA_START (UL(0xffffffffffffffff) - \
|
||||
(UL(1) << VA_BITS) + 1)
|
||||
#define PAGE_OFFSET (UL(0xffffffffffffffff) - \
|
||||
(UL(1) << (VA_BITS - 1)) + 1)
|
||||
#define KIMAGE_VADDR (MODULES_END)
|
||||
#define MODULES_END (MODULES_VADDR + MODULES_VSIZE)
|
||||
#define MODULES_VADDR (VA_START + KASAN_SHADOW_SIZE)
|
||||
|
|
|
|||
|
|
@ -16,5 +16,11 @@ static inline cycles_t get_cycles(void)
|
|||
#define vxtime_lock() do {} while (0)
|
||||
#define vxtime_unlock() do {} while (0)
|
||||
|
||||
/* This attribute is used in include/linux/jiffies.h alongside with
|
||||
* __cacheline_aligned_in_smp. It is assumed that __cacheline_aligned_in_smp
|
||||
* for frv does not contain another section specification.
|
||||
*/
|
||||
#define __jiffy_arch_data __attribute__((__section__(".data")))
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ typedef union mips_instruction kprobe_opcode_t;
|
|||
|
||||
#define flush_insn_slot(p) \
|
||||
do { \
|
||||
flush_icache_range((unsigned long)p->addr, \
|
||||
if (p->addr) \
|
||||
flush_icache_range((unsigned long)p->addr, \
|
||||
(unsigned long)p->addr + \
|
||||
(MAX_INSN_SIZE * sizeof(kprobe_opcode_t))); \
|
||||
} while (0)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
#include <asm-generic/pgtable-nopmd.h>
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
#include <asm/highmem.h>
|
||||
#endif
|
||||
|
||||
extern int temp_tlb_entry;
|
||||
|
||||
/*
|
||||
|
|
@ -61,7 +65,8 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
|
|||
|
||||
#define VMALLOC_START MAP_BASE
|
||||
|
||||
#define PKMAP_BASE (0xfe000000UL)
|
||||
#define PKMAP_END ((FIXADDR_START) & ~((LAST_PKMAP << PAGE_SHIFT)-1))
|
||||
#define PKMAP_BASE (PKMAP_END - PAGE_SIZE * LAST_PKMAP)
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
|
||||
|
|
|
|||
|
|
@ -1238,6 +1238,13 @@ __clear_user(void __user *addr, __kernel_size_t size)
|
|||
{
|
||||
__kernel_size_t res;
|
||||
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
/* micromips memset / bzero also clobbers t7 & t8 */
|
||||
#define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$15", "$24", "$31"
|
||||
#else
|
||||
#define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$31"
|
||||
#endif /* CONFIG_CPU_MICROMIPS */
|
||||
|
||||
if (eva_kernel_access()) {
|
||||
__asm__ __volatile__(
|
||||
"move\t$4, %1\n\t"
|
||||
|
|
@ -1247,7 +1254,7 @@ __clear_user(void __user *addr, __kernel_size_t size)
|
|||
"move\t%0, $6"
|
||||
: "=r" (res)
|
||||
: "r" (addr), "r" (size)
|
||||
: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
|
||||
: bzero_clobbers);
|
||||
} else {
|
||||
might_fault();
|
||||
__asm__ __volatile__(
|
||||
|
|
@ -1258,7 +1265,7 @@ __clear_user(void __user *addr, __kernel_size_t size)
|
|||
"move\t%0, $6"
|
||||
: "=r" (res)
|
||||
: "r" (addr), "r" (size)
|
||||
: "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
|
||||
: bzero_clobbers);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@
|
|||
1: PTR_ADDIU a0, 1 /* fill bytewise */
|
||||
R10KCBARRIER(0(ra))
|
||||
bne t1, a0, 1b
|
||||
sb a1, -1(a0)
|
||||
EX(sb, a1, -1(a0), .Lsmall_fixup\@)
|
||||
|
||||
2: jr ra /* done */
|
||||
move a2, zero
|
||||
|
|
@ -249,13 +249,18 @@
|
|||
PTR_L t0, TI_TASK($28)
|
||||
andi a2, STORMASK
|
||||
LONG_L t0, THREAD_BUADDR(t0)
|
||||
LONG_ADDU a2, t1
|
||||
LONG_ADDU a2, a0
|
||||
jr ra
|
||||
LONG_SUBU a2, t0
|
||||
|
||||
.Llast_fixup\@:
|
||||
jr ra
|
||||
andi v1, a2, STORMASK
|
||||
nop
|
||||
|
||||
.Lsmall_fixup\@:
|
||||
PTR_SUBU a2, t1, a0
|
||||
jr ra
|
||||
PTR_ADDIU a2, 1
|
||||
|
||||
.endm
|
||||
|
||||
|
|
|
|||
|
|
@ -51,15 +51,15 @@ void __init pagetable_init(void)
|
|||
/*
|
||||
* Fixed mappings:
|
||||
*/
|
||||
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
|
||||
fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
|
||||
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
|
||||
fixrange_init(vaddr & PMD_MASK, vaddr + FIXADDR_SIZE, pgd_base);
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
/*
|
||||
* Permanent kmaps:
|
||||
*/
|
||||
vaddr = PKMAP_BASE;
|
||||
fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
|
||||
fixrange_init(vaddr & PMD_MASK, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
|
||||
|
||||
pgd = swapper_pg_dir + __pgd_offset(vaddr);
|
||||
pud = pud_offset(pgd, vaddr);
|
||||
|
|
|
|||
|
|
@ -648,6 +648,10 @@ static int match_pci_device(struct device *dev, int index,
|
|||
(modpath->mod == PCI_FUNC(devfn)));
|
||||
}
|
||||
|
||||
/* index might be out of bounds for bc[] */
|
||||
if (index >= 6)
|
||||
return 0;
|
||||
|
||||
id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5);
|
||||
return (modpath->bc[index] == id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@
|
|||
|
||||
#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); mb(); } while (0)
|
||||
|
||||
#ifdef __SUBARCH_HAS_LWSYNC
|
||||
/* The sub-arch has lwsync */
|
||||
#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
|
||||
# define SMPWMB LWSYNC
|
||||
#else
|
||||
# define SMPWMB eieio
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
/* We calculate number of sg entries based on PAGE_SIZE */
|
||||
#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
|
||||
|
||||
/* Default time to sleep or delay between OPAL_BUSY/OPAL_BUSY_EVENT loops */
|
||||
#define OPAL_BUSY_DELAY_MS 10
|
||||
|
||||
/* /sys/firmware/opal */
|
||||
extern struct kobject *opal_kobj;
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,19 @@ extern long long virt_phys_offset;
|
|||
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
|
||||
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
|
||||
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
/*
|
||||
* On hash the vmalloc and other regions alias to the kernel region when passed
|
||||
* through __pa(), which virt_to_pfn() uses. That means virt_addr_valid() can
|
||||
* return true for some vmalloc addresses, which is incorrect. So explicitly
|
||||
* check that the address is in the kernel region.
|
||||
*/
|
||||
#define virt_addr_valid(kaddr) (REGION_ID(kaddr) == KERNEL_REGION_ID && \
|
||||
pfn_valid(virt_to_pfn(kaddr)))
|
||||
#else
|
||||
#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On Book-E parts we need __va to parse the device tree and we can't
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@
|
|||
#include <linux/stringify.h>
|
||||
#include <asm/feature-fixups.h>
|
||||
|
||||
#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
|
||||
#define __SUBARCH_HAS_LWSYNC
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
|
||||
extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
|
||||
|
|
|
|||
|
|
@ -788,7 +788,8 @@ static void eeh_restore_bridge_bars(struct eeh_dev *edev)
|
|||
eeh_ops->write_config(pdn, 15*4, 4, edev->config_space[15]);
|
||||
|
||||
/* PCI Command: 0x4 */
|
||||
eeh_ops->write_config(pdn, PCI_COMMAND, 4, edev->config_space[1]);
|
||||
eeh_ops->write_config(pdn, PCI_COMMAND, 4, edev->config_space[1] |
|
||||
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
|
||||
|
||||
/* Check the PCIe link is ready */
|
||||
eeh_bridge_check_link(edev);
|
||||
|
|
|
|||
|
|
@ -686,12 +686,20 @@ static int __init get_freq(char *name, int cells, unsigned long *val)
|
|||
static void start_cpu_decrementer(void)
|
||||
{
|
||||
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
|
||||
unsigned int tcr;
|
||||
|
||||
/* Clear any pending timer interrupts */
|
||||
mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
|
||||
|
||||
/* Enable decrementer interrupt */
|
||||
mtspr(SPRN_TCR, TCR_DIE);
|
||||
#endif /* defined(CONFIG_BOOKE) || defined(CONFIG_40x) */
|
||||
tcr = mfspr(SPRN_TCR);
|
||||
/*
|
||||
* The watchdog may have already been enabled by u-boot. So leave
|
||||
* TRC[WP] (Watchdog Period) alone.
|
||||
*/
|
||||
tcr &= TCR_WP_MASK; /* Clear all bits except for TCR[WP] */
|
||||
tcr |= TCR_DIE; /* Enable decrementer */
|
||||
mtspr(SPRN_TCR, tcr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init generic_calibrate_decr(void)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
|
|||
pteg_addr = get_pteg_addr(vcpu, pte_index);
|
||||
|
||||
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
|
||||
copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
|
||||
ret = H_FUNCTION;
|
||||
if (copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)))
|
||||
goto done;
|
||||
hpte = pteg;
|
||||
|
||||
ret = H_PTEG_FULL;
|
||||
|
|
@ -71,7 +73,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
|
|||
hpte[0] = cpu_to_be64(kvmppc_get_gpr(vcpu, 6));
|
||||
hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7));
|
||||
pteg_addr += i * HPTE_SIZE;
|
||||
copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE);
|
||||
ret = H_FUNCTION;
|
||||
if (copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE))
|
||||
goto done;
|
||||
kvmppc_set_gpr(vcpu, 4, pte_index | i);
|
||||
ret = H_SUCCESS;
|
||||
|
||||
|
|
@ -93,7 +97,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
|
|||
|
||||
pteg = get_pteg_addr(vcpu, pte_index);
|
||||
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
|
||||
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
|
||||
ret = H_FUNCTION;
|
||||
if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
|
||||
goto done;
|
||||
pte[0] = be64_to_cpu((__force __be64)pte[0]);
|
||||
pte[1] = be64_to_cpu((__force __be64)pte[1]);
|
||||
|
||||
|
|
@ -103,7 +109,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
|
|||
((flags & H_ANDCOND) && (pte[0] & avpn) != 0))
|
||||
goto done;
|
||||
|
||||
copy_to_user((void __user *)pteg, &v, sizeof(v));
|
||||
ret = H_FUNCTION;
|
||||
if (copy_to_user((void __user *)pteg, &v, sizeof(v)))
|
||||
goto done;
|
||||
|
||||
rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
|
||||
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
|
||||
|
|
@ -171,7 +179,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
|
||||
pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
|
||||
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
|
||||
if (copy_from_user(pte, (void __user *)pteg, sizeof(pte))) {
|
||||
ret = H_FUNCTION;
|
||||
break;
|
||||
}
|
||||
pte[0] = be64_to_cpu((__force __be64)pte[0]);
|
||||
pte[1] = be64_to_cpu((__force __be64)pte[1]);
|
||||
|
||||
|
|
@ -184,7 +195,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
|
|||
tsh |= H_BULK_REMOVE_NOT_FOUND;
|
||||
} else {
|
||||
/* Splat the pteg in (userland) hpt */
|
||||
copy_to_user((void __user *)pteg, &v, sizeof(v));
|
||||
if (copy_to_user((void __user *)pteg, &v, sizeof(v))) {
|
||||
ret = H_FUNCTION;
|
||||
break;
|
||||
}
|
||||
|
||||
rb = compute_tlbie_rb(pte[0], pte[1],
|
||||
tsh & H_BULK_REMOVE_PTEX);
|
||||
|
|
@ -211,7 +225,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
|
|||
|
||||
pteg = get_pteg_addr(vcpu, pte_index);
|
||||
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
|
||||
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
|
||||
ret = H_FUNCTION;
|
||||
if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
|
||||
goto done;
|
||||
pte[0] = be64_to_cpu((__force __be64)pte[0]);
|
||||
pte[1] = be64_to_cpu((__force __be64)pte[1]);
|
||||
|
||||
|
|
@ -234,7 +250,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
|
|||
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
|
||||
pte[0] = (__force u64)cpu_to_be64(pte[0]);
|
||||
pte[1] = (__force u64)cpu_to_be64(pte[1]);
|
||||
copy_to_user((void __user *)pteg, pte, sizeof(pte));
|
||||
ret = H_FUNCTION;
|
||||
if (copy_to_user((void __user *)pteg, pte, sizeof(pte)))
|
||||
goto done;
|
||||
ret = H_SUCCESS;
|
||||
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
|
|||
unsigned int *target = (unsigned int *)branch_target(src);
|
||||
|
||||
/* Branch within the section doesn't need translating */
|
||||
if (target < alt_start || target >= alt_end) {
|
||||
if (target < alt_start || target > alt_end) {
|
||||
instr = translate_branch(dest, src);
|
||||
if (!instr)
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -174,6 +174,8 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
|
|||
if (!dump_skip(cprm,
|
||||
roundup(cprm->written - total + sz, 4) - cprm->written))
|
||||
goto Eio;
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
free_page((unsigned long)buf);
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#define DEBUG
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
|
|
@ -56,9 +57,17 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
|
|||
|
||||
while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
|
||||
rc = opal_write_nvram(__pa(buf), count, off);
|
||||
if (rc == OPAL_BUSY_EVENT)
|
||||
if (rc == OPAL_BUSY_EVENT) {
|
||||
msleep(OPAL_BUSY_DELAY_MS);
|
||||
opal_poll_events(NULL);
|
||||
} else if (rc == OPAL_BUSY) {
|
||||
msleep(OPAL_BUSY_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc)
|
||||
return -EIO;
|
||||
|
||||
*index += count;
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ config S390
|
|||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_CPU_AUTOPROBE
|
||||
select GENERIC_CPU_DEVICES if !SMP
|
||||
select GENERIC_CPU_VULNERABILITIES
|
||||
select GENERIC_FIND_FIRST_BIT
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
|
|
@ -709,6 +710,51 @@ config SECCOMP
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config KERNEL_NOBP
|
||||
def_bool n
|
||||
prompt "Enable modified branch prediction for the kernel by default"
|
||||
help
|
||||
If this option is selected the kernel will switch to a modified
|
||||
branch prediction mode if the firmware interface is available.
|
||||
The modified branch prediction mode improves the behaviour in
|
||||
regard to speculative execution.
|
||||
|
||||
With the option enabled the kernel parameter "nobp=0" or "nospec"
|
||||
can be used to run the kernel in the normal branch prediction mode.
|
||||
|
||||
With the option disabled the modified branch prediction mode is
|
||||
enabled with the "nobp=1" kernel parameter.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config EXPOLINE
|
||||
def_bool n
|
||||
prompt "Avoid speculative indirect branches in the kernel"
|
||||
help
|
||||
Compile the kernel with the expoline compiler options to guard
|
||||
against kernel-to-user data leaks by avoiding speculative indirect
|
||||
branches.
|
||||
Requires a compiler with -mindirect-branch=thunk support for full
|
||||
protection. The kernel may run slower.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
choice
|
||||
prompt "Expoline default"
|
||||
depends on EXPOLINE
|
||||
default EXPOLINE_FULL
|
||||
|
||||
config EXPOLINE_OFF
|
||||
bool "spectre_v2=off"
|
||||
|
||||
config EXPOLINE_AUTO
|
||||
bool "spectre_v2=auto"
|
||||
|
||||
config EXPOLINE_FULL
|
||||
bool "spectre_v2=on"
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Power Management"
|
||||
|
|
@ -758,6 +804,7 @@ config PFAULT
|
|||
config SHARED_KERNEL
|
||||
bool "VM shared kernel support"
|
||||
depends on !JUMP_LABEL
|
||||
depends on !ALTERNATIVES
|
||||
help
|
||||
Select this option, if you want to share the text segment of the
|
||||
Linux kernel between different VM guests. This reduces memory
|
||||
|
|
|
|||
|
|
@ -77,6 +77,16 @@ ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
|
|||
cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EXPOLINE
|
||||
ifeq ($(call cc-option-yn,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),y)
|
||||
CC_FLAGS_EXPOLINE := -mindirect-branch=thunk
|
||||
CC_FLAGS_EXPOLINE += -mfunction-return=thunk
|
||||
CC_FLAGS_EXPOLINE += -mindirect-branch-table
|
||||
export CC_FLAGS_EXPOLINE
|
||||
cflags-y += $(CC_FLAGS_EXPOLINE) -DCC_USING_EXPOLINE
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
# make use of hotpatch feature if the compiler supports it
|
||||
cc_hotpatch := -mhotpatch=0,3
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ static void hypfs_kill_super(struct super_block *sb)
|
|||
|
||||
if (sb->s_root)
|
||||
hypfs_delete_tree(sb->s_root);
|
||||
if (sb_info->update_file)
|
||||
if (sb_info && sb_info->update_file)
|
||||
hypfs_remove(sb_info->update_file);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
|
|
|
|||
149
arch/s390/include/asm/alternative.h
Normal file
149
arch/s390/include/asm/alternative.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#ifndef _ASM_S390_ALTERNATIVE_H
|
||||
#define _ASM_S390_ALTERNATIVE_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/stringify.h>
|
||||
|
||||
struct alt_instr {
|
||||
s32 instr_offset; /* original instruction */
|
||||
s32 repl_offset; /* offset to replacement instruction */
|
||||
u16 facility; /* facility bit set for replacement */
|
||||
u8 instrlen; /* length of original instruction */
|
||||
u8 replacementlen; /* length of new instruction */
|
||||
} __packed;
|
||||
|
||||
void apply_alternative_instructions(void);
|
||||
void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
|
||||
/*
|
||||
* |661: |662: |6620 |663:
|
||||
* +-----------+---------------------+
|
||||
* | oldinstr | oldinstr_padding |
|
||||
* | +----------+----------+
|
||||
* | | | |
|
||||
* | | >6 bytes |6/4/2 nops|
|
||||
* | |6 bytes jg----------->
|
||||
* +-----------+---------------------+
|
||||
* ^^ static padding ^^
|
||||
*
|
||||
* .altinstr_replacement section
|
||||
* +---------------------+-----------+
|
||||
* |6641: |6651:
|
||||
* | alternative instr 1 |
|
||||
* +-----------+---------+- - - - - -+
|
||||
* |6642: |6652: |
|
||||
* | alternative instr 2 | padding
|
||||
* +---------------------+- - - - - -+
|
||||
* ^ runtime ^
|
||||
*
|
||||
* .altinstructions section
|
||||
* +---------------------------------+
|
||||
* | alt_instr entries for each |
|
||||
* | alternative instr |
|
||||
* +---------------------------------+
|
||||
*/
|
||||
|
||||
#define b_altinstr(num) "664"#num
|
||||
#define e_altinstr(num) "665"#num
|
||||
|
||||
#define e_oldinstr_pad_end "663"
|
||||
#define oldinstr_len "662b-661b"
|
||||
#define oldinstr_total_len e_oldinstr_pad_end"b-661b"
|
||||
#define altinstr_len(num) e_altinstr(num)"b-"b_altinstr(num)"b"
|
||||
#define oldinstr_pad_len(num) \
|
||||
"-(((" altinstr_len(num) ")-(" oldinstr_len ")) > 0) * " \
|
||||
"((" altinstr_len(num) ")-(" oldinstr_len "))"
|
||||
|
||||
#define INSTR_LEN_SANITY_CHECK(len) \
|
||||
".if " len " > 254\n" \
|
||||
"\t.error \"cpu alternatives does not support instructions " \
|
||||
"blocks > 254 bytes\"\n" \
|
||||
".endif\n" \
|
||||
".if (" len ") %% 2\n" \
|
||||
"\t.error \"cpu alternatives instructions length is odd\"\n" \
|
||||
".endif\n"
|
||||
|
||||
#define OLDINSTR_PADDING(oldinstr, num) \
|
||||
".if " oldinstr_pad_len(num) " > 6\n" \
|
||||
"\tjg " e_oldinstr_pad_end "f\n" \
|
||||
"6620:\n" \
|
||||
"\t.fill (" oldinstr_pad_len(num) " - (6620b-662b)) / 2, 2, 0x0700\n" \
|
||||
".else\n" \
|
||||
"\t.fill " oldinstr_pad_len(num) " / 6, 6, 0xc0040000\n" \
|
||||
"\t.fill " oldinstr_pad_len(num) " %% 6 / 4, 4, 0x47000000\n" \
|
||||
"\t.fill " oldinstr_pad_len(num) " %% 6 %% 4 / 2, 2, 0x0700\n" \
|
||||
".endif\n"
|
||||
|
||||
#define OLDINSTR(oldinstr, num) \
|
||||
"661:\n\t" oldinstr "\n662:\n" \
|
||||
OLDINSTR_PADDING(oldinstr, num) \
|
||||
e_oldinstr_pad_end ":\n" \
|
||||
INSTR_LEN_SANITY_CHECK(oldinstr_len)
|
||||
|
||||
#define OLDINSTR_2(oldinstr, num1, num2) \
|
||||
"661:\n\t" oldinstr "\n662:\n" \
|
||||
".if " altinstr_len(num1) " < " altinstr_len(num2) "\n" \
|
||||
OLDINSTR_PADDING(oldinstr, num2) \
|
||||
".else\n" \
|
||||
OLDINSTR_PADDING(oldinstr, num1) \
|
||||
".endif\n" \
|
||||
e_oldinstr_pad_end ":\n" \
|
||||
INSTR_LEN_SANITY_CHECK(oldinstr_len)
|
||||
|
||||
#define ALTINSTR_ENTRY(facility, num) \
|
||||
"\t.long 661b - .\n" /* old instruction */ \
|
||||
"\t.long " b_altinstr(num)"b - .\n" /* alt instruction */ \
|
||||
"\t.word " __stringify(facility) "\n" /* facility bit */ \
|
||||
"\t.byte " oldinstr_total_len "\n" /* source len */ \
|
||||
"\t.byte " altinstr_len(num) "\n" /* alt instruction len */
|
||||
|
||||
#define ALTINSTR_REPLACEMENT(altinstr, num) /* replacement */ \
|
||||
b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n" \
|
||||
INSTR_LEN_SANITY_CHECK(altinstr_len(num))
|
||||
|
||||
/* alternative assembly primitive: */
|
||||
#define ALTERNATIVE(oldinstr, altinstr, facility) \
|
||||
".pushsection .altinstr_replacement, \"ax\"\n" \
|
||||
ALTINSTR_REPLACEMENT(altinstr, 1) \
|
||||
".popsection\n" \
|
||||
OLDINSTR(oldinstr, 1) \
|
||||
".pushsection .altinstructions,\"a\"\n" \
|
||||
ALTINSTR_ENTRY(facility, 1) \
|
||||
".popsection\n"
|
||||
|
||||
#define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2)\
|
||||
".pushsection .altinstr_replacement, \"ax\"\n" \
|
||||
ALTINSTR_REPLACEMENT(altinstr1, 1) \
|
||||
ALTINSTR_REPLACEMENT(altinstr2, 2) \
|
||||
".popsection\n" \
|
||||
OLDINSTR_2(oldinstr, 1, 2) \
|
||||
".pushsection .altinstructions,\"a\"\n" \
|
||||
ALTINSTR_ENTRY(facility1, 1) \
|
||||
ALTINSTR_ENTRY(facility2, 2) \
|
||||
".popsection\n"
|
||||
|
||||
/*
|
||||
* Alternative instructions for different CPU types or capabilities.
|
||||
*
|
||||
* This allows to use optimized instructions even on generic binary
|
||||
* kernels.
|
||||
*
|
||||
* oldinstr is padded with jump and nops at compile time if altinstr is
|
||||
* longer. altinstr is padded with jump and nops at run-time during patching.
|
||||
*
|
||||
* For non barrier like inlines please define new variants
|
||||
* without volatile and memory clobber.
|
||||
*/
|
||||
#define alternative(oldinstr, altinstr, facility) \
|
||||
asm volatile(ALTERNATIVE(oldinstr, altinstr, facility) : : : "memory")
|
||||
|
||||
#define alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \
|
||||
asm volatile(ALTERNATIVE_2(oldinstr, altinstr1, facility1, \
|
||||
altinstr2, facility2) ::: "memory")
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_S390_ALTERNATIVE_H */
|
||||
|
|
@ -53,4 +53,28 @@ do { \
|
|||
___p1; \
|
||||
})
|
||||
|
||||
/**
|
||||
* array_index_mask_nospec - generate a mask for array_idx() that is
|
||||
* ~0UL when the bounds check succeeds and 0 otherwise
|
||||
* @index: array element index
|
||||
* @size: number of elements in array
|
||||
*/
|
||||
#define array_index_mask_nospec array_index_mask_nospec
|
||||
static inline unsigned long array_index_mask_nospec(unsigned long index,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long mask;
|
||||
|
||||
if (__builtin_constant_p(size) && size > 0) {
|
||||
asm(" clgr %2,%1\n"
|
||||
" slbgr %0,%0\n"
|
||||
:"=d" (mask) : "d" (size-1), "d" (index) :"cc");
|
||||
return mask;
|
||||
}
|
||||
asm(" clgr %1,%2\n"
|
||||
" slbgr %0,%0\n"
|
||||
:"=d" (mask) : "d" (size), "d" (index) :"cc");
|
||||
return ~mask;
|
||||
}
|
||||
|
||||
#endif /* __ASM_BARRIER_H */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,24 @@
|
|||
|
||||
#define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */
|
||||
|
||||
static inline void __set_facility(unsigned long nr, void *facilities)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char *) facilities;
|
||||
|
||||
if (nr >= MAX_FACILITY_BIT)
|
||||
return;
|
||||
ptr[nr >> 3] |= 0x80 >> (nr & 7);
|
||||
}
|
||||
|
||||
static inline void __clear_facility(unsigned long nr, void *facilities)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char *) facilities;
|
||||
|
||||
if (nr >= MAX_FACILITY_BIT)
|
||||
return;
|
||||
ptr[nr >> 3] &= ~(0x80 >> (nr & 7));
|
||||
}
|
||||
|
||||
static inline int __test_facility(unsigned long nr, void *facilities)
|
||||
{
|
||||
unsigned char *ptr;
|
||||
|
|
|
|||
|
|
@ -136,7 +136,8 @@ struct kvm_s390_sie_block {
|
|||
__u16 ipa; /* 0x0056 */
|
||||
__u32 ipb; /* 0x0058 */
|
||||
__u32 scaoh; /* 0x005c */
|
||||
__u8 reserved60; /* 0x0060 */
|
||||
#define FPF_BPBC 0x20
|
||||
__u8 fpf; /* 0x0060 */
|
||||
__u8 ecb; /* 0x0061 */
|
||||
__u8 ecb2; /* 0x0062 */
|
||||
#define ECB3_AES 0x04
|
||||
|
|
|
|||
|
|
@ -155,7 +155,9 @@ struct _lowcore {
|
|||
/* Per cpu primary space access list */
|
||||
__u32 paste[16]; /* 0x0400 */
|
||||
|
||||
__u8 pad_0x04c0[0x0e00-0x0440]; /* 0x0440 */
|
||||
/* br %r1 trampoline */
|
||||
__u16 br_r1_trampoline; /* 0x0440 */
|
||||
__u8 pad_0x0442[0x0e00-0x0442]; /* 0x0442 */
|
||||
|
||||
/*
|
||||
* 0xe00 contains the address of the IPL Parameter Information
|
||||
|
|
@ -170,7 +172,8 @@ struct _lowcore {
|
|||
__u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */
|
||||
|
||||
/* Extended facility list */
|
||||
__u64 stfle_fac_list[32]; /* 0x0f00 */
|
||||
__u64 stfle_fac_list[16]; /* 0x0f00 */
|
||||
__u64 alt_stfle_fac_list[16]; /* 0x0f80 */
|
||||
__u8 pad_0x1000[0x11b0-0x1000]; /* 0x1000 */
|
||||
|
||||
/* Pointer to vector register save area */
|
||||
|
|
|
|||
17
arch/s390/include/asm/nospec-branch.h
Normal file
17
arch/s390/include/asm/nospec-branch.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_S390_EXPOLINE_H
|
||||
#define _ASM_S390_EXPOLINE_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
extern int nospec_disable;
|
||||
|
||||
void nospec_init_branches(void);
|
||||
void nospec_auto_detect(void);
|
||||
void nospec_revert(s32 *start, s32 *end);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_S390_EXPOLINE_H */
|
||||
|
|
@ -69,6 +69,7 @@ extern void s390_adjust_jiffies(void);
|
|||
extern const struct seq_operations cpuinfo_op;
|
||||
extern int sysctl_ieee_emulation_warnings;
|
||||
extern void execve_tail(void);
|
||||
extern void __bpon(void);
|
||||
|
||||
/*
|
||||
* User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
|
||||
|
|
@ -315,6 +316,9 @@ extern void memcpy_absolute(void *, void *, size_t);
|
|||
memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \
|
||||
}
|
||||
|
||||
extern int s390_isolate_bp(void);
|
||||
extern int s390_isolate_bp_guest(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_S390_PROCESSOR_H */
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ void arch_release_task_struct(struct task_struct *tsk);
|
|||
#define TIF_SECCOMP 5 /* secure computing */
|
||||
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
|
||||
#define TIF_UPROBE 7 /* breakpointed or single-stepping */
|
||||
#define TIF_ISOLATE_BP 8 /* Run process with isolated BP */
|
||||
#define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP */
|
||||
#define TIF_31BIT 16 /* 32bit process */
|
||||
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
|
||||
#define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal() */
|
||||
|
|
@ -93,6 +95,8 @@ void arch_release_task_struct(struct task_struct *tsk);
|
|||
#define _TIF_SECCOMP _BITUL(TIF_SECCOMP)
|
||||
#define _TIF_SYSCALL_TRACEPOINT _BITUL(TIF_SYSCALL_TRACEPOINT)
|
||||
#define _TIF_UPROBE _BITUL(TIF_UPROBE)
|
||||
#define _TIF_ISOLATE_BP _BITUL(TIF_ISOLATE_BP)
|
||||
#define _TIF_ISOLATE_BP_GUEST _BITUL(TIF_ISOLATE_BP_GUEST)
|
||||
#define _TIF_31BIT _BITUL(TIF_31BIT)
|
||||
#define _TIF_SINGLE_STEP _BITUL(TIF_SINGLE_STEP)
|
||||
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ struct kvm_guest_debug_arch {
|
|||
#define KVM_SYNC_ARCH0 (1UL << 4)
|
||||
#define KVM_SYNC_PFAULT (1UL << 5)
|
||||
#define KVM_SYNC_VRS (1UL << 6)
|
||||
#define KVM_SYNC_BPBC (1UL << 10)
|
||||
/* definition of registers in kvm_run */
|
||||
struct kvm_sync_regs {
|
||||
__u64 prefix; /* prefix register */
|
||||
|
|
@ -168,6 +169,8 @@ struct kvm_sync_regs {
|
|||
__u64 vrs[32][2]; /* vector registers */
|
||||
__u8 reserved[512]; /* for future vector expansion */
|
||||
__u32 fpc; /* only valid with vector registers */
|
||||
__u8 bpbc : 1; /* bp mode */
|
||||
__u8 reserved2 : 7;
|
||||
};
|
||||
|
||||
#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
|
||||
|
|
|
|||
|
|
@ -44,10 +44,13 @@ obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
|
|||
obj-y += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
|
||||
obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
|
||||
obj-y += runtime_instr.o cache.o dumpstack.o
|
||||
obj-y += entry.o reipl.o relocate_kernel.o
|
||||
obj-y += entry.o reipl.o relocate_kernel.o alternative.o
|
||||
obj-y += nospec-branch.o
|
||||
|
||||
extra-y += head.o head64.o vmlinux.lds
|
||||
|
||||
CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE)
|
||||
|
||||
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_SCHED_BOOK) += topology.o
|
||||
|
|
|
|||
112
arch/s390/kernel/alternative.c
Normal file
112
arch/s390/kernel/alternative.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#include <linux/module.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/facility.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#define MAX_PATCH_LEN (255 - 1)
|
||||
|
||||
static int __initdata_or_module alt_instr_disabled;
|
||||
|
||||
static int __init disable_alternative_instructions(char *str)
|
||||
{
|
||||
alt_instr_disabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_param("noaltinstr", disable_alternative_instructions);
|
||||
|
||||
struct brcl_insn {
|
||||
u16 opc;
|
||||
s32 disp;
|
||||
} __packed;
|
||||
|
||||
static u16 __initdata_or_module nop16 = 0x0700;
|
||||
static u32 __initdata_or_module nop32 = 0x47000000;
|
||||
static struct brcl_insn __initdata_or_module nop48 = {
|
||||
0xc004, 0
|
||||
};
|
||||
|
||||
static const void *nops[] __initdata_or_module = {
|
||||
&nop16,
|
||||
&nop32,
|
||||
&nop48
|
||||
};
|
||||
|
||||
static void __init_or_module add_jump_padding(void *insns, unsigned int len)
|
||||
{
|
||||
struct brcl_insn brcl = {
|
||||
0xc0f4,
|
||||
len / 2
|
||||
};
|
||||
|
||||
memcpy(insns, &brcl, sizeof(brcl));
|
||||
insns += sizeof(brcl);
|
||||
len -= sizeof(brcl);
|
||||
|
||||
while (len > 0) {
|
||||
memcpy(insns, &nop16, 2);
|
||||
insns += 2;
|
||||
len -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init_or_module add_padding(void *insns, unsigned int len)
|
||||
{
|
||||
if (len > 6)
|
||||
add_jump_padding(insns, len);
|
||||
else if (len >= 2)
|
||||
memcpy(insns, nops[len / 2 - 1], len);
|
||||
}
|
||||
|
||||
static void __init_or_module __apply_alternatives(struct alt_instr *start,
|
||||
struct alt_instr *end)
|
||||
{
|
||||
struct alt_instr *a;
|
||||
u8 *instr, *replacement;
|
||||
u8 insnbuf[MAX_PATCH_LEN];
|
||||
|
||||
/*
|
||||
* The scan order should be from start to end. A later scanned
|
||||
* alternative code can overwrite previously scanned alternative code.
|
||||
*/
|
||||
for (a = start; a < end; a++) {
|
||||
int insnbuf_sz = 0;
|
||||
|
||||
instr = (u8 *)&a->instr_offset + a->instr_offset;
|
||||
replacement = (u8 *)&a->repl_offset + a->repl_offset;
|
||||
|
||||
if (!__test_facility(a->facility,
|
||||
S390_lowcore.alt_stfle_fac_list))
|
||||
continue;
|
||||
|
||||
if (unlikely(a->instrlen % 2 || a->replacementlen % 2)) {
|
||||
WARN_ONCE(1, "cpu alternatives instructions length is "
|
||||
"odd, skipping patching\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(insnbuf, replacement, a->replacementlen);
|
||||
insnbuf_sz = a->replacementlen;
|
||||
|
||||
if (a->instrlen > a->replacementlen) {
|
||||
add_padding(insnbuf + a->replacementlen,
|
||||
a->instrlen - a->replacementlen);
|
||||
insnbuf_sz += a->instrlen - a->replacementlen;
|
||||
}
|
||||
|
||||
s390_kernel_write(instr, insnbuf, insnbuf_sz);
|
||||
}
|
||||
}
|
||||
|
||||
void __init_or_module apply_alternatives(struct alt_instr *start,
|
||||
struct alt_instr *end)
|
||||
{
|
||||
if (!alt_instr_disabled)
|
||||
__apply_alternatives(start, end);
|
||||
}
|
||||
|
||||
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
||||
void __init apply_alternative_instructions(void)
|
||||
{
|
||||
apply_alternatives(__alt_instructions, __alt_instructions_end);
|
||||
}
|
||||
|
|
@ -279,6 +279,11 @@ static noinline __init void setup_facility_list(void)
|
|||
{
|
||||
stfle(S390_lowcore.stfle_fac_list,
|
||||
ARRAY_SIZE(S390_lowcore.stfle_fac_list));
|
||||
memcpy(S390_lowcore.alt_stfle_fac_list,
|
||||
S390_lowcore.stfle_fac_list,
|
||||
sizeof(S390_lowcore.alt_stfle_fac_list));
|
||||
if (!IS_ENABLED(CONFIG_KERNEL_NOBP))
|
||||
__clear_facility(82, S390_lowcore.alt_stfle_fac_list);
|
||||
}
|
||||
|
||||
static __init void detect_diag9c(void)
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ _PIF_WORK = (_PIF_PER_TRAP)
|
|||
j 3f
|
||||
1: LAST_BREAK %r14
|
||||
UPDATE_VTIME %r14,%r15,\timer
|
||||
BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
|
||||
2: lg %r15,__LC_ASYNC_STACK # load async stack
|
||||
3: la %r11,STACK_FRAME_OVERHEAD(%r15)
|
||||
.endm
|
||||
|
|
@ -162,8 +163,137 @@ _PIF_WORK = (_PIF_PER_TRAP)
|
|||
tm off+\addr, \mask
|
||||
.endm
|
||||
|
||||
.macro BPOFF
|
||||
.pushsection .altinstr_replacement, "ax"
|
||||
660: .long 0xb2e8c000
|
||||
.popsection
|
||||
661: .long 0x47000000
|
||||
.pushsection .altinstructions, "a"
|
||||
.long 661b - .
|
||||
.long 660b - .
|
||||
.word 82
|
||||
.byte 4
|
||||
.byte 4
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BPON
|
||||
.pushsection .altinstr_replacement, "ax"
|
||||
662: .long 0xb2e8d000
|
||||
.popsection
|
||||
663: .long 0x47000000
|
||||
.pushsection .altinstructions, "a"
|
||||
.long 663b - .
|
||||
.long 662b - .
|
||||
.word 82
|
||||
.byte 4
|
||||
.byte 4
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BPENTER tif_ptr,tif_mask
|
||||
.pushsection .altinstr_replacement, "ax"
|
||||
662: .word 0xc004, 0x0000, 0x0000 # 6 byte nop
|
||||
.word 0xc004, 0x0000, 0x0000 # 6 byte nop
|
||||
.popsection
|
||||
664: TSTMSK \tif_ptr,\tif_mask
|
||||
jz . + 8
|
||||
.long 0xb2e8d000
|
||||
.pushsection .altinstructions, "a"
|
||||
.long 664b - .
|
||||
.long 662b - .
|
||||
.word 82
|
||||
.byte 12
|
||||
.byte 12
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BPEXIT tif_ptr,tif_mask
|
||||
TSTMSK \tif_ptr,\tif_mask
|
||||
.pushsection .altinstr_replacement, "ax"
|
||||
662: jnz . + 8
|
||||
.long 0xb2e8d000
|
||||
.popsection
|
||||
664: jz . + 8
|
||||
.long 0xb2e8c000
|
||||
.pushsection .altinstructions, "a"
|
||||
.long 664b - .
|
||||
.long 662b - .
|
||||
.word 82
|
||||
.byte 8
|
||||
.byte 8
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_EXPOLINE
|
||||
|
||||
.macro GEN_BR_THUNK name,reg,tmp
|
||||
.section .text.\name,"axG",@progbits,\name,comdat
|
||||
.globl \name
|
||||
.hidden \name
|
||||
.type \name,@function
|
||||
\name:
|
||||
.cfi_startproc
|
||||
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
|
||||
exrl 0,0f
|
||||
#else
|
||||
larl \tmp,0f
|
||||
ex 0,0(\tmp)
|
||||
#endif
|
||||
j .
|
||||
0: br \reg
|
||||
.cfi_endproc
|
||||
.endm
|
||||
|
||||
GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1
|
||||
GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1
|
||||
GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11
|
||||
|
||||
.macro BASR_R14_R9
|
||||
0: brasl %r14,__s390x_indirect_jump_r1use_r9
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 0b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BR_R1USE_R14
|
||||
0: jg __s390x_indirect_jump_r1use_r14
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 0b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
.macro BR_R11USE_R14
|
||||
0: jg __s390x_indirect_jump_r11use_r14
|
||||
.pushsection .s390_indirect_branches,"a",@progbits
|
||||
.long 0b-.
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
#else /* CONFIG_EXPOLINE */
|
||||
|
||||
.macro BASR_R14_R9
|
||||
basr %r14,%r9
|
||||
.endm
|
||||
|
||||
.macro BR_R1USE_R14
|
||||
br %r14
|
||||
.endm
|
||||
|
||||
.macro BR_R11USE_R14
|
||||
br %r14
|
||||
.endm
|
||||
|
||||
#endif /* CONFIG_EXPOLINE */
|
||||
|
||||
|
||||
.section .kprobes.text, "ax"
|
||||
|
||||
ENTRY(__bpon)
|
||||
.globl __bpon
|
||||
BPON
|
||||
BR_R1USE_R14
|
||||
|
||||
/*
|
||||
* Scheduler resume function, called by switch_to
|
||||
* gpr2 = (task_struct *) prev
|
||||
|
|
@ -190,9 +320,9 @@ ENTRY(__switch_to)
|
|||
mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
|
||||
lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
||||
bzr %r14
|
||||
jz 0f
|
||||
.insn s,0xb2800000,__LC_LPP # set program parameter
|
||||
br %r14
|
||||
0: BR_R1USE_R14
|
||||
|
||||
.L__critical_start:
|
||||
|
||||
|
|
@ -204,9 +334,11 @@ ENTRY(__switch_to)
|
|||
*/
|
||||
ENTRY(sie64a)
|
||||
stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
|
||||
lg %r12,__LC_CURRENT
|
||||
stg %r2,__SF_EMPTY(%r15) # save control block pointer
|
||||
stg %r3,__SF_EMPTY+8(%r15) # save guest register save area
|
||||
xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # reason code = 0
|
||||
mvc __SF_EMPTY+24(8,%r15),__TI_flags(%r12) # copy thread flags
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU # load guest fp/vx registers ?
|
||||
jno .Lsie_load_guest_gprs
|
||||
brasl %r14,load_fpu_regs # load guest fp/vx regs
|
||||
|
|
@ -223,7 +355,11 @@ ENTRY(sie64a)
|
|||
jnz .Lsie_skip
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
jo .Lsie_skip # exit if fp/vx regs changed
|
||||
BPEXIT __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
|
||||
sie 0(%r14)
|
||||
.Lsie_exit:
|
||||
BPOFF
|
||||
BPENTER __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
|
||||
.Lsie_skip:
|
||||
ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
|
||||
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
||||
|
|
@ -244,9 +380,15 @@ ENTRY(sie64a)
|
|||
sie_exit:
|
||||
lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
|
||||
stmg %r0,%r13,0(%r14) # save guest gprs 0-13
|
||||
xgr %r0,%r0 # clear guest registers to
|
||||
xgr %r1,%r1 # prevent speculative use
|
||||
xgr %r2,%r2
|
||||
xgr %r3,%r3
|
||||
xgr %r4,%r4
|
||||
xgr %r5,%r5
|
||||
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
|
||||
lg %r2,__SF_EMPTY+16(%r15) # return exit reason code
|
||||
br %r14
|
||||
BR_R1USE_R14
|
||||
.Lsie_fault:
|
||||
lghi %r14,-EFAULT
|
||||
stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
|
||||
|
|
@ -267,6 +409,7 @@ ENTRY(system_call)
|
|||
stpt __LC_SYNC_ENTER_TIMER
|
||||
.Lsysc_stmg:
|
||||
stmg %r8,%r15,__LC_SAVE_AREA_SYNC
|
||||
BPOFF
|
||||
lg %r10,__LC_LAST_BREAK
|
||||
lg %r12,__LC_THREAD_INFO
|
||||
lghi %r14,_PIF_SYSCALL
|
||||
|
|
@ -276,12 +419,15 @@ ENTRY(system_call)
|
|||
LAST_BREAK %r13
|
||||
.Lsysc_vtime:
|
||||
UPDATE_VTIME %r10,%r13,__LC_SYNC_ENTER_TIMER
|
||||
BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
|
||||
stmg %r0,%r7,__PT_R0(%r11)
|
||||
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
|
||||
mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW
|
||||
mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
|
||||
stg %r14,__PT_FLAGS(%r11)
|
||||
.Lsysc_do_svc:
|
||||
# clear user controlled register to prevent speculative use
|
||||
xgr %r0,%r0
|
||||
lg %r10,__TI_sysc_table(%r12) # address of system call table
|
||||
llgh %r8,__PT_INT_CODE+2(%r11)
|
||||
slag %r8,%r8,2 # shift and test for svc 0
|
||||
|
|
@ -299,7 +445,7 @@ ENTRY(system_call)
|
|||
lgf %r9,0(%r8,%r10) # get system call add.
|
||||
TSTMSK __TI_flags(%r12),_TIF_TRACE
|
||||
jnz .Lsysc_tracesys
|
||||
basr %r14,%r9 # call sys_xxxx
|
||||
BASR_R14_R9 # call sys_xxxx
|
||||
stg %r2,__PT_R2(%r11) # store return value
|
||||
|
||||
.Lsysc_return:
|
||||
|
|
@ -311,6 +457,7 @@ ENTRY(system_call)
|
|||
jnz .Lsysc_work # check for work
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_WORK
|
||||
jnz .Lsysc_work
|
||||
BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
|
||||
.Lsysc_restore:
|
||||
lg %r14,__LC_VDSO_PER_CPU
|
||||
lmg %r0,%r10,__PT_R0(%r11)
|
||||
|
|
@ -438,7 +585,7 @@ ENTRY(system_call)
|
|||
lmg %r3,%r7,__PT_R3(%r11)
|
||||
stg %r7,STACK_FRAME_OVERHEAD(%r15)
|
||||
lg %r2,__PT_ORIG_GPR2(%r11)
|
||||
basr %r14,%r9 # call sys_xxx
|
||||
BASR_R14_R9 # call sys_xxx
|
||||
stg %r2,__PT_R2(%r11) # store return value
|
||||
.Lsysc_tracenogo:
|
||||
TSTMSK __TI_flags(%r12),_TIF_TRACE
|
||||
|
|
@ -462,7 +609,7 @@ ENTRY(ret_from_fork)
|
|||
lmg %r9,%r10,__PT_R9(%r11) # load gprs
|
||||
ENTRY(kernel_thread_starter)
|
||||
la %r2,0(%r10)
|
||||
basr %r14,%r9
|
||||
BASR_R14_R9
|
||||
j .Lsysc_tracenogo
|
||||
|
||||
/*
|
||||
|
|
@ -471,6 +618,7 @@ ENTRY(kernel_thread_starter)
|
|||
|
||||
ENTRY(pgm_check_handler)
|
||||
stpt __LC_SYNC_ENTER_TIMER
|
||||
BPOFF
|
||||
stmg %r8,%r15,__LC_SAVE_AREA_SYNC
|
||||
lg %r10,__LC_LAST_BREAK
|
||||
lg %r12,__LC_THREAD_INFO
|
||||
|
|
@ -495,6 +643,7 @@ ENTRY(pgm_check_handler)
|
|||
j 3f
|
||||
2: LAST_BREAK %r14
|
||||
UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
|
||||
BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
|
||||
lg %r15,__LC_KERNEL_STACK
|
||||
lg %r14,__TI_task(%r12)
|
||||
aghi %r14,__TASK_thread # pointer to thread_struct
|
||||
|
|
@ -504,6 +653,15 @@ ENTRY(pgm_check_handler)
|
|||
mvc __THREAD_trap_tdb(256,%r14),0(%r13)
|
||||
3: la %r11,STACK_FRAME_OVERHEAD(%r15)
|
||||
stmg %r0,%r7,__PT_R0(%r11)
|
||||
# clear user controlled registers to prevent speculative use
|
||||
xgr %r0,%r0
|
||||
xgr %r1,%r1
|
||||
xgr %r2,%r2
|
||||
xgr %r3,%r3
|
||||
xgr %r4,%r4
|
||||
xgr %r5,%r5
|
||||
xgr %r6,%r6
|
||||
xgr %r7,%r7
|
||||
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
|
||||
stmg %r8,%r9,__PT_PSW(%r11)
|
||||
mvc __PT_INT_CODE(4,%r11),__LC_PGM_ILC
|
||||
|
|
@ -525,9 +683,9 @@ ENTRY(pgm_check_handler)
|
|||
nill %r10,0x007f
|
||||
sll %r10,2
|
||||
je .Lpgm_return
|
||||
lgf %r1,0(%r10,%r1) # load address of handler routine
|
||||
lgf %r9,0(%r10,%r1) # load address of handler routine
|
||||
lgr %r2,%r11 # pass pointer to pt_regs
|
||||
basr %r14,%r1 # branch to interrupt-handler
|
||||
BASR_R14_R9 # branch to interrupt-handler
|
||||
.Lpgm_return:
|
||||
LOCKDEP_SYS_EXIT
|
||||
tm __PT_PSW+1(%r11),0x01 # returning to user ?
|
||||
|
|
@ -560,6 +718,7 @@ ENTRY(pgm_check_handler)
|
|||
ENTRY(io_int_handler)
|
||||
STCK __LC_INT_CLOCK
|
||||
stpt __LC_ASYNC_ENTER_TIMER
|
||||
BPOFF
|
||||
stmg %r8,%r15,__LC_SAVE_AREA_ASYNC
|
||||
lg %r10,__LC_LAST_BREAK
|
||||
lg %r12,__LC_THREAD_INFO
|
||||
|
|
@ -567,6 +726,16 @@ ENTRY(io_int_handler)
|
|||
lmg %r8,%r9,__LC_IO_OLD_PSW
|
||||
SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
|
||||
stmg %r0,%r7,__PT_R0(%r11)
|
||||
# clear user controlled registers to prevent speculative use
|
||||
xgr %r0,%r0
|
||||
xgr %r1,%r1
|
||||
xgr %r2,%r2
|
||||
xgr %r3,%r3
|
||||
xgr %r4,%r4
|
||||
xgr %r5,%r5
|
||||
xgr %r6,%r6
|
||||
xgr %r7,%r7
|
||||
xgr %r10,%r10
|
||||
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
|
||||
stmg %r8,%r9,__PT_PSW(%r11)
|
||||
mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID
|
||||
|
|
@ -601,9 +770,13 @@ ENTRY(io_int_handler)
|
|||
lg %r14,__LC_VDSO_PER_CPU
|
||||
lmg %r0,%r10,__PT_R0(%r11)
|
||||
mvc __LC_RETURN_PSW(16),__PT_PSW(%r11)
|
||||
tm __PT_PSW+1(%r11),0x01 # returning to user ?
|
||||
jno .Lio_exit_kernel
|
||||
BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
|
||||
.Lio_exit_timer:
|
||||
stpt __LC_EXIT_TIMER
|
||||
mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
|
||||
.Lio_exit_kernel:
|
||||
lmg %r11,%r15,__PT_R11(%r11)
|
||||
lpswe __LC_RETURN_PSW
|
||||
.Lio_done:
|
||||
|
|
@ -735,6 +908,7 @@ ENTRY(io_int_handler)
|
|||
ENTRY(ext_int_handler)
|
||||
STCK __LC_INT_CLOCK
|
||||
stpt __LC_ASYNC_ENTER_TIMER
|
||||
BPOFF
|
||||
stmg %r8,%r15,__LC_SAVE_AREA_ASYNC
|
||||
lg %r10,__LC_LAST_BREAK
|
||||
lg %r12,__LC_THREAD_INFO
|
||||
|
|
@ -742,6 +916,16 @@ ENTRY(ext_int_handler)
|
|||
lmg %r8,%r9,__LC_EXT_OLD_PSW
|
||||
SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
|
||||
stmg %r0,%r7,__PT_R0(%r11)
|
||||
# clear user controlled registers to prevent speculative use
|
||||
xgr %r0,%r0
|
||||
xgr %r1,%r1
|
||||
xgr %r2,%r2
|
||||
xgr %r3,%r3
|
||||
xgr %r4,%r4
|
||||
xgr %r5,%r5
|
||||
xgr %r6,%r6
|
||||
xgr %r7,%r7
|
||||
xgr %r10,%r10
|
||||
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
|
||||
stmg %r8,%r9,__PT_PSW(%r11)
|
||||
lghi %r1,__LC_EXT_PARAMS2
|
||||
|
|
@ -773,11 +957,12 @@ ENTRY(psw_idle)
|
|||
.insn rsy,0xeb0000000017,%r1,5,__SF_EMPTY+16(%r15)
|
||||
.Lpsw_idle_stcctm:
|
||||
#endif
|
||||
BPON
|
||||
STCK __CLOCK_IDLE_ENTER(%r2)
|
||||
stpt __TIMER_IDLE_ENTER(%r2)
|
||||
.Lpsw_idle_lpsw:
|
||||
lpswe __SF_EMPTY(%r15)
|
||||
br %r14
|
||||
BR_R1USE_R14
|
||||
.Lpsw_idle_end:
|
||||
|
||||
/*
|
||||
|
|
@ -791,7 +976,7 @@ ENTRY(save_fpu_regs)
|
|||
lg %r2,__LC_CURRENT
|
||||
aghi %r2,__TASK_thread
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
bor %r14
|
||||
jo .Lsave_fpu_regs_exit
|
||||
stfpc __THREAD_FPU_fpc(%r2)
|
||||
.Lsave_fpu_regs_fpc_end:
|
||||
lg %r3,__THREAD_FPU_regs(%r2)
|
||||
|
|
@ -821,7 +1006,8 @@ ENTRY(save_fpu_regs)
|
|||
std 15,120(%r3)
|
||||
.Lsave_fpu_regs_done:
|
||||
oi __LC_CPU_FLAGS+7,_CIF_FPU
|
||||
br %r14
|
||||
.Lsave_fpu_regs_exit:
|
||||
BR_R1USE_R14
|
||||
.Lsave_fpu_regs_end:
|
||||
|
||||
/*
|
||||
|
|
@ -838,7 +1024,7 @@ load_fpu_regs:
|
|||
lg %r4,__LC_CURRENT
|
||||
aghi %r4,__TASK_thread
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
bnor %r14
|
||||
jno .Lload_fpu_regs_exit
|
||||
lfpc __THREAD_FPU_fpc(%r4)
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
|
||||
lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area
|
||||
|
|
@ -867,7 +1053,8 @@ load_fpu_regs:
|
|||
ld 15,120(%r4)
|
||||
.Lload_fpu_regs_done:
|
||||
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
|
||||
br %r14
|
||||
.Lload_fpu_regs_exit:
|
||||
BR_R1USE_R14
|
||||
.Lload_fpu_regs_end:
|
||||
|
||||
.L__critical_end:
|
||||
|
|
@ -877,6 +1064,7 @@ load_fpu_regs:
|
|||
*/
|
||||
ENTRY(mcck_int_handler)
|
||||
STCK __LC_MCCK_CLOCK
|
||||
BPOFF
|
||||
la %r1,4095 # revalidate r1
|
||||
spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
|
||||
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
|
||||
|
|
@ -908,6 +1096,16 @@ ENTRY(mcck_int_handler)
|
|||
.Lmcck_skip:
|
||||
lghi %r14,__LC_GPREGS_SAVE_AREA+64
|
||||
stmg %r0,%r7,__PT_R0(%r11)
|
||||
# clear user controlled registers to prevent speculative use
|
||||
xgr %r0,%r0
|
||||
xgr %r1,%r1
|
||||
xgr %r2,%r2
|
||||
xgr %r3,%r3
|
||||
xgr %r4,%r4
|
||||
xgr %r5,%r5
|
||||
xgr %r6,%r6
|
||||
xgr %r7,%r7
|
||||
xgr %r10,%r10
|
||||
mvc __PT_R8(64,%r11),0(%r14)
|
||||
stmg %r8,%r9,__PT_PSW(%r11)
|
||||
xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
|
||||
|
|
@ -933,6 +1131,7 @@ ENTRY(mcck_int_handler)
|
|||
mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
|
||||
tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
|
||||
jno 0f
|
||||
BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
|
||||
stpt __LC_EXIT_TIMER
|
||||
mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
|
||||
0: lmg %r11,%r15,__PT_R11(%r11)
|
||||
|
|
@ -1028,7 +1227,7 @@ cleanup_critical:
|
|||
jl 0f
|
||||
clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end
|
||||
jl .Lcleanup_load_fpu_regs
|
||||
0: br %r14
|
||||
0: BR_R11USE_R14
|
||||
|
||||
.align 8
|
||||
.Lcleanup_table:
|
||||
|
|
@ -1053,11 +1252,12 @@ cleanup_critical:
|
|||
.quad .Lsie_done
|
||||
|
||||
.Lcleanup_sie:
|
||||
BPENTER __SF_EMPTY+24(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
|
||||
lg %r9,__SF_EMPTY(%r15) # get control block pointer
|
||||
ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
|
||||
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
||||
larl %r9,sie_exit # skip forward to sie_exit
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
#endif
|
||||
|
||||
.Lcleanup_system_call:
|
||||
|
|
@ -1099,7 +1299,8 @@ cleanup_critical:
|
|||
srag %r9,%r9,23
|
||||
jz 0f
|
||||
mvc __TI_last_break(8,%r12),16(%r11)
|
||||
0: # set up saved register r11
|
||||
0: BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
|
||||
# set up saved register r11
|
||||
lg %r15,__LC_KERNEL_STACK
|
||||
la %r9,STACK_FRAME_OVERHEAD(%r15)
|
||||
stg %r9,24(%r11) # r11 pt_regs pointer
|
||||
|
|
@ -1114,7 +1315,7 @@ cleanup_critical:
|
|||
stg %r15,56(%r11) # r15 stack pointer
|
||||
# set new psw address and exit
|
||||
larl %r9,.Lsysc_do_svc
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
.Lcleanup_system_call_insn:
|
||||
.quad system_call
|
||||
.quad .Lsysc_stmg
|
||||
|
|
@ -1124,7 +1325,7 @@ cleanup_critical:
|
|||
|
||||
.Lcleanup_sysc_tif:
|
||||
larl %r9,.Lsysc_tif
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
|
||||
.Lcleanup_sysc_restore:
|
||||
# check if stpt has been executed
|
||||
|
|
@ -1141,14 +1342,14 @@ cleanup_critical:
|
|||
mvc 0(64,%r11),__PT_R8(%r9)
|
||||
lmg %r0,%r7,__PT_R0(%r9)
|
||||
1: lmg %r8,%r9,__LC_RETURN_PSW
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
.Lcleanup_sysc_restore_insn:
|
||||
.quad .Lsysc_exit_timer
|
||||
.quad .Lsysc_done - 4
|
||||
|
||||
.Lcleanup_io_tif:
|
||||
larl %r9,.Lio_tif
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
|
||||
.Lcleanup_io_restore:
|
||||
# check if stpt has been executed
|
||||
|
|
@ -1162,7 +1363,7 @@ cleanup_critical:
|
|||
mvc 0(64,%r11),__PT_R8(%r9)
|
||||
lmg %r0,%r7,__PT_R0(%r9)
|
||||
1: lmg %r8,%r9,__LC_RETURN_PSW
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
.Lcleanup_io_restore_insn:
|
||||
.quad .Lio_exit_timer
|
||||
.quad .Lio_done - 4
|
||||
|
|
@ -1214,17 +1415,17 @@ cleanup_critical:
|
|||
# prepare return psw
|
||||
nihh %r8,0xfcfd # clear irq & wait state bits
|
||||
lg %r9,48(%r11) # return from psw_idle
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
.Lcleanup_idle_insn:
|
||||
.quad .Lpsw_idle_lpsw
|
||||
|
||||
.Lcleanup_save_fpu_regs:
|
||||
larl %r9,save_fpu_regs
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
|
||||
.Lcleanup_load_fpu_regs:
|
||||
larl %r9,load_fpu_regs
|
||||
br %r14
|
||||
BR_R11USE_R14
|
||||
|
||||
/*
|
||||
* Integer constants
|
||||
|
|
@ -1240,7 +1441,6 @@ cleanup_critical:
|
|||
.Lsie_critical_length:
|
||||
.quad .Lsie_done - .Lsie_gmap
|
||||
#endif
|
||||
|
||||
.section .rodata, "a"
|
||||
#define SYSCALL(esame,emu) .long esame
|
||||
.globl sys_call_table
|
||||
|
|
|
|||
|
|
@ -563,6 +563,7 @@ static struct kset *ipl_kset;
|
|||
|
||||
static void __ipl_run(void *unused)
|
||||
{
|
||||
__bpon();
|
||||
diag308(DIAG308_IPL, NULL);
|
||||
if (MACHINE_IS_VM)
|
||||
__cpcmd("IPL", NULL, 0, NULL);
|
||||
|
|
@ -798,6 +799,7 @@ static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
|
|||
/* copy and convert to ebcdic */
|
||||
memcpy(ipb->hdr.loadparm, buf, lp_len);
|
||||
ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
|
||||
ipb->hdr.flags |= DIAG308_FLAGS_LP_VALID;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/bug.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/facility.h>
|
||||
|
||||
#if 0
|
||||
#define DEBUGP printk
|
||||
|
|
@ -163,7 +166,11 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
|||
me->arch.got_offset = me->core_size;
|
||||
me->core_size += me->arch.got_size;
|
||||
me->arch.plt_offset = me->core_size;
|
||||
me->core_size += me->arch.plt_size;
|
||||
if (me->arch.plt_size) {
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable)
|
||||
me->arch.plt_size += PLT_ENTRY_SIZE;
|
||||
me->core_size += me->arch.plt_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -317,9 +324,20 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
|
|||
unsigned int *ip;
|
||||
ip = me->module_core + me->arch.plt_offset +
|
||||
info->plt_offset;
|
||||
ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */
|
||||
ip[1] = 0x100a0004;
|
||||
ip[2] = 0x07f10000;
|
||||
ip[0] = 0x0d10e310; /* basr 1,0 */
|
||||
ip[1] = 0x100a0004; /* lg 1,10(1) */
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable) {
|
||||
unsigned int *ij;
|
||||
ij = me->module_core +
|
||||
me->arch.plt_offset +
|
||||
me->arch.plt_size - PLT_ENTRY_SIZE;
|
||||
ip[2] = 0xa7f40000 + /* j __jump_r1 */
|
||||
(unsigned int)(u16)
|
||||
(((unsigned long) ij - 8 -
|
||||
(unsigned long) ip) / 2);
|
||||
} else {
|
||||
ip[2] = 0x07f10000; /* br %r1 */
|
||||
}
|
||||
ip[3] = (unsigned int) (val >> 32);
|
||||
ip[4] = (unsigned int) val;
|
||||
info->plt_initialized = 1;
|
||||
|
|
@ -424,6 +442,45 @@ int module_finalize(const Elf_Ehdr *hdr,
|
|||
const Elf_Shdr *sechdrs,
|
||||
struct module *me)
|
||||
{
|
||||
const Elf_Shdr *s;
|
||||
char *secstrings, *secname;
|
||||
void *aseg;
|
||||
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE) &&
|
||||
!nospec_disable && me->arch.plt_size) {
|
||||
unsigned int *ij;
|
||||
|
||||
ij = me->module_core + me->arch.plt_offset +
|
||||
me->arch.plt_size - PLT_ENTRY_SIZE;
|
||||
if (test_facility(35)) {
|
||||
ij[0] = 0xc6000000; /* exrl %r0,.+10 */
|
||||
ij[1] = 0x0005a7f4; /* j . */
|
||||
ij[2] = 0x000007f1; /* br %r1 */
|
||||
} else {
|
||||
ij[0] = 0x44000000 | (unsigned int)
|
||||
offsetof(struct _lowcore, br_r1_trampoline);
|
||||
ij[1] = 0xa7f40000; /* j . */
|
||||
}
|
||||
}
|
||||
|
||||
secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
|
||||
for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
|
||||
aseg = (void *) s->sh_addr;
|
||||
secname = secstrings + s->sh_name;
|
||||
|
||||
if (!strcmp(".altinstructions", secname))
|
||||
/* patch .altinstructions */
|
||||
apply_alternatives(aseg, aseg + s->sh_size);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE) &&
|
||||
(!strncmp(".s390_indirect", secname, 14)))
|
||||
nospec_revert(aseg, aseg + s->sh_size);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE) &&
|
||||
(!strncmp(".s390_return", secname, 12)))
|
||||
nospec_revert(aseg, aseg + s->sh_size);
|
||||
}
|
||||
|
||||
jump_label_apply_nops(me);
|
||||
vfree(me->arch.syminfo);
|
||||
me->arch.syminfo = NULL;
|
||||
|
|
|
|||
169
arch/s390/kernel/nospec-branch.c
Normal file
169
arch/s390/kernel/nospec-branch.c
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/facility.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
static int __init nobp_setup_early(char *str)
|
||||
{
|
||||
bool enabled;
|
||||
int rc;
|
||||
|
||||
rc = kstrtobool(str, &enabled);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (enabled && test_facility(82)) {
|
||||
/*
|
||||
* The user explicitely requested nobp=1, enable it and
|
||||
* disable the expoline support.
|
||||
*/
|
||||
__set_facility(82, S390_lowcore.alt_stfle_fac_list);
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE))
|
||||
nospec_disable = 1;
|
||||
} else {
|
||||
__clear_facility(82, S390_lowcore.alt_stfle_fac_list);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
early_param("nobp", nobp_setup_early);
|
||||
|
||||
static int __init nospec_setup_early(char *str)
|
||||
{
|
||||
__clear_facility(82, S390_lowcore.alt_stfle_fac_list);
|
||||
return 0;
|
||||
}
|
||||
early_param("nospec", nospec_setup_early);
|
||||
|
||||
static int __init nospec_report(void)
|
||||
{
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
|
||||
pr_info("Spectre V2 mitigation: execute trampolines.\n");
|
||||
if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
|
||||
pr_info("Spectre V2 mitigation: limited branch prediction.\n");
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(nospec_report);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
ssize_t cpu_show_spectre_v1(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
||||
}
|
||||
|
||||
ssize_t cpu_show_spectre_v2(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
|
||||
return sprintf(buf, "Mitigation: execute trampolines\n");
|
||||
if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
|
||||
return sprintf(buf, "Mitigation: limited branch prediction.\n");
|
||||
return sprintf(buf, "Vulnerable\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXPOLINE
|
||||
|
||||
int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
|
||||
|
||||
static int __init nospectre_v2_setup_early(char *str)
|
||||
{
|
||||
nospec_disable = 1;
|
||||
return 0;
|
||||
}
|
||||
early_param("nospectre_v2", nospectre_v2_setup_early);
|
||||
|
||||
void __init nospec_auto_detect(void)
|
||||
{
|
||||
if (IS_ENABLED(CC_USING_EXPOLINE)) {
|
||||
/*
|
||||
* The kernel has been compiled with expolines.
|
||||
* Keep expolines enabled and disable nobp.
|
||||
*/
|
||||
nospec_disable = 0;
|
||||
__clear_facility(82, S390_lowcore.alt_stfle_fac_list);
|
||||
}
|
||||
/*
|
||||
* If the kernel has not been compiled with expolines the
|
||||
* nobp setting decides what is done, this depends on the
|
||||
* CONFIG_KERNEL_NP option and the nobp/nospec parameters.
|
||||
*/
|
||||
}
|
||||
|
||||
static int __init spectre_v2_setup_early(char *str)
|
||||
{
|
||||
if (str && !strncmp(str, "on", 2)) {
|
||||
nospec_disable = 0;
|
||||
__clear_facility(82, S390_lowcore.alt_stfle_fac_list);
|
||||
}
|
||||
if (str && !strncmp(str, "off", 3))
|
||||
nospec_disable = 1;
|
||||
if (str && !strncmp(str, "auto", 4))
|
||||
nospec_auto_detect();
|
||||
return 0;
|
||||
}
|
||||
early_param("spectre_v2", spectre_v2_setup_early);
|
||||
|
||||
static void __init_or_module __nospec_revert(s32 *start, s32 *end)
|
||||
{
|
||||
enum { BRCL_EXPOLINE, BRASL_EXPOLINE } type;
|
||||
u8 *instr, *thunk, *br;
|
||||
u8 insnbuf[6];
|
||||
s32 *epo;
|
||||
|
||||
/* Second part of the instruction replace is always a nop */
|
||||
memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
|
||||
for (epo = start; epo < end; epo++) {
|
||||
instr = (u8 *) epo + *epo;
|
||||
if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
|
||||
type = BRCL_EXPOLINE; /* brcl instruction */
|
||||
else if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x05)
|
||||
type = BRASL_EXPOLINE; /* brasl instruction */
|
||||
else
|
||||
continue;
|
||||
thunk = instr + (*(int *)(instr + 2)) * 2;
|
||||
if (thunk[0] == 0xc6 && thunk[1] == 0x00)
|
||||
/* exrl %r0,<target-br> */
|
||||
br = thunk + (*(int *)(thunk + 2)) * 2;
|
||||
else if (thunk[0] == 0xc0 && (thunk[1] & 0x0f) == 0x00 &&
|
||||
thunk[6] == 0x44 && thunk[7] == 0x00 &&
|
||||
(thunk[8] & 0x0f) == 0x00 && thunk[9] == 0x00 &&
|
||||
(thunk[1] & 0xf0) == (thunk[8] & 0xf0))
|
||||
/* larl %rx,<target br> + ex %r0,0(%rx) */
|
||||
br = thunk + (*(int *)(thunk + 2)) * 2;
|
||||
else
|
||||
continue;
|
||||
if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
|
||||
continue;
|
||||
switch (type) {
|
||||
case BRCL_EXPOLINE:
|
||||
/* brcl to thunk, replace with br + nop */
|
||||
insnbuf[0] = br[0];
|
||||
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
|
||||
break;
|
||||
case BRASL_EXPOLINE:
|
||||
/* brasl to thunk, replace with basr + nop */
|
||||
insnbuf[0] = 0x0d;
|
||||
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
|
||||
break;
|
||||
}
|
||||
|
||||
s390_kernel_write(instr, insnbuf, 6);
|
||||
}
|
||||
}
|
||||
|
||||
void __init_or_module nospec_revert(s32 *start, s32 *end)
|
||||
{
|
||||
if (nospec_disable)
|
||||
__nospec_revert(start, end);
|
||||
}
|
||||
|
||||
extern s32 __nospec_call_start[], __nospec_call_end[];
|
||||
extern s32 __nospec_return_start[], __nospec_return_end[];
|
||||
void __init nospec_init_branches(void)
|
||||
{
|
||||
nospec_revert(__nospec_call_start, __nospec_call_end);
|
||||
nospec_revert(__nospec_return_start, __nospec_return_end);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_EXPOLINE */
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/cpu.h>
|
||||
#include <asm/diag.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/facility.h>
|
||||
#include <asm/lowcore.h>
|
||||
#include <asm/param.h>
|
||||
#include <asm/smp.h>
|
||||
|
|
@ -113,3 +114,20 @@ const struct seq_operations cpuinfo_op = {
|
|||
.show = show_cpuinfo,
|
||||
};
|
||||
|
||||
int s390_isolate_bp(void)
|
||||
{
|
||||
if (!test_facility(82))
|
||||
return -EOPNOTSUPP;
|
||||
set_thread_flag(TIF_ISOLATE_BP);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(s390_isolate_bp);
|
||||
|
||||
int s390_isolate_bp_guest(void)
|
||||
{
|
||||
if (!test_facility(82))
|
||||
return -EOPNOTSUPP;
|
||||
set_thread_flag(TIF_ISOLATE_BP_GUEST);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(s390_isolate_bp_guest);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@
|
|||
#include <asm/sclp.h>
|
||||
#include <asm/sysinfo.h>
|
||||
#include <asm/numa.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include "entry.h"
|
||||
|
||||
/*
|
||||
|
|
@ -333,7 +335,9 @@ static void __init setup_lowcore(void)
|
|||
lc->machine_flags = S390_lowcore.machine_flags;
|
||||
lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
|
||||
memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
|
||||
MAX_FACILITY_BIT/8);
|
||||
sizeof(lc->stfle_fac_list));
|
||||
memcpy(lc->alt_stfle_fac_list, S390_lowcore.alt_stfle_fac_list,
|
||||
sizeof(lc->alt_stfle_fac_list));
|
||||
if (MACHINE_HAS_VX)
|
||||
lc->vector_save_area_addr =
|
||||
(unsigned long) &lc->vector_save_area;
|
||||
|
|
@ -370,6 +374,7 @@ static void __init setup_lowcore(void)
|
|||
#ifdef CONFIG_SMP
|
||||
lc->spinlock_lockval = arch_spin_lockval(0);
|
||||
#endif
|
||||
lc->br_r1_trampoline = 0x07f1; /* br %r1 */
|
||||
|
||||
set_prefix((u32)(unsigned long) lc);
|
||||
lowcore_ptr[0] = lc;
|
||||
|
|
@ -841,6 +846,9 @@ void __init setup_arch(char **cmdline_p)
|
|||
init_mm.end_data = (unsigned long) &_edata;
|
||||
init_mm.brk = (unsigned long) &_end;
|
||||
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE_AUTO))
|
||||
nospec_auto_detect();
|
||||
|
||||
parse_early_param();
|
||||
os_info_init();
|
||||
setup_ipl();
|
||||
|
|
@ -893,6 +901,10 @@ void __init setup_arch(char **cmdline_p)
|
|||
conmode_default();
|
||||
set_preferred_console();
|
||||
|
||||
apply_alternative_instructions();
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE))
|
||||
nospec_init_branches();
|
||||
|
||||
/* Setup zfcpdump support */
|
||||
setup_zfcpdump();
|
||||
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
|
|||
lc->panic_stack = panic_stack + PANIC_FRAME_OFFSET;
|
||||
lc->cpu_nr = cpu;
|
||||
lc->spinlock_lockval = arch_spin_lockval(cpu);
|
||||
lc->br_r1_trampoline = 0x07f1; /* br %r1 */
|
||||
if (MACHINE_HAS_VX)
|
||||
lc->vector_save_area_addr =
|
||||
(unsigned long) &lc->vector_save_area;
|
||||
|
|
@ -250,7 +251,9 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
|
|||
__ctl_store(lc->cregs_save_area, 0, 15);
|
||||
save_access_regs((unsigned int *) lc->access_regs_save_area);
|
||||
memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
|
||||
MAX_FACILITY_BIT/8);
|
||||
sizeof(lc->stfle_fac_list));
|
||||
memcpy(lc->alt_stfle_fac_list, S390_lowcore.alt_stfle_fac_list,
|
||||
sizeof(lc->alt_stfle_fac_list));
|
||||
}
|
||||
|
||||
static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
|
||||
|
|
@ -299,6 +302,7 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),
|
|||
mem_assign_absolute(lc->restart_fn, (unsigned long) func);
|
||||
mem_assign_absolute(lc->restart_data, (unsigned long) data);
|
||||
mem_assign_absolute(lc->restart_source, source_cpu);
|
||||
__bpon();
|
||||
asm volatile(
|
||||
"0: sigp 0,%0,%2 # sigp restart to target cpu\n"
|
||||
" brc 2,0b # busy, try again\n"
|
||||
|
|
@ -888,6 +892,7 @@ void __cpu_die(unsigned int cpu)
|
|||
void __noreturn cpu_die(void)
|
||||
{
|
||||
idle_task_exit();
|
||||
__bpon();
|
||||
pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0);
|
||||
for (;;) ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,6 +147,15 @@ unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline,
|
|||
return orig;
|
||||
}
|
||||
|
||||
bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (ctx == RP_CHECK_CHAIN_CALL)
|
||||
return user_stack_pointer(regs) <= ret->stack;
|
||||
else
|
||||
return user_stack_pointer(regs) < ret->stack;
|
||||
}
|
||||
|
||||
/* Instruction Emulation */
|
||||
|
||||
static void adjust_psw_addr(psw_t *psw, unsigned long len)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,14 @@ SECTIONS
|
|||
{
|
||||
. = 0x00000000;
|
||||
.text : {
|
||||
_text = .; /* Text and read-only data */
|
||||
/* Text and read-only data */
|
||||
HEAD_TEXT
|
||||
/*
|
||||
* E.g. perf doesn't like symbols starting at address zero,
|
||||
* therefore skip the initial PSW and channel program located
|
||||
* at address zero and let _text start at 0x200.
|
||||
*/
|
||||
_text = 0x200;
|
||||
TEXT_TEXT
|
||||
SCHED_TEXT
|
||||
LOCK_TEXT
|
||||
|
|
@ -72,6 +78,43 @@ SECTIONS
|
|||
EXIT_DATA
|
||||
}
|
||||
|
||||
/*
|
||||
* struct alt_inst entries. From the header (alternative.h):
|
||||
* "Alternative instructions for different CPU types or capabilities"
|
||||
* Think locking instructions on spinlocks.
|
||||
* Note, that it is a part of __init region.
|
||||
*/
|
||||
. = ALIGN(8);
|
||||
.altinstructions : {
|
||||
__alt_instructions = .;
|
||||
*(.altinstructions)
|
||||
__alt_instructions_end = .;
|
||||
}
|
||||
|
||||
/*
|
||||
* And here are the replacement instructions. The linker sticks
|
||||
* them as binary blobs. The .altinstructions has enough data to
|
||||
* get the address and the length of them to patch the kernel safely.
|
||||
* Note, that it is a part of __init region.
|
||||
*/
|
||||
.altinstr_replacement : {
|
||||
*(.altinstr_replacement)
|
||||
}
|
||||
|
||||
/*
|
||||
* Table with the patch locations to undo expolines
|
||||
*/
|
||||
.nospec_call_table : {
|
||||
__nospec_call_start = . ;
|
||||
*(.s390_indirect*)
|
||||
__nospec_call_end = . ;
|
||||
}
|
||||
.nospec_return_table : {
|
||||
__nospec_return_start = . ;
|
||||
*(.s390_return*)
|
||||
__nospec_return_end = . ;
|
||||
}
|
||||
|
||||
/* early.c uses stsi, which requires page aligned data. */
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
INIT_DATA_SECTION(0x100)
|
||||
|
|
|
|||
|
|
@ -118,8 +118,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
|
|||
|
||||
/* upper facilities limit for kvm */
|
||||
unsigned long kvm_s390_fac_list_mask[] = {
|
||||
0xffe6fffbfcfdfc40UL,
|
||||
0x005e800000000000UL,
|
||||
0xffe6ffffffffffffUL,
|
||||
0x005effffffffffffUL,
|
||||
};
|
||||
|
||||
unsigned long kvm_s390_fac_list_mask_size(void)
|
||||
|
|
@ -257,6 +257,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||
case KVM_CAP_S390_VECTOR_REGISTERS:
|
||||
r = MACHINE_HAS_VX;
|
||||
break;
|
||||
case KVM_CAP_S390_BPB:
|
||||
r = test_facility(82);
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
}
|
||||
|
|
@ -1264,6 +1267,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
|
|||
KVM_SYNC_PFAULT;
|
||||
if (test_kvm_facility(vcpu->kvm, 129))
|
||||
vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
|
||||
if (test_kvm_facility(vcpu->kvm, 82))
|
||||
vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC;
|
||||
|
||||
if (kvm_is_ucontrol(vcpu->kvm))
|
||||
return __kvm_ucontrol_vcpu_init(vcpu);
|
||||
|
|
@ -1327,6 +1332,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
|
|||
current->thread.fpu.fpc = 0;
|
||||
vcpu->arch.sie_block->gbea = 1;
|
||||
vcpu->arch.sie_block->pp = 0;
|
||||
vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
|
||||
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
|
||||
kvm_clear_async_pf_completion_queue(vcpu);
|
||||
if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
|
||||
|
|
@ -2145,6 +2151,11 @@ static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
|||
if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
|
||||
kvm_clear_async_pf_completion_queue(vcpu);
|
||||
}
|
||||
if ((kvm_run->kvm_dirty_regs & KVM_SYNC_BPBC) &&
|
||||
test_kvm_facility(vcpu->kvm, 82)) {
|
||||
vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
|
||||
vcpu->arch.sie_block->fpf |= kvm_run->s.regs.bpbc ? FPF_BPBC : 0;
|
||||
}
|
||||
kvm_run->kvm_dirty_regs = 0;
|
||||
}
|
||||
|
||||
|
|
@ -2162,6 +2173,7 @@ static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
|||
kvm_run->s.regs.pft = vcpu->arch.pfault_token;
|
||||
kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
|
||||
kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
|
||||
kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
|
||||
}
|
||||
|
||||
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
|
||||
|
|
|
|||
|
|
@ -1733,9 +1733,14 @@ static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size)
|
|||
|
||||
lp->rcv_nxt = p->seqid;
|
||||
|
||||
/*
|
||||
* If this is a control-only packet, there is nothing
|
||||
* else to do but advance the rx queue since the packet
|
||||
* was already processed above.
|
||||
*/
|
||||
if (!(p->type & LDC_DATA)) {
|
||||
new = rx_advance(lp, new);
|
||||
goto no_data;
|
||||
break;
|
||||
}
|
||||
if (p->stype & (LDC_ACK | LDC_NACK)) {
|
||||
err = data_ack_nack(lp, p);
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
|
|||
|
||||
static void hard_handler(int sig, siginfo_t *si, void *p)
|
||||
{
|
||||
struct ucontext *uc = p;
|
||||
ucontext_t *uc = p;
|
||||
mcontext_t *mc = &uc->uc_mcontext;
|
||||
unsigned long pending = 1UL << sig;
|
||||
|
||||
|
|
|
|||
|
|
@ -282,11 +282,6 @@ config X86_32_LAZY_GS
|
|||
def_bool y
|
||||
depends on X86_32 && !CC_STACKPROTECTOR
|
||||
|
||||
config ARCH_HWEIGHT_CFLAGS
|
||||
string
|
||||
default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
|
||||
default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
|
||||
|
||||
config ARCH_SUPPORTS_UPROBES
|
||||
def_bool y
|
||||
|
||||
|
|
|
|||
|
|
@ -66,8 +66,6 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
|
|||
void (*fn)(struct cast5_ctx *ctx, u8 *dst, const u8 *src);
|
||||
int err;
|
||||
|
||||
fn = (enc) ? cast5_ecb_enc_16way : cast5_ecb_dec_16way;
|
||||
|
||||
err = blkcipher_walk_virt(desc, walk);
|
||||
desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||
|
||||
|
|
@ -79,6 +77,7 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
|
|||
|
||||
/* Process multi-block batch */
|
||||
if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
|
||||
fn = (enc) ? cast5_ecb_enc_16way : cast5_ecb_dec_16way;
|
||||
do {
|
||||
fn(ctx, wdst, wsrc);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#define _ASM_X86_HWEIGHT_H
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/* popcnt %edi, %eax -- redundant REX prefix for alignment */
|
||||
#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
|
||||
/* popcnt %edi, %eax */
|
||||
#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc7"
|
||||
/* popcnt %rdi, %rax */
|
||||
#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
|
||||
#define REG_IN "D"
|
||||
|
|
@ -15,19 +15,15 @@
|
|||
#define REG_OUT "a"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* __sw_hweightXX are called from within the alternatives below
|
||||
* and callee-clobbered registers need to be taken care of. See
|
||||
* ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
|
||||
* compiler switches.
|
||||
*/
|
||||
#define __HAVE_ARCH_SW_HWEIGHT
|
||||
|
||||
static __always_inline unsigned int __arch_hweight32(unsigned int w)
|
||||
{
|
||||
unsigned int res = 0;
|
||||
unsigned int res;
|
||||
|
||||
asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
|
||||
: "="REG_OUT (res)
|
||||
: REG_IN (w));
|
||||
: "="REG_OUT (res)
|
||||
: REG_IN (w));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -51,11 +47,11 @@ static inline unsigned long __arch_hweight64(__u64 w)
|
|||
#else
|
||||
static __always_inline unsigned long __arch_hweight64(__u64 w)
|
||||
{
|
||||
unsigned long res = 0;
|
||||
unsigned long res;
|
||||
|
||||
asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
|
||||
: "="REG_OUT (res)
|
||||
: REG_IN (w));
|
||||
: "="REG_OUT (res)
|
||||
: REG_IN (w));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,32 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef __ASM_X64_MSGBUF_H
|
||||
#define __ASM_X64_MSGBUF_H
|
||||
|
||||
#if !defined(__x86_64__) || !defined(__ILP32__)
|
||||
#include <asm-generic/msgbuf.h>
|
||||
#else
|
||||
/*
|
||||
* The msqid64_ds structure for x86 architecture with x32 ABI.
|
||||
*
|
||||
* On x86-32 and x86-64 we can just use the generic definition, but
|
||||
* x32 uses the same binary layout as x86_64, which is differnet
|
||||
* from other 32-bit architectures.
|
||||
*/
|
||||
|
||||
struct msqid64_ds {
|
||||
struct ipc64_perm msg_perm;
|
||||
__kernel_time_t msg_stime; /* last msgsnd time */
|
||||
__kernel_time_t msg_rtime; /* last msgrcv time */
|
||||
__kernel_time_t msg_ctime; /* last change time */
|
||||
__kernel_ulong_t msg_cbytes; /* current number of bytes on queue */
|
||||
__kernel_ulong_t msg_qnum; /* number of messages in queue */
|
||||
__kernel_ulong_t msg_qbytes; /* max number of bytes on queue */
|
||||
__kernel_pid_t msg_lspid; /* pid of last msgsnd */
|
||||
__kernel_pid_t msg_lrpid; /* last receive pid */
|
||||
__kernel_ulong_t __unused4;
|
||||
__kernel_ulong_t __unused5;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_GENERIC_MSGBUF_H */
|
||||
|
|
|
|||
|
|
@ -1 +1,43 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef __ASM_X86_SHMBUF_H
|
||||
#define __ASM_X86_SHMBUF_H
|
||||
|
||||
#if !defined(__x86_64__) || !defined(__ILP32__)
|
||||
#include <asm-generic/shmbuf.h>
|
||||
#else
|
||||
/*
|
||||
* The shmid64_ds structure for x86 architecture with x32 ABI.
|
||||
*
|
||||
* On x86-32 and x86-64 we can just use the generic definition, but
|
||||
* x32 uses the same binary layout as x86_64, which is differnet
|
||||
* from other 32-bit architectures.
|
||||
*/
|
||||
|
||||
struct shmid64_ds {
|
||||
struct ipc64_perm shm_perm; /* operation perms */
|
||||
size_t shm_segsz; /* size of segment (bytes) */
|
||||
__kernel_time_t shm_atime; /* last attach time */
|
||||
__kernel_time_t shm_dtime; /* last detach time */
|
||||
__kernel_time_t shm_ctime; /* last change time */
|
||||
__kernel_pid_t shm_cpid; /* pid of creator */
|
||||
__kernel_pid_t shm_lpid; /* pid of last operator */
|
||||
__kernel_ulong_t shm_nattch; /* no. of current attaches */
|
||||
__kernel_ulong_t __unused4;
|
||||
__kernel_ulong_t __unused5;
|
||||
};
|
||||
|
||||
struct shminfo64 {
|
||||
__kernel_ulong_t shmmax;
|
||||
__kernel_ulong_t shmmin;
|
||||
__kernel_ulong_t shmmni;
|
||||
__kernel_ulong_t shmseg;
|
||||
__kernel_ulong_t shmall;
|
||||
__kernel_ulong_t __unused1;
|
||||
__kernel_ulong_t __unused2;
|
||||
__kernel_ulong_t __unused3;
|
||||
__kernel_ulong_t __unused4;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_X86_SHMBUF_H */
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/cpu.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/nospec.h>
|
||||
|
||||
#include <asm/apic.h>
|
||||
#include <asm/stacktrace.h>
|
||||
|
|
@ -297,17 +298,20 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
|
|||
|
||||
config = attr->config;
|
||||
|
||||
cache_type = (config >> 0) & 0xff;
|
||||
cache_type = (config >> 0) & 0xff;
|
||||
if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
|
||||
return -EINVAL;
|
||||
cache_type = array_index_nospec(cache_type, PERF_COUNT_HW_CACHE_MAX);
|
||||
|
||||
cache_op = (config >> 8) & 0xff;
|
||||
if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
|
||||
return -EINVAL;
|
||||
cache_op = array_index_nospec(cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
|
||||
|
||||
cache_result = (config >> 16) & 0xff;
|
||||
if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
|
||||
return -EINVAL;
|
||||
cache_result = array_index_nospec(cache_result, PERF_COUNT_HW_CACHE_RESULT_MAX);
|
||||
|
||||
val = hw_cache_event_ids[cache_type][cache_op][cache_result];
|
||||
|
||||
|
|
@ -404,6 +408,8 @@ int x86_setup_perfctr(struct perf_event *event)
|
|||
if (attr->config >= x86_pmu.max_events)
|
||||
return -EINVAL;
|
||||
|
||||
attr->config = array_index_nospec((unsigned long)attr->config, x86_pmu.max_events);
|
||||
|
||||
/*
|
||||
* The generic map:
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include "perf_event.h"
|
||||
|
||||
|
|
@ -409,6 +410,7 @@ static int cstate_pmu_event_init(struct perf_event *event)
|
|||
} else if (event->pmu == &cstate_pkg_pmu) {
|
||||
if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
|
||||
return -EINVAL;
|
||||
cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX);
|
||||
if (!pkg_msr[cfg].attr)
|
||||
return -EINVAL;
|
||||
event->hw.event_base = pkg_msr[cfg].msr;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <linux/perf_event.h>
|
||||
#include <linux/nospec.h>
|
||||
|
||||
enum perf_msr_id {
|
||||
PERF_MSR_TSC = 0,
|
||||
|
|
@ -115,9 +116,6 @@ static int msr_event_init(struct perf_event *event)
|
|||
if (event->attr.type != event->pmu->type)
|
||||
return -ENOENT;
|
||||
|
||||
if (cfg >= PERF_MSR_EVENT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
/* unsupported modes and filters */
|
||||
if (event->attr.exclude_user ||
|
||||
event->attr.exclude_kernel ||
|
||||
|
|
@ -128,6 +126,11 @@ static int msr_event_init(struct perf_event *event)
|
|||
event->attr.sample_period) /* no sampling */
|
||||
return -EINVAL;
|
||||
|
||||
if (cfg >= PERF_MSR_EVENT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
cfg = array_index_nospec((unsigned long)cfg, PERF_MSR_EVENT_MAX);
|
||||
|
||||
if (!msr[cfg].attr)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,3 +42,5 @@ EXPORT_SYMBOL(empty_zero_page);
|
|||
EXPORT_SYMBOL(___preempt_schedule);
|
||||
EXPORT_SYMBOL(___preempt_schedule_notrace);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(__sw_hweight32);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include <linux/kdebug.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/moduleloader.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/desc.h>
|
||||
|
|
@ -402,6 +403,14 @@ int __copy_instruction(u8 *dest, u8 *src)
|
|||
return length;
|
||||
}
|
||||
|
||||
/* Recover page to RW mode before releasing it */
|
||||
void free_insn_page(void *page)
|
||||
{
|
||||
set_memory_nx((unsigned long)page & PAGE_MASK, 1);
|
||||
set_memory_rw((unsigned long)page & PAGE_MASK, 1);
|
||||
module_memfree(page);
|
||||
}
|
||||
|
||||
static int arch_copy_kprobe(struct kprobe *p)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -1442,6 +1442,8 @@ static inline void mwait_play_dead(void)
|
|||
void *mwait_ptr;
|
||||
int i;
|
||||
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
|
||||
return;
|
||||
if (!this_cpu_has(X86_FEATURE_MWAIT))
|
||||
return;
|
||||
if (!this_cpu_has(X86_FEATURE_CLFLUSH))
|
||||
|
|
|
|||
|
|
@ -365,6 +365,8 @@ static int __init tsc_setup(char *str)
|
|||
tsc_clocksource_reliable = 1;
|
||||
if (!strncmp(str, "noirqtime", 9))
|
||||
no_sched_irq_time = 1;
|
||||
if (!strcmp(str, "unstable"))
|
||||
mark_tsc_unstable("boot parameter");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -406,7 +408,7 @@ static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2)
|
|||
hpet2 -= hpet1;
|
||||
tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
|
||||
do_div(tmp, 1000000);
|
||||
do_div(deltatsc, tmp);
|
||||
deltatsc = div64_u64(deltatsc, tmp);
|
||||
|
||||
return (unsigned long) deltatsc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ EXPORT_SYMBOL(clear_page);
|
|||
|
||||
EXPORT_SYMBOL(csum_partial);
|
||||
|
||||
EXPORT_SYMBOL(__sw_hweight32);
|
||||
EXPORT_SYMBOL(__sw_hweight64);
|
||||
|
||||
/*
|
||||
* Export string functions. We normally rely on gcc builtin for most of these,
|
||||
* but gcc sometimes decides not to inline them.
|
||||
|
|
|
|||
|
|
@ -1386,6 +1386,7 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
|
|||
*/
|
||||
if (var->unusable)
|
||||
var->db = 0;
|
||||
/* This is symmetric with svm_set_segment() */
|
||||
var->dpl = to_svm(vcpu)->vmcb->save.cpl;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1531,18 +1532,14 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
|
|||
s->base = var->base;
|
||||
s->limit = var->limit;
|
||||
s->selector = var->selector;
|
||||
if (var->unusable)
|
||||
s->attrib = 0;
|
||||
else {
|
||||
s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
|
||||
s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
|
||||
s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
|
||||
s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT;
|
||||
s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
|
||||
s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
|
||||
s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
|
||||
s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
|
||||
}
|
||||
s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
|
||||
s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
|
||||
s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
|
||||
s->attrib |= ((var->present & 1) && !var->unusable) << SVM_SELECTOR_P_SHIFT;
|
||||
s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
|
||||
s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
|
||||
s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
|
||||
s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
|
||||
|
||||
/*
|
||||
* This is always accurate, except if SYSRET returned to a segment
|
||||
|
|
@ -1551,7 +1548,8 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
|
|||
* would entail passing the CPL to userspace and back.
|
||||
*/
|
||||
if (seg == VCPU_SREG_SS)
|
||||
svm->vmcb->save.cpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3;
|
||||
/* This is symmetric with svm_get_segment() */
|
||||
svm->vmcb->save.cpl = (var->dpl & 3);
|
||||
|
||||
mark_dirty(svm->vmcb, VMCB_SEG);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7657,11 +7657,13 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
|
|||
{
|
||||
unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
|
||||
int cr = exit_qualification & 15;
|
||||
int reg = (exit_qualification >> 8) & 15;
|
||||
unsigned long val = kvm_register_readl(vcpu, reg);
|
||||
int reg;
|
||||
unsigned long val;
|
||||
|
||||
switch ((exit_qualification >> 4) & 3) {
|
||||
case 0: /* mov to cr */
|
||||
reg = (exit_qualification >> 8) & 15;
|
||||
val = kvm_register_readl(vcpu, reg);
|
||||
switch (cr) {
|
||||
case 0:
|
||||
if (vmcs12->cr0_guest_host_mask &
|
||||
|
|
@ -7716,6 +7718,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
|
|||
* lmsw can change bits 1..3 of cr0, and only set bit 0 of
|
||||
* cr0. Other attempted changes are ignored, with no exit.
|
||||
*/
|
||||
val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
|
||||
if (vmcs12->cr0_guest_host_mask & 0xe &
|
||||
(val ^ vmcs12->cr0_read_shadow))
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
|
|||
lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o
|
||||
lib-$(CONFIG_RETPOLINE) += retpoline.o
|
||||
|
||||
obj-y += msr.o msr-reg.o msr-reg-export.o
|
||||
obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
|
||||
|
||||
ifeq ($(CONFIG_X86_32),y)
|
||||
obj-y += atomic64_32.o
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ ENTRY(csum_partial_copy_generic)
|
|||
movq %r12, 3*8(%rsp)
|
||||
movq %r14, 4*8(%rsp)
|
||||
movq %r13, 5*8(%rsp)
|
||||
movq %rbp, 6*8(%rsp)
|
||||
movq %r15, 6*8(%rsp)
|
||||
|
||||
movq %r8, (%rsp)
|
||||
movq %r9, 1*8(%rsp)
|
||||
|
|
@ -74,7 +74,7 @@ ENTRY(csum_partial_copy_generic)
|
|||
/* main loop. clear in 64 byte blocks */
|
||||
/* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
|
||||
/* r11: temp3, rdx: temp4, r12 loopcnt */
|
||||
/* r10: temp5, rbp: temp6, r14 temp7, r13 temp8 */
|
||||
/* r10: temp5, r15: temp6, r14 temp7, r13 temp8 */
|
||||
.p2align 4
|
||||
.Lloop:
|
||||
source
|
||||
|
|
@ -89,7 +89,7 @@ ENTRY(csum_partial_copy_generic)
|
|||
source
|
||||
movq 32(%rdi), %r10
|
||||
source
|
||||
movq 40(%rdi), %rbp
|
||||
movq 40(%rdi), %r15
|
||||
source
|
||||
movq 48(%rdi), %r14
|
||||
source
|
||||
|
|
@ -103,7 +103,7 @@ ENTRY(csum_partial_copy_generic)
|
|||
adcq %r11, %rax
|
||||
adcq %rdx, %rax
|
||||
adcq %r10, %rax
|
||||
adcq %rbp, %rax
|
||||
adcq %r15, %rax
|
||||
adcq %r14, %rax
|
||||
adcq %r13, %rax
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ ENTRY(csum_partial_copy_generic)
|
|||
dest
|
||||
movq %r10, 32(%rsi)
|
||||
dest
|
||||
movq %rbp, 40(%rsi)
|
||||
movq %r15, 40(%rsi)
|
||||
dest
|
||||
movq %r14, 48(%rsi)
|
||||
dest
|
||||
|
|
@ -203,7 +203,7 @@ ENTRY(csum_partial_copy_generic)
|
|||
movq 3*8(%rsp), %r12
|
||||
movq 4*8(%rsp), %r14
|
||||
movq 5*8(%rsp), %r13
|
||||
movq 6*8(%rsp), %rbp
|
||||
movq 6*8(%rsp), %r15
|
||||
addq $7*8, %rsp
|
||||
ret
|
||||
|
||||
|
|
|
|||
79
arch/x86/lib/hweight.S
Normal file
79
arch/x86/lib/hweight.S
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#include <linux/linkage.h>
|
||||
|
||||
#include <asm/asm.h>
|
||||
|
||||
/*
|
||||
* unsigned int __sw_hweight32(unsigned int w)
|
||||
* %rdi: w
|
||||
*/
|
||||
ENTRY(__sw_hweight32)
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
movl %edi, %eax # w
|
||||
#endif
|
||||
__ASM_SIZE(push,) %__ASM_REG(dx)
|
||||
movl %eax, %edx # w -> t
|
||||
shrl %edx # t >>= 1
|
||||
andl $0x55555555, %edx # t &= 0x55555555
|
||||
subl %edx, %eax # w -= t
|
||||
|
||||
movl %eax, %edx # w -> t
|
||||
shrl $2, %eax # w_tmp >>= 2
|
||||
andl $0x33333333, %edx # t &= 0x33333333
|
||||
andl $0x33333333, %eax # w_tmp &= 0x33333333
|
||||
addl %edx, %eax # w = w_tmp + t
|
||||
|
||||
movl %eax, %edx # w -> t
|
||||
shrl $4, %edx # t >>= 4
|
||||
addl %edx, %eax # w_tmp += t
|
||||
andl $0x0f0f0f0f, %eax # w_tmp &= 0x0f0f0f0f
|
||||
imull $0x01010101, %eax, %eax # w_tmp *= 0x01010101
|
||||
shrl $24, %eax # w = w_tmp >> 24
|
||||
__ASM_SIZE(pop,) %__ASM_REG(dx)
|
||||
ret
|
||||
ENDPROC(__sw_hweight32)
|
||||
|
||||
ENTRY(__sw_hweight64)
|
||||
#ifdef CONFIG_X86_64
|
||||
pushq %rdi
|
||||
pushq %rdx
|
||||
|
||||
movq %rdi, %rdx # w -> t
|
||||
movabsq $0x5555555555555555, %rax
|
||||
shrq %rdx # t >>= 1
|
||||
andq %rdx, %rax # t &= 0x5555555555555555
|
||||
movabsq $0x3333333333333333, %rdx
|
||||
subq %rax, %rdi # w -= t
|
||||
|
||||
movq %rdi, %rax # w -> t
|
||||
shrq $2, %rdi # w_tmp >>= 2
|
||||
andq %rdx, %rax # t &= 0x3333333333333333
|
||||
andq %rdi, %rdx # w_tmp &= 0x3333333333333333
|
||||
addq %rdx, %rax # w = w_tmp + t
|
||||
|
||||
movq %rax, %rdx # w -> t
|
||||
shrq $4, %rdx # t >>= 4
|
||||
addq %rdx, %rax # w_tmp += t
|
||||
movabsq $0x0f0f0f0f0f0f0f0f, %rdx
|
||||
andq %rdx, %rax # w_tmp &= 0x0f0f0f0f0f0f0f0f
|
||||
movabsq $0x0101010101010101, %rdx
|
||||
imulq %rdx, %rax # w_tmp *= 0x0101010101010101
|
||||
shrq $56, %rax # w = w_tmp >> 56
|
||||
|
||||
popq %rdx
|
||||
popq %rdi
|
||||
ret
|
||||
#else /* CONFIG_X86_32 */
|
||||
/* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */
|
||||
pushl %ecx
|
||||
|
||||
call __sw_hweight32
|
||||
movl %eax, %ecx # stash away result
|
||||
movl %edx, %eax # second part of input
|
||||
call __sw_hweight32
|
||||
addl %ecx, %eax # result
|
||||
|
||||
popl %ecx
|
||||
ret
|
||||
#endif
|
||||
ENDPROC(__sw_hweight64)
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
void __attribute__ ((__section__ (".__syscall_stub")))
|
||||
stub_segv_handler(int sig, siginfo_t *info, void *p)
|
||||
{
|
||||
struct ucontext *uc = p;
|
||||
ucontext_t *uc = p;
|
||||
|
||||
GET_FAULTINFO_FROM_MC(*((struct faultinfo *) STUB_DATA),
|
||||
&uc->uc_mcontext);
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ bool bio_integrity_enabled(struct bio *bio)
|
|||
if (!bio_is_rw(bio))
|
||||
return false;
|
||||
|
||||
if (!bio_sectors(bio))
|
||||
return false;
|
||||
|
||||
/* Already protected? */
|
||||
if (bio_integrity(bio))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1252,13 +1252,13 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
|
|||
|
||||
blk_queue_bounce(q, &bio);
|
||||
|
||||
blk_queue_split(q, &bio, q->bio_split);
|
||||
|
||||
if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
|
||||
bio_io_error(bio);
|
||||
return BLK_QC_T_NONE;
|
||||
}
|
||||
|
||||
blk_queue_split(q, &bio, q->bio_split);
|
||||
|
||||
if (!is_flush_fua && !blk_queue_nomerges(q) &&
|
||||
blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
|
||||
return BLK_QC_T_NONE;
|
||||
|
|
@ -1634,7 +1634,8 @@ static void blk_mq_exit_hctx(struct request_queue *q,
|
|||
{
|
||||
unsigned flush_start_tag = set->queue_depth;
|
||||
|
||||
blk_mq_tag_idle(hctx);
|
||||
if (blk_mq_hw_queue_mapped(hctx))
|
||||
blk_mq_tag_idle(hctx);
|
||||
|
||||
if (set->ops->exit_request)
|
||||
set->ops->exit_request(set->driver_data,
|
||||
|
|
|
|||
|
|
@ -309,8 +309,10 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,
|
|||
|
||||
if (info) {
|
||||
struct partition_meta_info *pinfo = alloc_part_info(disk);
|
||||
if (!pinfo)
|
||||
if (!pinfo) {
|
||||
err = -ENOMEM;
|
||||
goto out_free_stats;
|
||||
}
|
||||
memcpy(pinfo, info, sizeof(*info));
|
||||
p->info = pinfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@ static void parse_bsd(struct parsed_partitions *state,
|
|||
continue;
|
||||
bsd_start = le32_to_cpu(p->p_offset);
|
||||
bsd_size = le32_to_cpu(p->p_size);
|
||||
if (memcmp(flavour, "bsd\0", 4) == 0)
|
||||
/* FreeBSD has relative offset if C partition offset is zero */
|
||||
if (memcmp(flavour, "bsd\0", 4) == 0 &&
|
||||
le32_to_cpu(l->d_partitions[2].p_offset) == 0)
|
||||
bsd_start += offset;
|
||||
if (offset == bsd_start && size == bsd_size)
|
||||
/* full parent partition, we have it already */
|
||||
|
|
|
|||
|
|
@ -157,16 +157,16 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
|||
void *private;
|
||||
int err;
|
||||
|
||||
/* If caller uses non-allowed flag, return error. */
|
||||
if ((sa->salg_feat & ~allowed) || (sa->salg_mask & ~allowed))
|
||||
return -EINVAL;
|
||||
|
||||
if (sock->state == SS_CONNECTED)
|
||||
return -EINVAL;
|
||||
|
||||
if (addr_len != sizeof(*sa))
|
||||
return -EINVAL;
|
||||
|
||||
/* If caller uses non-allowed flag, return error. */
|
||||
if ((sa->salg_feat & ~allowed) || (sa->salg_mask & ~allowed))
|
||||
return -EINVAL;
|
||||
|
||||
sa->salg_type[sizeof(sa->salg_type) - 1] = 0;
|
||||
sa->salg_name[sizeof(sa->salg_name) - 1] = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -91,13 +91,14 @@ int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
|
|||
|
||||
if (nbytes && walk->offset & alignmask && !err) {
|
||||
walk->offset = ALIGN(walk->offset, alignmask + 1);
|
||||
walk->data += walk->offset;
|
||||
|
||||
nbytes = min(nbytes,
|
||||
((unsigned int)(PAGE_SIZE)) - walk->offset);
|
||||
walk->entrylen -= nbytes;
|
||||
|
||||
return nbytes;
|
||||
if (nbytes) {
|
||||
walk->data += walk->offset;
|
||||
return nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (walk->flags & CRYPTO_ALG_ASYNC)
|
||||
|
|
|
|||
|
|
@ -62,9 +62,6 @@ do_async_gen_syndrome(struct dma_chan *chan,
|
|||
dma_addr_t dma_dest[2];
|
||||
int src_off = 0;
|
||||
|
||||
if (submit->flags & ASYNC_TX_FENCE)
|
||||
dma_flags |= DMA_PREP_FENCE;
|
||||
|
||||
while (src_cnt > 0) {
|
||||
submit->flags = flags_orig;
|
||||
pq_src_cnt = min(src_cnt, dma_maxpq(dma, dma_flags));
|
||||
|
|
@ -83,6 +80,8 @@ do_async_gen_syndrome(struct dma_chan *chan,
|
|||
if (cb_fn_orig)
|
||||
dma_flags |= DMA_PREP_INTERRUPT;
|
||||
}
|
||||
if (submit->flags & ASYNC_TX_FENCE)
|
||||
dma_flags |= DMA_PREP_FENCE;
|
||||
|
||||
/* Drivers force forward progress in case they can not provide
|
||||
* a descriptor
|
||||
|
|
|
|||
|
|
@ -180,6 +180,12 @@ acpi_status acpi_enable_event(u32 event, u32 flags)
|
|||
|
||||
ACPI_FUNCTION_TRACE(acpi_enable_event);
|
||||
|
||||
/* If Hardware Reduced flag is set, there are no fixed events */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* Decode the Fixed Event */
|
||||
|
||||
if (event > ACPI_EVENT_MAX) {
|
||||
|
|
@ -237,6 +243,12 @@ acpi_status acpi_disable_event(u32 event, u32 flags)
|
|||
|
||||
ACPI_FUNCTION_TRACE(acpi_disable_event);
|
||||
|
||||
/* If Hardware Reduced flag is set, there are no fixed events */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* Decode the Fixed Event */
|
||||
|
||||
if (event > ACPI_EVENT_MAX) {
|
||||
|
|
@ -290,6 +302,12 @@ acpi_status acpi_clear_event(u32 event)
|
|||
|
||||
ACPI_FUNCTION_TRACE(acpi_clear_event);
|
||||
|
||||
/* If Hardware Reduced flag is set, there are no fixed events */
|
||||
|
||||
if (acpi_gbl_reduced_hardware) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* Decode the Fixed Event */
|
||||
|
||||
if (event > ACPI_EVENT_MAX) {
|
||||
|
|
|
|||
|
|
@ -121,6 +121,9 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
|
|||
(u32)(aml_offset +
|
||||
sizeof(struct acpi_table_header)));
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Aborting disassembly, AML byte code is corrupt"));
|
||||
|
||||
/* Dump the context surrounding the invalid opcode */
|
||||
|
||||
acpi_ut_dump_buffer(((u8 *)walk_state->parser_state.
|
||||
|
|
@ -129,6 +132,14 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
|
|||
sizeof(struct acpi_table_header) -
|
||||
16));
|
||||
acpi_os_printf(" */\n");
|
||||
|
||||
/*
|
||||
* Just abort the disassembly, cannot continue because the
|
||||
* parser is essentially lost. The disassembler can then
|
||||
* randomly fail because an ill-constructed parse tree
|
||||
* can result.
|
||||
*/
|
||||
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -293,6 +304,9 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state,
|
|||
if (status == AE_CTRL_PARSE_CONTINUE) {
|
||||
return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
|
||||
}
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Create Op structure and append to parent's argument list */
|
||||
|
||||
|
|
|
|||
|
|
@ -131,9 +131,6 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
|
|||
quirk = &prt_quirks[i];
|
||||
|
||||
/* All current quirks involve link devices, not GSIs */
|
||||
if (!prt->source)
|
||||
continue;
|
||||
|
||||
if (dmi_check_system(quirk->system) &&
|
||||
entry->id.segment == quirk->segment &&
|
||||
entry->id.bus == quirk->bus &&
|
||||
|
|
|
|||
|
|
@ -205,6 +205,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||
"3570R/370R/470R/450R/510R/4450RV"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugzilla.redhat.com/show_bug.cgi?id=1557060 */
|
||||
.callback = video_detect_force_video,
|
||||
.ident = "SAMSUNG 670Z5E",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "670Z5E"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* https://bugzilla.redhat.com/show_bug.cgi?id=1094948 */
|
||||
.callback = video_detect_force_video,
|
||||
|
|
|
|||
|
|
@ -68,11 +68,12 @@ static ssize_t driver_override_show(struct device *_dev,
|
|||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct amba_device *dev = to_amba_device(_dev);
|
||||
ssize_t len;
|
||||
|
||||
if (!dev->driver_override)
|
||||
return 0;
|
||||
|
||||
return sprintf(buf, "%s\n", dev->driver_override);
|
||||
device_lock(_dev);
|
||||
len = sprintf(buf, "%s\n", dev->driver_override);
|
||||
device_unlock(_dev);
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t driver_override_store(struct device *_dev,
|
||||
|
|
@ -80,9 +81,10 @@ static ssize_t driver_override_store(struct device *_dev,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct amba_device *dev = to_amba_device(_dev);
|
||||
char *driver_override, *old = dev->driver_override, *cp;
|
||||
char *driver_override, *old, *cp;
|
||||
|
||||
if (count > PATH_MAX)
|
||||
/* We need to keep extra room for a newline */
|
||||
if (count >= (PAGE_SIZE - 1))
|
||||
return -EINVAL;
|
||||
|
||||
driver_override = kstrndup(buf, count, GFP_KERNEL);
|
||||
|
|
@ -93,12 +95,15 @@ static ssize_t driver_override_store(struct device *_dev,
|
|||
if (cp)
|
||||
*cp = '\0';
|
||||
|
||||
device_lock(_dev);
|
||||
old = dev->driver_override;
|
||||
if (strlen(driver_override)) {
|
||||
dev->driver_override = driver_override;
|
||||
} else {
|
||||
kfree(driver_override);
|
||||
dev->driver_override = NULL;
|
||||
}
|
||||
device_unlock(_dev);
|
||||
|
||||
kfree(old);
|
||||
|
||||
|
|
|
|||
|
|
@ -514,8 +514,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
|
|||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0) {
|
||||
dev_err(dev, "no irq\n");
|
||||
return -EINVAL;
|
||||
if (irq != -EPROBE_DEFER)
|
||||
dev_err(dev, "no irq\n");
|
||||
return irq;
|
||||
}
|
||||
|
||||
hpriv->irq = irq;
|
||||
|
|
|
|||
|
|
@ -4243,6 +4243,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
|||
ATA_HORKAGE_ZERO_AFTER_TRIM |
|
||||
ATA_HORKAGE_NOLPM, },
|
||||
|
||||
/* Sandisk devices which are known to not handle LPM well */
|
||||
{ "SanDisk SD7UB3Q*G1001", NULL, ATA_HORKAGE_NOLPM, },
|
||||
|
||||
/* devices that don't properly handle queued TRIM commands */
|
||||
{ "Micron_M500_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
|
||||
ATA_HORKAGE_ZERO_AFTER_TRIM, },
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/string.h>
|
||||
#include <asm/io.h>
|
||||
|
|
@ -1456,6 +1457,8 @@ static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
|
|||
return -EFAULT;
|
||||
if (pool < 0 || pool > ZATM_LAST_POOL)
|
||||
return -EINVAL;
|
||||
pool = array_index_nospec(pool,
|
||||
ZATM_LAST_POOL + 1);
|
||||
spin_lock_irqsave(&zatm_dev->lock, flags);
|
||||
info = zatm_dev->pool_info[pool];
|
||||
if (cmd == ZATM_GETPOOLZ) {
|
||||
|
|
|
|||
|
|
@ -1582,7 +1582,7 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
|
|||
return -EINVAL;
|
||||
if (val_len % map->format.val_bytes)
|
||||
return -EINVAL;
|
||||
if (map->max_raw_write && map->max_raw_write > val_len)
|
||||
if (map->max_raw_write && map->max_raw_write < val_len)
|
||||
return -E2BIG;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
|
|
|
|||
|
|
@ -623,6 +623,9 @@ static int loop_switch(struct loop_device *lo, struct file *file)
|
|||
*/
|
||||
static int loop_flush(struct loop_device *lo)
|
||||
{
|
||||
/* loop not yet configured, no running thread, nothing to flush */
|
||||
if (lo->lo_state != Lo_bound)
|
||||
return 0;
|
||||
return loop_switch(lo, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1118,11 +1121,15 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
|||
if (info->lo_encrypt_type) {
|
||||
unsigned int type = info->lo_encrypt_type;
|
||||
|
||||
if (type >= MAX_LO_CRYPT)
|
||||
return -EINVAL;
|
||||
if (type >= MAX_LO_CRYPT) {
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
xfer = xfer_funcs[type];
|
||||
if (xfer == NULL)
|
||||
return -EINVAL;
|
||||
if (xfer == NULL) {
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
} else
|
||||
xfer = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -169,25 +169,6 @@ static bool mtip_check_surprise_removal(struct pci_dev *pdev)
|
|||
return false; /* device present */
|
||||
}
|
||||
|
||||
/* we have to use runtime tag to setup command header */
|
||||
static void mtip_init_cmd_header(struct request *rq)
|
||||
{
|
||||
struct driver_data *dd = rq->q->queuedata;
|
||||
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
u32 host_cap_64 = readl(dd->mmio + HOST_CAP) & HOST_CAP_64;
|
||||
|
||||
/* Point the command headers at the command tables. */
|
||||
cmd->command_header = dd->port->command_list +
|
||||
(sizeof(struct mtip_cmd_hdr) * rq->tag);
|
||||
cmd->command_header_dma = dd->port->command_list_dma +
|
||||
(sizeof(struct mtip_cmd_hdr) * rq->tag);
|
||||
|
||||
if (host_cap_64)
|
||||
cmd->command_header->ctbau = __force_bit2int cpu_to_le32((cmd->command_dma >> 16) >> 16);
|
||||
|
||||
cmd->command_header->ctba = __force_bit2int cpu_to_le32(cmd->command_dma & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd)
|
||||
{
|
||||
struct request *rq;
|
||||
|
|
@ -199,9 +180,6 @@ static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd)
|
|||
if (IS_ERR(rq))
|
||||
return NULL;
|
||||
|
||||
/* Internal cmd isn't submitted via .queue_rq */
|
||||
mtip_init_cmd_header(rq);
|
||||
|
||||
return blk_mq_rq_to_pdu(rq);
|
||||
}
|
||||
|
||||
|
|
@ -3840,8 +3818,6 @@ static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx,
|
|||
struct request *rq = bd->rq;
|
||||
int ret;
|
||||
|
||||
mtip_init_cmd_header(rq);
|
||||
|
||||
if (unlikely(mtip_check_unal_depth(hctx, rq)))
|
||||
return BLK_MQ_RQ_QUEUE_BUSY;
|
||||
|
||||
|
|
@ -3873,6 +3849,7 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx,
|
|||
{
|
||||
struct driver_data *dd = data;
|
||||
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
u32 host_cap_64 = readl(dd->mmio + HOST_CAP) & HOST_CAP_64;
|
||||
|
||||
/*
|
||||
* For flush requests, request_idx starts at the end of the
|
||||
|
|
@ -3889,6 +3866,17 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx,
|
|||
|
||||
memset(cmd->command, 0, CMD_DMA_ALLOC_SZ);
|
||||
|
||||
/* Point the command headers at the command tables. */
|
||||
cmd->command_header = dd->port->command_list +
|
||||
(sizeof(struct mtip_cmd_hdr) * request_idx);
|
||||
cmd->command_header_dma = dd->port->command_list_dma +
|
||||
(sizeof(struct mtip_cmd_hdr) * request_idx);
|
||||
|
||||
if (host_cap_64)
|
||||
cmd->command_header->ctbau = __force_bit2int cpu_to_le32((cmd->command_dma >> 16) >> 16);
|
||||
|
||||
cmd->command_header->ctba = __force_bit2int cpu_to_le32(cmd->command_dma & 0xFFFFFFFF);
|
||||
|
||||
sg_init_table(cmd->sg, MTIP_MAX_SG);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user