From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 8B2651382C5 for ; Sat, 17 Feb 2018 14:02:26 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id A286FE0978; Sat, 17 Feb 2018 14:02:25 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 51D13E0978 for ; Sat, 17 Feb 2018 14:02:25 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id AFAAB335C06 for ; Sat, 17 Feb 2018 14:02:23 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id D94471D4 for ; Sat, 17 Feb 2018 14:02:18 +0000 (UTC) From: "Alice Ferrazzi" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Alice Ferrazzi" Message-ID: <1518876116.22eadc0e10798d00a998ffebb02b9b4d83a7edb3.alicef@gentoo> Subject: [gentoo-commits] proj/linux-patches:4.15 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1003_linux-4.15.4.patch X-VCS-Directories: / X-VCS-Committer: alicef X-VCS-Committer-Name: Alice Ferrazzi X-VCS-Revision: 22eadc0e10798d00a998ffebb02b9b4d83a7edb3 X-VCS-Branch: 4.15 Date: Sat, 17 Feb 2018 14:02:18 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: ee599e05-469a-441c-b99f-647702facbd4 X-Archives-Hash: 6028e99664bbaa1b8109119f5bdf1966 commit: 22eadc0e10798d00a998ffebb02b9b4d83a7edb3 Author: Alice Ferrazzi gentoo org> AuthorDate: Sat Feb 17 14:01:56 2018 +0000 Commit: Alice Ferrazzi gentoo org> CommitDate: Sat Feb 17 14:01:56 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=22eadc0e linux kernel 4.15.4 0000_README | 4 + 1003_linux-4.15.4.patch | 10956 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 10960 insertions(+) diff --git a/0000_README b/0000_README index 635b977..ffe8729 100644 --- a/0000_README +++ b/0000_README @@ -55,6 +55,10 @@ Patch: 1002_linux-4.15.3.patch From: http://www.kernel.org Desc: Linux 4.15.3 +Patch: 1003_linux-4.15.4.patch +From: http://www.kernel.org +Desc: Linux 4.15.4 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1003_linux-4.15.4.patch b/1003_linux-4.15.4.patch new file mode 100644 index 0000000..657bd62 --- /dev/null +++ b/1003_linux-4.15.4.patch @@ -0,0 +1,10956 @@ +diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt +index fc1c884fea10..c1d520de6dfe 100644 +--- a/Documentation/arm64/silicon-errata.txt ++++ b/Documentation/arm64/silicon-errata.txt +@@ -72,7 +72,7 @@ stable kernels. + | Hisilicon | Hip0{6,7} | #161010701 | N/A | + | Hisilicon | Hip07 | #161600802 | HISILICON_ERRATUM_161600802 | + | | | | | +-| Qualcomm Tech. | Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | ++| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | + | Qualcomm Tech. | Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 | + | Qualcomm Tech. | QDF2400 ITS | E0065 | QCOM_QDF2400_ERRATUM_0065 | + | Qualcomm Tech. | Falkor v{1,2} | E1041 | QCOM_FALKOR_ERRATUM_1041 | +diff --git a/Documentation/devicetree/bindings/media/cec-gpio.txt b/Documentation/devicetree/bindings/media/cec-gpio.txt +index 46a0bac8b3b9..12fcd55ed153 100644 +--- a/Documentation/devicetree/bindings/media/cec-gpio.txt ++++ b/Documentation/devicetree/bindings/media/cec-gpio.txt +@@ -4,6 +4,10 @@ The HDMI CEC GPIO module supports CEC implementations where the CEC line + is hooked up to a pull-up GPIO line and - optionally - the HPD line is + hooked up to another GPIO line. + ++Please note: the maximum voltage for the CEC line is 3.63V, for the HPD ++line it is 5.3V. So you may need some sort of level conversion circuitry ++when connecting them to a GPIO line. ++ + Required properties: + - compatible: value must be "cec-gpio". + - cec-gpios: gpio that the CEC line is connected to. The line should be +@@ -21,7 +25,7 @@ the following property is optional: + + Example for the Raspberry Pi 3 where the CEC line is connected to + pin 26 aka BCM7 aka CE1 on the GPIO pin header and the HPD line is +-connected to pin 11 aka BCM17: ++connected to pin 11 aka BCM17 (some level shifter is needed for this!): + + #include + +diff --git a/Makefile b/Makefile +index 13566ad7863a..8495e1ca052e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 15 +-SUBLEVEL = 3 ++SUBLEVEL = 4 + EXTRAVERSION = + NAME = Fearless Coyote + +@@ -432,7 +432,8 @@ export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE + export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS + + export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS +-export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_KASAN CFLAGS_UBSAN ++export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE ++export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE CFLAGS_UBSAN + export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE + export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE + export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL +diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h +index d2e4da93e68c..ca3322536f72 100644 +--- a/arch/alpha/include/asm/futex.h ++++ b/arch/alpha/include/asm/futex.h +@@ -20,8 +20,8 @@ + "3: .subsection 2\n" \ + "4: br 1b\n" \ + " .previous\n" \ +- EXC(1b,3b,%1,$31) \ +- EXC(2b,3b,%1,$31) \ ++ EXC(1b,3b,$31,%1) \ ++ EXC(2b,3b,$31,%1) \ + : "=&r" (oldval), "=&r"(ret) \ + : "r" (uaddr), "r"(oparg) \ + : "memory") +@@ -82,8 +82,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + "3: .subsection 2\n" + "4: br 1b\n" + " .previous\n" +- EXC(1b,3b,%0,$31) +- EXC(2b,3b,%0,$31) ++ EXC(1b,3b,$31,%0) ++ EXC(2b,3b,$31,%0) + : "+r"(ret), "=&r"(prev), "=&r"(cmp) + : "r"(uaddr), "r"((long)(int)oldval), "r"(newval) + : "memory"); +diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c +index ce3a675c0c4b..75a5c35a2067 100644 +--- a/arch/alpha/kernel/osf_sys.c ++++ b/arch/alpha/kernel/osf_sys.c +@@ -964,8 +964,8 @@ static inline long + put_tv32(struct timeval32 __user *o, struct timeval *i) + { + return copy_to_user(o, &(struct timeval32){ +- .tv_sec = o->tv_sec, +- .tv_usec = o->tv_usec}, ++ .tv_sec = i->tv_sec, ++ .tv_usec = i->tv_usec}, + sizeof(struct timeval32)); + } + +diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h +index 2e4cb74fdc41..18043af45e2b 100644 +--- a/arch/alpha/kernel/pci_impl.h ++++ b/arch/alpha/kernel/pci_impl.h +@@ -144,7 +144,8 @@ struct pci_iommu_arena + }; + + #if defined(CONFIG_ALPHA_SRM) && \ +- (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA)) ++ (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA) || \ ++ defined(CONFIG_ALPHA_AVANTI)) + # define NEED_SRM_SAVE_RESTORE + #else + # undef NEED_SRM_SAVE_RESTORE +diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c +index 74bfb1f2d68e..3a885253f486 100644 +--- a/arch/alpha/kernel/process.c ++++ b/arch/alpha/kernel/process.c +@@ -269,12 +269,13 @@ copy_thread(unsigned long clone_flags, unsigned long usp, + application calling fork. */ + if (clone_flags & CLONE_SETTLS) + childti->pcb.unique = regs->r20; ++ else ++ regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */ + childti->pcb.usp = usp ?: rdusp(); + *childregs = *regs; + childregs->r0 = 0; + childregs->r19 = 0; + childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ +- regs->r20 = 0; + stack = ((struct switch_stack *) regs) - 1; + *childstack = *stack; + childstack->r26 = (unsigned long) ret_from_fork; +diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c +index 4bd99a7b1c41..f43bd05dede2 100644 +--- a/arch/alpha/kernel/traps.c ++++ b/arch/alpha/kernel/traps.c +@@ -160,11 +160,16 @@ void show_stack(struct task_struct *task, unsigned long *sp) + for(i=0; i < kstack_depth_to_print; i++) { + if (((long) stack & (THREAD_SIZE-1)) == 0) + break; +- if (i && ((i % 4) == 0)) +- printk("\n "); +- printk("%016lx ", *stack++); ++ if ((i % 4) == 0) { ++ if (i) ++ pr_cont("\n"); ++ printk(" "); ++ } else { ++ pr_cont(" "); ++ } ++ pr_cont("%016lx", *stack++); + } +- printk("\n"); ++ pr_cont("\n"); + dik_show_trace(sp); + } + +diff --git a/arch/arm/crypto/crc32-ce-glue.c b/arch/arm/crypto/crc32-ce-glue.c +index 1b0e0e86ee9c..96e62ec105d0 100644 +--- a/arch/arm/crypto/crc32-ce-glue.c ++++ b/arch/arm/crypto/crc32-ce-glue.c +@@ -188,6 +188,7 @@ static struct shash_alg crc32_pmull_algs[] = { { + .base.cra_name = "crc32", + .base.cra_driver_name = "crc32-arm-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + }, { +@@ -203,6 +204,7 @@ static struct shash_alg crc32_pmull_algs[] = { { + .base.cra_name = "crc32c", + .base.cra_driver_name = "crc32c-arm-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + } }; +diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h +index a9f7d3f47134..fdd9da1555be 100644 +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -301,4 +301,10 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu, + /* All host FP/SIMD state is restored on guest exit, so nothing to save: */ + static inline void kvm_fpsimd_flush_cpu_state(void) {} + ++static inline bool kvm_arm_harden_branch_predictor(void) ++{ ++ /* No way to detect it yet, pretend it is not there. */ ++ return false; ++} ++ + #endif /* __ARM_KVM_HOST_H__ */ +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index fa6f2174276b..eb46fc81a440 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -221,6 +221,16 @@ static inline unsigned int kvm_get_vmid_bits(void) + return 8; + } + ++static inline void *kvm_get_hyp_vector(void) ++{ ++ return kvm_ksym_ref(__kvm_hyp_vector); ++} ++ ++static inline int kvm_map_vectors(void) ++{ ++ return 0; ++} ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* __ARM_KVM_MMU_H__ */ +diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h +deleted file mode 100644 +index 6bda945d31fa..000000000000 +--- a/arch/arm/include/asm/kvm_psci.h ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* +- * Copyright (C) 2012 - ARM Ltd +- * Author: Marc Zyngier +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef __ARM_KVM_PSCI_H__ +-#define __ARM_KVM_PSCI_H__ +- +-#define KVM_ARM_PSCI_0_1 1 +-#define KVM_ARM_PSCI_0_2 2 +- +-int kvm_psci_version(struct kvm_vcpu *vcpu); +-int kvm_psci_call(struct kvm_vcpu *vcpu); +- +-#endif /* __ARM_KVM_PSCI_H__ */ +diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c +index cf8bf6bf87c4..910bd8dabb3c 100644 +--- a/arch/arm/kvm/handle_exit.c ++++ b/arch/arm/kvm/handle_exit.c +@@ -21,7 +21,7 @@ + #include + #include + #include +-#include ++#include + #include + + #include "trace.h" +@@ -36,9 +36,9 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) + kvm_vcpu_hvc_get_imm(vcpu)); + vcpu->stat.hvc_exit_stat++; + +- ret = kvm_psci_call(vcpu); ++ ret = kvm_hvc_call_handler(vcpu); + if (ret < 0) { +- kvm_inject_undefined(vcpu); ++ vcpu_set_reg(vcpu, 0, ~0UL); + return 1; + } + +@@ -47,7 +47,16 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) + + static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) + { +- kvm_inject_undefined(vcpu); ++ /* ++ * "If an SMC instruction executed at Non-secure EL1 is ++ * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a ++ * Trap exception, not a Secure Monitor Call exception [...]" ++ * ++ * We need to advance the PC after the trap, as it would ++ * otherwise return to the same address... ++ */ ++ vcpu_set_reg(vcpu, 0, ~0UL); ++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 1; + } + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index c9a7e9e1414f..d22f64095ca2 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -522,20 +522,13 @@ config CAVIUM_ERRATUM_30115 + config QCOM_FALKOR_ERRATUM_1003 + bool "Falkor E1003: Incorrect translation due to ASID change" + default y +- select ARM64_PAN if ARM64_SW_TTBR0_PAN + help + On Falkor v1, an incorrect ASID may be cached in the TLB when ASID +- and BADDR are changed together in TTBRx_EL1. The workaround for this +- issue is to use a reserved ASID in cpu_do_switch_mm() before +- switching to the new ASID. Saying Y here selects ARM64_PAN if +- ARM64_SW_TTBR0_PAN is selected. This is done because implementing and +- maintaining the E1003 workaround in the software PAN emulation code +- would be an unnecessary complication. The affected Falkor v1 CPU +- implements ARMv8.1 hardware PAN support and using hardware PAN +- support versus software PAN emulation is mutually exclusive at +- runtime. +- +- If unsure, say Y. ++ and BADDR are changed together in TTBRx_EL1. Since we keep the ASID ++ in TTBR1_EL1, this situation only occurs in the entry trampoline and ++ then only for entries in the walk cache, since the leaf translation ++ is unchanged. Work around the erratum by invalidating the walk cache ++ entries for the trampoline before entering the kernel proper. + + config QCOM_FALKOR_ERRATUM_1009 + bool "Falkor E1009: Prematurely complete a DSB after a TLBI" +@@ -850,6 +843,35 @@ config FORCE_MAX_ZONEORDER + However for 4K, we choose a higher default value, 11 as opposed to 10, giving us + 4M allocations matching the default size used by generic code. + ++config UNMAP_KERNEL_AT_EL0 ++ bool "Unmap kernel when running in userspace (aka \"KAISER\")" if EXPERT ++ default y ++ help ++ Speculation attacks against some high-performance processors can ++ be used to bypass MMU permission checks and leak kernel data to ++ userspace. This can be defended against by unmapping the kernel ++ when running in userspace, mapping it back in on exception entry ++ via a trampoline page in the vector table. ++ ++ If unsure, say Y. ++ ++config HARDEN_BRANCH_PREDICTOR ++ bool "Harden the branch predictor against aliasing attacks" if EXPERT ++ default y ++ help ++ Speculation attacks against some high-performance processors rely on ++ being able to manipulate the branch predictor for a victim context by ++ executing aliasing branches in the attacker context. Such attacks ++ can be partially mitigated against by clearing internal branch ++ predictor state and limiting the prediction logic in some situations. ++ ++ This config option will take CPU-specific actions to harden the ++ branch predictor against aliasing attacks and may rely on specific ++ instruction sequences or control bits being set by the system ++ firmware. ++ ++ If unsure, say Y. ++ + menuconfig ARMV8_DEPRECATED + bool "Emulate deprecated/obsolete ARMv8 instructions" + depends on COMPAT +diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts +index 52b5341cb270..62b83416b30c 100644 +--- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts ++++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts +@@ -61,6 +61,12 @@ + reg = <0x0 0x0 0x0 0x80000000>; + }; + ++ aliases { ++ ethernet0 = &cpm_eth0; ++ ethernet1 = &cpm_eth1; ++ ethernet2 = &cpm_eth2; ++ }; ++ + cpm_reg_usb3_0_vbus: cpm-usb3-0-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb3h0-vbus"; +diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts +index d97b72bed662..d9fffde64c44 100644 +--- a/arch/arm64/boot/dts/marvell/armada-8040-db.dts ++++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts +@@ -61,6 +61,13 @@ + reg = <0x0 0x0 0x0 0x80000000>; + }; + ++ aliases { ++ ethernet0 = &cpm_eth0; ++ ethernet1 = &cpm_eth2; ++ ethernet2 = &cps_eth0; ++ ethernet3 = &cps_eth1; ++ }; ++ + cpm_reg_usb3_0_vbus: cpm-usb3-0-vbus { + compatible = "regulator-fixed"; + regulator-name = "cpm-usb3h0-vbus"; +diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts +index b3350827ee55..945f7bd22802 100644 +--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts ++++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts +@@ -62,6 +62,12 @@ + reg = <0x0 0x0 0x0 0x80000000>; + }; + ++ aliases { ++ ethernet0 = &cpm_eth0; ++ ethernet1 = &cps_eth0; ++ ethernet2 = &cps_eth1; ++ }; ++ + /* Regulator labels correspond with schematics */ + v_3_3: regulator-3-3v { + compatible = "regulator-fixed"; +diff --git a/arch/arm64/crypto/crc32-ce-glue.c b/arch/arm64/crypto/crc32-ce-glue.c +index 624f4137918c..34b4e3d46aab 100644 +--- a/arch/arm64/crypto/crc32-ce-glue.c ++++ b/arch/arm64/crypto/crc32-ce-glue.c +@@ -185,6 +185,7 @@ static struct shash_alg crc32_pmull_algs[] = { { + .base.cra_name = "crc32", + .base.cra_driver_name = "crc32-arm64-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + }, { +@@ -200,6 +201,7 @@ static struct shash_alg crc32_pmull_algs[] = { { + .base.cra_name = "crc32c", + .base.cra_driver_name = "crc32c-arm64-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + } }; +diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h +index b3da6c886835..dd49c3567f20 100644 +--- a/arch/arm64/include/asm/asm-uaccess.h ++++ b/arch/arm64/include/asm/asm-uaccess.h +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include + #include + +@@ -13,51 +14,62 @@ + #ifdef CONFIG_ARM64_SW_TTBR0_PAN + .macro __uaccess_ttbr0_disable, tmp1 + mrs \tmp1, ttbr1_el1 // swapper_pg_dir ++ bic \tmp1, \tmp1, #TTBR_ASID_MASK + add \tmp1, \tmp1, #SWAPPER_DIR_SIZE // reserved_ttbr0 at the end of swapper_pg_dir + msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1 + isb ++ sub \tmp1, \tmp1, #SWAPPER_DIR_SIZE ++ msr ttbr1_el1, \tmp1 // set reserved ASID ++ isb + .endm + +- .macro __uaccess_ttbr0_enable, tmp1 ++ .macro __uaccess_ttbr0_enable, tmp1, tmp2 + get_thread_info \tmp1 + ldr \tmp1, [\tmp1, #TSK_TI_TTBR0] // load saved TTBR0_EL1 ++ mrs \tmp2, ttbr1_el1 ++ extr \tmp2, \tmp2, \tmp1, #48 ++ ror \tmp2, \tmp2, #16 ++ msr ttbr1_el1, \tmp2 // set the active ASID ++ isb + msr ttbr0_el1, \tmp1 // set the non-PAN TTBR0_EL1 + isb + .endm + +- .macro uaccess_ttbr0_disable, tmp1 ++ .macro uaccess_ttbr0_disable, tmp1, tmp2 + alternative_if_not ARM64_HAS_PAN ++ save_and_disable_irq \tmp2 // avoid preemption + __uaccess_ttbr0_disable \tmp1 ++ restore_irq \tmp2 + alternative_else_nop_endif + .endm + +- .macro uaccess_ttbr0_enable, tmp1, tmp2 ++ .macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3 + alternative_if_not ARM64_HAS_PAN +- save_and_disable_irq \tmp2 // avoid preemption +- __uaccess_ttbr0_enable \tmp1 +- restore_irq \tmp2 ++ save_and_disable_irq \tmp3 // avoid preemption ++ __uaccess_ttbr0_enable \tmp1, \tmp2 ++ restore_irq \tmp3 + alternative_else_nop_endif + .endm + #else +- .macro uaccess_ttbr0_disable, tmp1 ++ .macro uaccess_ttbr0_disable, tmp1, tmp2 + .endm + +- .macro uaccess_ttbr0_enable, tmp1, tmp2 ++ .macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3 + .endm + #endif + + /* + * These macros are no-ops when UAO is present. + */ +- .macro uaccess_disable_not_uao, tmp1 +- uaccess_ttbr0_disable \tmp1 ++ .macro uaccess_disable_not_uao, tmp1, tmp2 ++ uaccess_ttbr0_disable \tmp1, \tmp2 + alternative_if ARM64_ALT_PAN_NOT_UAO + SET_PSTATE_PAN(1) + alternative_else_nop_endif + .endm + +- .macro uaccess_enable_not_uao, tmp1, tmp2 +- uaccess_ttbr0_enable \tmp1, \tmp2 ++ .macro uaccess_enable_not_uao, tmp1, tmp2, tmp3 ++ uaccess_ttbr0_enable \tmp1, \tmp2, \tmp3 + alternative_if ARM64_ALT_PAN_NOT_UAO + SET_PSTATE_PAN(0) + alternative_else_nop_endif +diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h +index 8b168280976f..b05565dd50b6 100644 +--- a/arch/arm64/include/asm/assembler.h ++++ b/arch/arm64/include/asm/assembler.h +@@ -26,7 +26,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -109,6 +108,24 @@ + dmb \opt + .endm + ++/* ++ * Value prediction barrier ++ */ ++ .macro csdb ++ hint #20 ++ .endm ++ ++/* ++ * Sanitise a 64-bit bounded index wrt speculation, returning zero if out ++ * of bounds. ++ */ ++ .macro mask_nospec64, idx, limit, tmp ++ sub \tmp, \idx, \limit ++ bic \tmp, \tmp, \idx ++ and \idx, \idx, \tmp, asr #63 ++ csdb ++ .endm ++ + /* + * NOP sequence + */ +@@ -477,39 +494,8 @@ alternative_endif + mrs \rd, sp_el0 + .endm + +-/* +- * Errata workaround prior to TTBR0_EL1 update +- * +- * val: TTBR value with new BADDR, preserved +- * tmp0: temporary register, clobbered +- * tmp1: other temporary register, clobbered +- */ +- .macro pre_ttbr0_update_workaround, val, tmp0, tmp1 +-#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003 +-alternative_if ARM64_WORKAROUND_QCOM_FALKOR_E1003 +- mrs \tmp0, ttbr0_el1 +- mov \tmp1, #FALKOR_RESERVED_ASID +- bfi \tmp0, \tmp1, #48, #16 // reserved ASID + old BADDR +- msr ttbr0_el1, \tmp0 +- isb +- bfi \tmp0, \val, #0, #48 // reserved ASID + new BADDR +- msr ttbr0_el1, \tmp0 +- isb +-alternative_else_nop_endif +-#endif +- .endm +- +-/* +- * Errata workaround post TTBR0_EL1 update. +- */ +- .macro post_ttbr0_update_workaround +-#ifdef CONFIG_CAVIUM_ERRATUM_27456 +-alternative_if ARM64_WORKAROUND_CAVIUM_27456 +- ic iallu +- dsb nsh +- isb +-alternative_else_nop_endif +-#endif ++ .macro pte_to_phys, phys, pte ++ and \phys, \pte, #(((1 << (48 - PAGE_SHIFT)) - 1) << PAGE_SHIFT) + .endm + + /** +diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h +index 77651c49ef44..f11518af96a9 100644 +--- a/arch/arm64/include/asm/barrier.h ++++ b/arch/arm64/include/asm/barrier.h +@@ -32,6 +32,7 @@ + #define dsb(opt) asm volatile("dsb " #opt : : : "memory") + + #define psb_csync() asm volatile("hint #17" : : : "memory") ++#define csdb() asm volatile("hint #20" : : : "memory") + + #define mb() dsb(sy) + #define rmb() dsb(ld) +@@ -40,6 +41,27 @@ + #define dma_rmb() dmb(oshld) + #define dma_wmb() dmb(oshst) + ++/* ++ * Generate a mask for array_index__nospec() that is ~0UL when 0 <= idx < sz ++ * and 0 otherwise. ++ */ ++#define array_index_mask_nospec array_index_mask_nospec ++static inline unsigned long array_index_mask_nospec(unsigned long idx, ++ unsigned long sz) ++{ ++ unsigned long mask; ++ ++ asm volatile( ++ " cmp %1, %2\n" ++ " sbc %0, xzr, xzr\n" ++ : "=r" (mask) ++ : "r" (idx), "Ir" (sz) ++ : "cc"); ++ ++ csdb(); ++ return mask; ++} ++ + #define __smp_mb() dmb(ish) + #define __smp_rmb() dmb(ishld) + #define __smp_wmb() dmb(ishst) +diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h +index 2ff7c5e8efab..7049b4802587 100644 +--- a/arch/arm64/include/asm/cpucaps.h ++++ b/arch/arm64/include/asm/cpucaps.h +@@ -41,7 +41,10 @@ + #define ARM64_WORKAROUND_CAVIUM_30115 20 + #define ARM64_HAS_DCPOP 21 + #define ARM64_SVE 22 ++#define ARM64_UNMAP_KERNEL_AT_EL0 23 ++#define ARM64_HARDEN_BRANCH_PREDICTOR 24 ++#define ARM64_HARDEN_BP_POST_GUEST_EXIT 25 + +-#define ARM64_NCAPS 23 ++#define ARM64_NCAPS 26 + + #endif /* __ASM_CPUCAPS_H */ +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index cbf08d7cbf30..be7bd19c87ec 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -79,28 +79,37 @@ + #define ARM_CPU_PART_AEM_V8 0xD0F + #define ARM_CPU_PART_FOUNDATION 0xD00 + #define ARM_CPU_PART_CORTEX_A57 0xD07 ++#define ARM_CPU_PART_CORTEX_A72 0xD08 + #define ARM_CPU_PART_CORTEX_A53 0xD03 + #define ARM_CPU_PART_CORTEX_A73 0xD09 ++#define ARM_CPU_PART_CORTEX_A75 0xD0A + + #define APM_CPU_PART_POTENZA 0x000 + + #define CAVIUM_CPU_PART_THUNDERX 0x0A1 + #define CAVIUM_CPU_PART_THUNDERX_81XX 0x0A2 + #define CAVIUM_CPU_PART_THUNDERX_83XX 0x0A3 ++#define CAVIUM_CPU_PART_THUNDERX2 0x0AF + + #define BRCM_CPU_PART_VULCAN 0x516 + + #define QCOM_CPU_PART_FALKOR_V1 0x800 + #define QCOM_CPU_PART_FALKOR 0xC00 ++#define QCOM_CPU_PART_KRYO 0x200 + + #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) + #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) ++#define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) + #define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73) ++#define MIDR_CORTEX_A75 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75) + #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) + #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) + #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) ++#define MIDR_CAVIUM_THUNDERX2 MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX2) ++#define MIDR_BRCM_VULCAN MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN) + #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1) + #define MIDR_QCOM_FALKOR MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR) ++#define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO) + + #ifndef __ASSEMBLY__ + +diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h +index c4cd5081d78b..8389050328bb 100644 +--- a/arch/arm64/include/asm/efi.h ++++ b/arch/arm64/include/asm/efi.h +@@ -121,19 +121,21 @@ static inline void efi_set_pgd(struct mm_struct *mm) + if (mm != current->active_mm) { + /* + * Update the current thread's saved ttbr0 since it is +- * restored as part of a return from exception. Set +- * the hardware TTBR0_EL1 using cpu_switch_mm() +- * directly to enable potential errata workarounds. ++ * restored as part of a return from exception. Enable ++ * access to the valid TTBR0_EL1 and invoke the errata ++ * workaround directly since there is no return from ++ * exception when invoking the EFI run-time services. + */ + update_saved_ttbr0(current, mm); +- cpu_switch_mm(mm->pgd, mm); ++ uaccess_ttbr0_enable(); ++ post_ttbr_update_workaround(); + } else { + /* + * Defer the switch to the current thread's TTBR0_EL1 + * until uaccess_enable(). Restore the current + * thread's saved ttbr0 corresponding to its active_mm + */ +- cpu_set_reserved_ttbr0(); ++ uaccess_ttbr0_disable(); + update_saved_ttbr0(current, current->active_mm); + } + } +diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h +index 4052ec39e8db..ec1e6d6fa14c 100644 +--- a/arch/arm64/include/asm/fixmap.h ++++ b/arch/arm64/include/asm/fixmap.h +@@ -58,6 +58,11 @@ enum fixed_addresses { + FIX_APEI_GHES_NMI, + #endif /* CONFIG_ACPI_APEI_GHES */ + ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ FIX_ENTRY_TRAMP_DATA, ++ FIX_ENTRY_TRAMP_TEXT, ++#define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT)) ++#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + __end_of_permanent_fixed_addresses, + + /* +diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h +index 5bb2fd4674e7..07fe2479d310 100644 +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -48,9 +48,10 @@ do { \ + } while (0) + + static inline int +-arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr) + { + int oldval = 0, ret, tmp; ++ u32 __user *uaddr = __uaccess_mask_ptr(_uaddr); + + pagefault_disable(); + +@@ -88,15 +89,17 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + } + + static inline int +-futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, ++futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr, + u32 oldval, u32 newval) + { + int ret = 0; + u32 val, tmp; ++ u32 __user *uaddr; + +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) ++ if (!access_ok(VERIFY_WRITE, _uaddr, sizeof(u32))) + return -EFAULT; + ++ uaddr = __uaccess_mask_ptr(_uaddr); + uaccess_enable(); + asm volatile("// futex_atomic_cmpxchg_inatomic\n" + " prfm pstl1strm, %2\n" +diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h +index ab4d0a926043..24961b732e65 100644 +--- a/arch/arm64/include/asm/kvm_asm.h ++++ b/arch/arm64/include/asm/kvm_asm.h +@@ -68,6 +68,8 @@ extern u32 __kvm_get_mdcr_el2(void); + + extern u32 __init_stage2_translation(void); + ++extern void __qcom_hyp_sanitize_btac_predictors(void); ++ + #endif + + #endif /* __ARM_KVM_ASM_H__ */ +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index ea6cb5b24258..20cd5b514773 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -396,4 +396,9 @@ static inline void kvm_fpsimd_flush_cpu_state(void) + sve_flush_cpu_state(); + } + ++static inline bool kvm_arm_harden_branch_predictor(void) ++{ ++ return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); ++} ++ + #endif /* __ARM64_KVM_HOST_H__ */ +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index 672c8684d5c2..2d6d4bd9de52 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -309,5 +309,43 @@ static inline unsigned int kvm_get_vmid_bits(void) + return (cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR1_VMIDBITS_SHIFT) == 2) ? 16 : 8; + } + ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++#include ++ ++static inline void *kvm_get_hyp_vector(void) ++{ ++ struct bp_hardening_data *data = arm64_get_bp_hardening_data(); ++ void *vect = kvm_ksym_ref(__kvm_hyp_vector); ++ ++ if (data->fn) { ++ vect = __bp_harden_hyp_vecs_start + ++ data->hyp_vectors_slot * SZ_2K; ++ ++ if (!has_vhe()) ++ vect = lm_alias(vect); ++ } ++ ++ return vect; ++} ++ ++static inline int kvm_map_vectors(void) ++{ ++ return create_hyp_mappings(kvm_ksym_ref(__bp_harden_hyp_vecs_start), ++ kvm_ksym_ref(__bp_harden_hyp_vecs_end), ++ PAGE_HYP_EXEC); ++} ++ ++#else ++static inline void *kvm_get_hyp_vector(void) ++{ ++ return kvm_ksym_ref(__kvm_hyp_vector); ++} ++ ++static inline int kvm_map_vectors(void) ++{ ++ return 0; ++} ++#endif ++ + #endif /* __ASSEMBLY__ */ + #endif /* __ARM64_KVM_MMU_H__ */ +diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h +deleted file mode 100644 +index bc39e557c56c..000000000000 +--- a/arch/arm64/include/asm/kvm_psci.h ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* +- * Copyright (C) 2012,2013 - ARM Ltd +- * Author: Marc Zyngier +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program. If not, see . +- */ +- +-#ifndef __ARM64_KVM_PSCI_H__ +-#define __ARM64_KVM_PSCI_H__ +- +-#define KVM_ARM_PSCI_0_1 1 +-#define KVM_ARM_PSCI_0_2 2 +- +-int kvm_psci_version(struct kvm_vcpu *vcpu); +-int kvm_psci_call(struct kvm_vcpu *vcpu); +- +-#endif /* __ARM64_KVM_PSCI_H__ */ +diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h +index 0d34bf0a89c7..6dd83d75b82a 100644 +--- a/arch/arm64/include/asm/mmu.h ++++ b/arch/arm64/include/asm/mmu.h +@@ -17,6 +17,10 @@ + #define __ASM_MMU_H + + #define MMCF_AARCH32 0x1 /* mm context flag for AArch32 executables */ ++#define USER_ASID_FLAG (UL(1) << 48) ++#define TTBR_ASID_MASK (UL(0xffff) << 48) ++ ++#ifndef __ASSEMBLY__ + + typedef struct { + atomic64_t id; +@@ -31,6 +35,49 @@ typedef struct { + */ + #define ASID(mm) ((mm)->context.id.counter & 0xffff) + ++static inline bool arm64_kernel_unmapped_at_el0(void) ++{ ++ return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) && ++ cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0); ++} ++ ++typedef void (*bp_hardening_cb_t)(void); ++ ++struct bp_hardening_data { ++ int hyp_vectors_slot; ++ bp_hardening_cb_t fn; ++}; ++ ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++extern char __bp_harden_hyp_vecs_start[], __bp_harden_hyp_vecs_end[]; ++ ++DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); ++ ++static inline struct bp_hardening_data *arm64_get_bp_hardening_data(void) ++{ ++ return this_cpu_ptr(&bp_hardening_data); ++} ++ ++static inline void arm64_apply_bp_hardening(void) ++{ ++ struct bp_hardening_data *d; ++ ++ if (!cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR)) ++ return; ++ ++ d = arm64_get_bp_hardening_data(); ++ if (d->fn) ++ d->fn(); ++} ++#else ++static inline struct bp_hardening_data *arm64_get_bp_hardening_data(void) ++{ ++ return NULL; ++} ++ ++static inline void arm64_apply_bp_hardening(void) { } ++#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ ++ + extern void paging_init(void); + extern void bootmem_init(void); + extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); +@@ -41,4 +88,5 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, + extern void *fixmap_remap_fdt(phys_addr_t dt_phys); + extern void mark_linear_text_alias_ro(void); + ++#endif /* !__ASSEMBLY__ */ + #endif +diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h +index 9d155fa9a507..779d7a2ec5ec 100644 +--- a/arch/arm64/include/asm/mmu_context.h ++++ b/arch/arm64/include/asm/mmu_context.h +@@ -19,8 +19,6 @@ + #ifndef __ASM_MMU_CONTEXT_H + #define __ASM_MMU_CONTEXT_H + +-#define FALKOR_RESERVED_ASID 1 +- + #ifndef __ASSEMBLY__ + + #include +@@ -57,6 +55,13 @@ static inline void cpu_set_reserved_ttbr0(void) + isb(); + } + ++static inline void cpu_switch_mm(pgd_t *pgd, struct mm_struct *mm) ++{ ++ BUG_ON(pgd == swapper_pg_dir); ++ cpu_set_reserved_ttbr0(); ++ cpu_do_switch_mm(virt_to_phys(pgd),mm); ++} ++ + /* + * TCR.T0SZ value to use when the ID map is active. Usually equals + * TCR_T0SZ(VA_BITS), unless system RAM is positioned very high in +@@ -170,7 +175,7 @@ static inline void update_saved_ttbr0(struct task_struct *tsk, + else + ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48; + +- task_thread_info(tsk)->ttbr0 = ttbr; ++ WRITE_ONCE(task_thread_info(tsk)->ttbr0, ttbr); + } + #else + static inline void update_saved_ttbr0(struct task_struct *tsk, +@@ -225,6 +230,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, + #define activate_mm(prev,next) switch_mm(prev, next, current) + + void verify_cpu_asid_bits(void); ++void post_ttbr_update_workaround(void); + + #endif /* !__ASSEMBLY__ */ + +diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h +index eb0c2bd90de9..8df4cb6ac6f7 100644 +--- a/arch/arm64/include/asm/pgtable-hwdef.h ++++ b/arch/arm64/include/asm/pgtable-hwdef.h +@@ -272,6 +272,7 @@ + #define TCR_TG1_4K (UL(2) << TCR_TG1_SHIFT) + #define TCR_TG1_64K (UL(3) << TCR_TG1_SHIFT) + ++#define TCR_A1 (UL(1) << 22) + #define TCR_ASID16 (UL(1) << 36) + #define TCR_TBI0 (UL(1) << 37) + #define TCR_HA (UL(1) << 39) +diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h +index 0a5635fb0ef9..2db84df5eb42 100644 +--- a/arch/arm64/include/asm/pgtable-prot.h ++++ b/arch/arm64/include/asm/pgtable-prot.h +@@ -34,8 +34,14 @@ + + #include + +-#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) +-#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) ++#define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) ++#define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) ++ ++#define PTE_MAYBE_NG (arm64_kernel_unmapped_at_el0() ? PTE_NG : 0) ++#define PMD_MAYBE_NG (arm64_kernel_unmapped_at_el0() ? PMD_SECT_NG : 0) ++ ++#define PROT_DEFAULT (_PROT_DEFAULT | PTE_MAYBE_NG) ++#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_MAYBE_NG) + + #define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) + #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) +@@ -47,23 +53,24 @@ + #define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) + #define PROT_SECT_NORMAL_EXEC (PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) + +-#define _PAGE_DEFAULT (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) ++#define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) ++#define _HYP_PAGE_DEFAULT _PAGE_DEFAULT + +-#define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) +-#define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY) +-#define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY) +-#define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) +-#define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT) ++#define PAGE_KERNEL __pgprot(PROT_NORMAL) ++#define PAGE_KERNEL_RO __pgprot((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) ++#define PAGE_KERNEL_ROX __pgprot((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY) ++#define PAGE_KERNEL_EXEC __pgprot(PROT_NORMAL & ~PTE_PXN) ++#define PAGE_KERNEL_EXEC_CONT __pgprot((PROT_NORMAL & ~PTE_PXN) | PTE_CONT) + +-#define PAGE_HYP __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_HYP_XN) +-#define PAGE_HYP_EXEC __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY) +-#define PAGE_HYP_RO __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | PTE_HYP_XN) ++#define PAGE_HYP __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_HYP_XN) ++#define PAGE_HYP_EXEC __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY) ++#define PAGE_HYP_RO __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | PTE_HYP_XN) + #define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP) + +-#define PAGE_S2 __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) +-#define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN) ++#define PAGE_S2 __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) ++#define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN) + +-#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN) ++#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) + #define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) + #define PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE) + #define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index bdcc7f1c9d06..e74394e7b4a6 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -683,6 +683,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, + + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; ++extern pgd_t tramp_pg_dir[PTRS_PER_PGD]; + + /* + * Encode and decode a swap entry: +diff --git a/arch/arm64/include/asm/proc-fns.h b/arch/arm64/include/asm/proc-fns.h +index 14ad6e4e87d1..16cef2e8449e 100644 +--- a/arch/arm64/include/asm/proc-fns.h ++++ b/arch/arm64/include/asm/proc-fns.h +@@ -35,12 +35,6 @@ extern u64 cpu_do_resume(phys_addr_t ptr, u64 idmap_ttbr); + + #include + +-#define cpu_switch_mm(pgd,mm) \ +-do { \ +- BUG_ON(pgd == swapper_pg_dir); \ +- cpu_do_switch_mm(virt_to_phys(pgd),mm); \ +-} while (0) +- + #endif /* __ASSEMBLY__ */ + #endif /* __KERNEL__ */ + #endif /* __ASM_PROCFNS_H */ +diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h +index 023cacb946c3..f96a13556887 100644 +--- a/arch/arm64/include/asm/processor.h ++++ b/arch/arm64/include/asm/processor.h +@@ -21,6 +21,9 @@ + + #define TASK_SIZE_64 (UL(1) << VA_BITS) + ++#define KERNEL_DS UL(-1) ++#define USER_DS (TASK_SIZE_64 - 1) ++ + #ifndef __ASSEMBLY__ + + /* +diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h +index 08cc88574659..871744973ece 100644 +--- a/arch/arm64/include/asm/sysreg.h ++++ b/arch/arm64/include/asm/sysreg.h +@@ -437,6 +437,8 @@ + #define ID_AA64ISAR1_DPB_SHIFT 0 + + /* id_aa64pfr0 */ ++#define ID_AA64PFR0_CSV3_SHIFT 60 ++#define ID_AA64PFR0_CSV2_SHIFT 56 + #define ID_AA64PFR0_SVE_SHIFT 32 + #define ID_AA64PFR0_GIC_SHIFT 24 + #define ID_AA64PFR0_ASIMD_SHIFT 20 +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index af1c76981911..9e82dd79c7db 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -23,6 +23,7 @@ + + #include + #include ++#include + + /* + * Raw TLBI operations. +@@ -54,6 +55,11 @@ + + #define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0) + ++#define __tlbi_user(op, arg) do { \ ++ if (arm64_kernel_unmapped_at_el0()) \ ++ __tlbi(op, (arg) | USER_ASID_FLAG); \ ++} while (0) ++ + /* + * TLB Management + * ============== +@@ -115,6 +121,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm) + + dsb(ishst); + __tlbi(aside1is, asid); ++ __tlbi_user(aside1is, asid); + dsb(ish); + } + +@@ -125,6 +132,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, + + dsb(ishst); + __tlbi(vale1is, addr); ++ __tlbi_user(vale1is, addr); + dsb(ish); + } + +@@ -151,10 +159,13 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, + + dsb(ishst); + for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { +- if (last_level) ++ if (last_level) { + __tlbi(vale1is, addr); +- else ++ __tlbi_user(vale1is, addr); ++ } else { + __tlbi(vae1is, addr); ++ __tlbi_user(vae1is, addr); ++ } + } + dsb(ish); + } +@@ -194,6 +205,7 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm, + unsigned long addr = uaddr >> 12 | (ASID(mm) << 48); + + __tlbi(vae1is, addr); ++ __tlbi_user(vae1is, addr); + dsb(ish); + } + +diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h +index fc0f9eb66039..fad8c1b2ca3e 100644 +--- a/arch/arm64/include/asm/uaccess.h ++++ b/arch/arm64/include/asm/uaccess.h +@@ -35,16 +35,20 @@ + #include + #include + +-#define KERNEL_DS (-1UL) + #define get_ds() (KERNEL_DS) +- +-#define USER_DS TASK_SIZE_64 + #define get_fs() (current_thread_info()->addr_limit) + + static inline void set_fs(mm_segment_t fs) + { + current_thread_info()->addr_limit = fs; + ++ /* ++ * Prevent a mispredicted conditional call to set_fs from forwarding ++ * the wrong address limit to access_ok under speculation. ++ */ ++ dsb(nsh); ++ isb(); ++ + /* On user-mode return, check fs is correct */ + set_thread_flag(TIF_FSCHECK); + +@@ -66,22 +70,32 @@ static inline void set_fs(mm_segment_t fs) + * Returns 1 if the range is valid, 0 otherwise. + * + * This is equivalent to the following test: +- * (u65)addr + (u65)size <= current->addr_limit +- * +- * This needs 65-bit arithmetic. ++ * (u65)addr + (u65)size <= (u65)current->addr_limit + 1 + */ +-#define __range_ok(addr, size) \ +-({ \ +- unsigned long __addr = (unsigned long)(addr); \ +- unsigned long flag, roksum; \ +- __chk_user_ptr(addr); \ +- asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \ +- : "=&r" (flag), "=&r" (roksum) \ +- : "1" (__addr), "Ir" (size), \ +- "r" (current_thread_info()->addr_limit) \ +- : "cc"); \ +- flag; \ +-}) ++static inline unsigned long __range_ok(unsigned long addr, unsigned long size) ++{ ++ unsigned long limit = current_thread_info()->addr_limit; ++ ++ __chk_user_ptr(addr); ++ asm volatile( ++ // A + B <= C + 1 for all A,B,C, in four easy steps: ++ // 1: X = A + B; X' = X % 2^64 ++ " adds %0, %0, %2\n" ++ // 2: Set C = 0 if X > 2^64, to guarantee X' > C in step 4 ++ " csel %1, xzr, %1, hi\n" ++ // 3: Set X' = ~0 if X >= 2^64. For X == 2^64, this decrements X' ++ // to compensate for the carry flag being set in step 4. For ++ // X > 2^64, X' merely has to remain nonzero, which it does. ++ " csinv %0, %0, xzr, cc\n" ++ // 4: For X < 2^64, this gives us X' - C - 1 <= 0, where the -1 ++ // comes from the carry in being clear. Otherwise, we are ++ // testing X' - C == 0, subject to the previous adjustments. ++ " sbcs xzr, %0, %1\n" ++ " cset %0, ls\n" ++ : "+r" (addr), "+r" (limit) : "Ir" (size) : "cc"); ++ ++ return addr; ++} + + /* + * When dealing with data aborts, watchpoints, or instruction traps we may end +@@ -90,7 +104,7 @@ static inline void set_fs(mm_segment_t fs) + */ + #define untagged_addr(addr) sign_extend64(addr, 55) + +-#define access_ok(type, addr, size) __range_ok(addr, size) ++#define access_ok(type, addr, size) __range_ok((unsigned long)(addr), size) + #define user_addr_max get_fs + + #define _ASM_EXTABLE(from, to) \ +@@ -105,17 +119,23 @@ static inline void set_fs(mm_segment_t fs) + #ifdef CONFIG_ARM64_SW_TTBR0_PAN + static inline void __uaccess_ttbr0_disable(void) + { +- unsigned long ttbr; ++ unsigned long flags, ttbr; + ++ local_irq_save(flags); ++ ttbr = read_sysreg(ttbr1_el1); ++ ttbr &= ~TTBR_ASID_MASK; + /* reserved_ttbr0 placed at the end of swapper_pg_dir */ +- ttbr = read_sysreg(ttbr1_el1) + SWAPPER_DIR_SIZE; +- write_sysreg(ttbr, ttbr0_el1); ++ write_sysreg(ttbr + SWAPPER_DIR_SIZE, ttbr0_el1); + isb(); ++ /* Set reserved ASID */ ++ write_sysreg(ttbr, ttbr1_el1); ++ isb(); ++ local_irq_restore(flags); + } + + static inline void __uaccess_ttbr0_enable(void) + { +- unsigned long flags; ++ unsigned long flags, ttbr0, ttbr1; + + /* + * Disable interrupts to avoid preemption between reading the 'ttbr0' +@@ -123,7 +143,17 @@ static inline void __uaccess_ttbr0_enable(void) + * roll-over and an update of 'ttbr0'. + */ + local_irq_save(flags); +- write_sysreg(current_thread_info()->ttbr0, ttbr0_el1); ++ ttbr0 = READ_ONCE(current_thread_info()->ttbr0); ++ ++ /* Restore active ASID */ ++ ttbr1 = read_sysreg(ttbr1_el1); ++ ttbr1 &= ~TTBR_ASID_MASK; /* safety measure */ ++ ttbr1 |= ttbr0 & TTBR_ASID_MASK; ++ write_sysreg(ttbr1, ttbr1_el1); ++ isb(); ++ ++ /* Restore user page table */ ++ write_sysreg(ttbr0, ttbr0_el1); + isb(); + local_irq_restore(flags); + } +@@ -192,6 +222,26 @@ static inline void uaccess_enable_not_uao(void) + __uaccess_enable(ARM64_ALT_PAN_NOT_UAO); + } + ++/* ++ * Sanitise a uaccess pointer such that it becomes NULL if above the ++ * current addr_limit. ++ */ ++#define uaccess_mask_ptr(ptr) (__typeof__(ptr))__uaccess_mask_ptr(ptr) ++static inline void __user *__uaccess_mask_ptr(const void __user *ptr) ++{ ++ void __user *safe_ptr; ++ ++ asm volatile( ++ " bics xzr, %1, %2\n" ++ " csel %0, %1, xzr, eq\n" ++ : "=&r" (safe_ptr) ++ : "r" (ptr), "r" (current_thread_info()->addr_limit) ++ : "cc"); ++ ++ csdb(); ++ return safe_ptr; ++} ++ + /* + * The "__xxx" versions of the user access functions do not verify the address + * space - it must have been done previously with a separate "access_ok()" +@@ -244,28 +294,33 @@ do { \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ + } while (0) + +-#define __get_user(x, ptr) \ ++#define __get_user_check(x, ptr, err) \ + ({ \ +- int __gu_err = 0; \ +- __get_user_err((x), (ptr), __gu_err); \ +- __gu_err; \ ++ __typeof__(*(ptr)) __user *__p = (ptr); \ ++ might_fault(); \ ++ if (access_ok(VERIFY_READ, __p, sizeof(*__p))) { \ ++ __p = uaccess_mask_ptr(__p); \ ++ __get_user_err((x), __p, (err)); \ ++ } else { \ ++ (x) = 0; (err) = -EFAULT; \ ++ } \ + }) + + #define __get_user_error(x, ptr, err) \ + ({ \ +- __get_user_err((x), (ptr), (err)); \ ++ __get_user_check((x), (ptr), (err)); \ + (void)0; \ + }) + +-#define get_user(x, ptr) \ ++#define __get_user(x, ptr) \ + ({ \ +- __typeof__(*(ptr)) __user *__p = (ptr); \ +- might_fault(); \ +- access_ok(VERIFY_READ, __p, sizeof(*__p)) ? \ +- __get_user((x), __p) : \ +- ((x) = 0, -EFAULT); \ ++ int __gu_err = 0; \ ++ __get_user_check((x), (ptr), __gu_err); \ ++ __gu_err; \ + }) + ++#define get_user __get_user ++ + #define __put_user_asm(instr, alt_instr, reg, x, addr, err, feature) \ + asm volatile( \ + "1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \ +@@ -308,43 +363,63 @@ do { \ + uaccess_disable_not_uao(); \ + } while (0) + +-#define __put_user(x, ptr) \ ++#define __put_user_check(x, ptr, err) \ + ({ \ +- int __pu_err = 0; \ +- __put_user_err((x), (ptr), __pu_err); \ +- __pu_err; \ ++ __typeof__(*(ptr)) __user *__p = (ptr); \ ++ might_fault(); \ ++ if (access_ok(VERIFY_WRITE, __p, sizeof(*__p))) { \ ++ __p = uaccess_mask_ptr(__p); \ ++ __put_user_err((x), __p, (err)); \ ++ } else { \ ++ (err) = -EFAULT; \ ++ } \ + }) + + #define __put_user_error(x, ptr, err) \ + ({ \ +- __put_user_err((x), (ptr), (err)); \ ++ __put_user_check((x), (ptr), (err)); \ + (void)0; \ + }) + +-#define put_user(x, ptr) \ ++#define __put_user(x, ptr) \ + ({ \ +- __typeof__(*(ptr)) __user *__p = (ptr); \ +- might_fault(); \ +- access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ? \ +- __put_user((x), __p) : \ +- -EFAULT; \ ++ int __pu_err = 0; \ ++ __put_user_check((x), (ptr), __pu_err); \ ++ __pu_err; \ + }) + ++#define put_user __put_user ++ + extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n); +-#define raw_copy_from_user __arch_copy_from_user ++#define raw_copy_from_user(to, from, n) \ ++({ \ ++ __arch_copy_from_user((to), __uaccess_mask_ptr(from), (n)); \ ++}) ++ + extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n); +-#define raw_copy_to_user __arch_copy_to_user +-extern unsigned long __must_check raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); +-extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); ++#define raw_copy_to_user(to, from, n) \ ++({ \ ++ __arch_copy_to_user(__uaccess_mask_ptr(to), (from), (n)); \ ++}) ++ ++extern unsigned long __must_check __arch_copy_in_user(void __user *to, const void __user *from, unsigned long n); ++#define raw_copy_in_user(to, from, n) \ ++({ \ ++ __arch_copy_in_user(__uaccess_mask_ptr(to), \ ++ __uaccess_mask_ptr(from), (n)); \ ++}) ++ + #define INLINE_COPY_TO_USER + #define INLINE_COPY_FROM_USER + +-static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) ++extern unsigned long __must_check __arch_clear_user(void __user *to, unsigned long n); ++static inline unsigned long __must_check __clear_user(void __user *to, unsigned long n) + { + if (access_ok(VERIFY_WRITE, to, n)) +- n = __clear_user(to, n); ++ n = __arch_clear_user(__uaccess_mask_ptr(to), n); + return n; + } ++#define clear_user __clear_user + + extern long strncpy_from_user(char *dest, const char __user *src, long count); + +@@ -358,7 +433,7 @@ extern unsigned long __must_check __copy_user_flushcache(void *to, const void __ + static inline int __copy_from_user_flushcache(void *dst, const void __user *src, unsigned size) + { + kasan_check_write(dst, size); +- return __copy_user_flushcache(dst, src, size); ++ return __copy_user_flushcache(dst, __uaccess_mask_ptr(src), size); + } + #endif + +diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile +index 067baace74a0..0c760db04858 100644 +--- a/arch/arm64/kernel/Makefile ++++ b/arch/arm64/kernel/Makefile +@@ -53,6 +53,10 @@ arm64-obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o + arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o + arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o + ++ifeq ($(CONFIG_KVM),y) ++arm64-obj-$(CONFIG_HARDEN_BRANCH_PREDICTOR) += bpi.o ++endif ++ + obj-y += $(arm64-obj-y) vdso/ probes/ + obj-m += $(arm64-obj-m) + head-y := head.o +diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c +index 67368c7329c0..66be504edb6c 100644 +--- a/arch/arm64/kernel/arm64ksyms.c ++++ b/arch/arm64/kernel/arm64ksyms.c +@@ -37,8 +37,8 @@ EXPORT_SYMBOL(clear_page); + /* user mem (segment) */ + EXPORT_SYMBOL(__arch_copy_from_user); + EXPORT_SYMBOL(__arch_copy_to_user); +-EXPORT_SYMBOL(__clear_user); +-EXPORT_SYMBOL(raw_copy_in_user); ++EXPORT_SYMBOL(__arch_clear_user); ++EXPORT_SYMBOL(__arch_copy_in_user); + + /* physical memory */ + EXPORT_SYMBOL(memstart_addr); +diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c +index 71bf088f1e4b..af247d10252f 100644 +--- a/arch/arm64/kernel/asm-offsets.c ++++ b/arch/arm64/kernel/asm-offsets.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -148,11 +149,14 @@ int main(void) + DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); + DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id)); + DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state)); +- + BLANK(); + DEFINE(HIBERN_PBE_ORIG, offsetof(struct pbe, orig_address)); + DEFINE(HIBERN_PBE_ADDR, offsetof(struct pbe, address)); + DEFINE(HIBERN_PBE_NEXT, offsetof(struct pbe, next)); + DEFINE(ARM64_FTR_SYSVAL, offsetof(struct arm64_ftr_reg, sys_val)); ++ BLANK(); ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ DEFINE(TRAMP_VALIAS, TRAMP_VALIAS); ++#endif + return 0; + } +diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S +new file mode 100644 +index 000000000000..e5de33513b5d +--- /dev/null ++++ b/arch/arm64/kernel/bpi.S +@@ -0,0 +1,83 @@ ++/* ++ * Contains CPU specific branch predictor invalidation sequences ++ * ++ * Copyright (C) 2018 ARM Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include ++#include ++ ++.macro ventry target ++ .rept 31 ++ nop ++ .endr ++ b \target ++.endm ++ ++.macro vectors target ++ ventry \target + 0x000 ++ ventry \target + 0x080 ++ ventry \target + 0x100 ++ ventry \target + 0x180 ++ ++ ventry \target + 0x200 ++ ventry \target + 0x280 ++ ventry \target + 0x300 ++ ventry \target + 0x380 ++ ++ ventry \target + 0x400 ++ ventry \target + 0x480 ++ ventry \target + 0x500 ++ ventry \target + 0x580 ++ ++ ventry \target + 0x600 ++ ventry \target + 0x680 ++ ventry \target + 0x700 ++ ventry \target + 0x780 ++.endm ++ ++ .align 11 ++ENTRY(__bp_harden_hyp_vecs_start) ++ .rept 4 ++ vectors __kvm_hyp_vector ++ .endr ++ENTRY(__bp_harden_hyp_vecs_end) ++ ++ENTRY(__qcom_hyp_sanitize_link_stack_start) ++ stp x29, x30, [sp, #-16]! ++ .rept 16 ++ bl . + 4 ++ .endr ++ ldp x29, x30, [sp], #16 ++ENTRY(__qcom_hyp_sanitize_link_stack_end) ++ ++.macro smccc_workaround_1 inst ++ sub sp, sp, #(8 * 4) ++ stp x2, x3, [sp, #(8 * 0)] ++ stp x0, x1, [sp, #(8 * 2)] ++ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 ++ \inst #0 ++ ldp x2, x3, [sp, #(8 * 0)] ++ ldp x0, x1, [sp, #(8 * 2)] ++ add sp, sp, #(8 * 4) ++.endm ++ ++ENTRY(__smccc_workaround_1_smc_start) ++ smccc_workaround_1 smc ++ENTRY(__smccc_workaround_1_smc_end) ++ ++ENTRY(__smccc_workaround_1_hvc_start) ++ smccc_workaround_1 hvc ++ENTRY(__smccc_workaround_1_hvc_end) +diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S +index 2a752cb2a0f3..8021b46c9743 100644 +--- a/arch/arm64/kernel/cpu-reset.S ++++ b/arch/arm64/kernel/cpu-reset.S +@@ -16,7 +16,7 @@ + #include + + .text +-.pushsection .idmap.text, "ax" ++.pushsection .idmap.text, "awx" + + /* + * __cpu_soft_restart(el2_switch, entry, arg0, arg1, arg2) - Helper for +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index 0e27f86ee709..07823595b7f0 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -30,6 +30,20 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope) + entry->midr_range_max); + } + ++static bool __maybe_unused ++is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope) ++{ ++ u32 model; ++ ++ WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); ++ ++ model = read_cpuid_id(); ++ model &= MIDR_IMPLEMENTOR_MASK | (0xf00 << MIDR_PARTNUM_SHIFT) | ++ MIDR_ARCHITECTURE_MASK; ++ ++ return model == entry->midr_model; ++} ++ + static bool + has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry, + int scope) +@@ -46,6 +60,174 @@ static int cpu_enable_trap_ctr_access(void *__unused) + return 0; + } + ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++#include ++#include ++ ++DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); ++ ++#ifdef CONFIG_KVM ++extern char __qcom_hyp_sanitize_link_stack_start[]; ++extern char __qcom_hyp_sanitize_link_stack_end[]; ++extern char __smccc_workaround_1_smc_start[]; ++extern char __smccc_workaround_1_smc_end[]; ++extern char __smccc_workaround_1_hvc_start[]; ++extern char __smccc_workaround_1_hvc_end[]; ++ ++static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, ++ const char *hyp_vecs_end) ++{ ++ void *dst = lm_alias(__bp_harden_hyp_vecs_start + slot * SZ_2K); ++ int i; ++ ++ for (i = 0; i < SZ_2K; i += 0x80) ++ memcpy(dst + i, hyp_vecs_start, hyp_vecs_end - hyp_vecs_start); ++ ++ flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K); ++} ++ ++static void __install_bp_hardening_cb(bp_hardening_cb_t fn, ++ const char *hyp_vecs_start, ++ const char *hyp_vecs_end) ++{ ++ static int last_slot = -1; ++ static DEFINE_SPINLOCK(bp_lock); ++ int cpu, slot = -1; ++ ++ spin_lock(&bp_lock); ++ for_each_possible_cpu(cpu) { ++ if (per_cpu(bp_hardening_data.fn, cpu) == fn) { ++ slot = per_cpu(bp_hardening_data.hyp_vectors_slot, cpu); ++ break; ++ } ++ } ++ ++ if (slot == -1) { ++ last_slot++; ++ BUG_ON(((__bp_harden_hyp_vecs_end - __bp_harden_hyp_vecs_start) ++ / SZ_2K) <= last_slot); ++ slot = last_slot; ++ __copy_hyp_vect_bpi(slot, hyp_vecs_start, hyp_vecs_end); ++ } ++ ++ __this_cpu_write(bp_hardening_data.hyp_vectors_slot, slot); ++ __this_cpu_write(bp_hardening_data.fn, fn); ++ spin_unlock(&bp_lock); ++} ++#else ++#define __qcom_hyp_sanitize_link_stack_start NULL ++#define __qcom_hyp_sanitize_link_stack_end NULL ++#define __smccc_workaround_1_smc_start NULL ++#define __smccc_workaround_1_smc_end NULL ++#define __smccc_workaround_1_hvc_start NULL ++#define __smccc_workaround_1_hvc_end NULL ++ ++static void __install_bp_hardening_cb(bp_hardening_cb_t fn, ++ const char *hyp_vecs_start, ++ const char *hyp_vecs_end) ++{ ++ __this_cpu_write(bp_hardening_data.fn, fn); ++} ++#endif /* CONFIG_KVM */ ++ ++static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, ++ bp_hardening_cb_t fn, ++ const char *hyp_vecs_start, ++ const char *hyp_vecs_end) ++{ ++ u64 pfr0; ++ ++ if (!entry->matches(entry, SCOPE_LOCAL_CPU)) ++ return; ++ ++ pfr0 = read_cpuid(ID_AA64PFR0_EL1); ++ if (cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_CSV2_SHIFT)) ++ return; ++ ++ __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end); ++} ++ ++#include ++#include ++#include ++ ++static void call_smc_arch_workaround_1(void) ++{ ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); ++} ++ ++static void call_hvc_arch_workaround_1(void) ++{ ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); ++} ++ ++static int enable_smccc_arch_workaround_1(void *data) ++{ ++ const struct arm64_cpu_capabilities *entry = data; ++ bp_hardening_cb_t cb; ++ void *smccc_start, *smccc_end; ++ struct arm_smccc_res res; ++ ++ if (!entry->matches(entry, SCOPE_LOCAL_CPU)) ++ return 0; ++ ++ if (psci_ops.smccc_version == SMCCC_VERSION_1_0) ++ return 0; ++ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_1, &res); ++ if (res.a0) ++ return 0; ++ cb = call_hvc_arch_workaround_1; ++ smccc_start = __smccc_workaround_1_hvc_start; ++ smccc_end = __smccc_workaround_1_hvc_end; ++ break; ++ ++ case PSCI_CONDUIT_SMC: ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_1, &res); ++ if (res.a0) ++ return 0; ++ cb = call_smc_arch_workaround_1; ++ smccc_start = __smccc_workaround_1_smc_start; ++ smccc_end = __smccc_workaround_1_smc_end; ++ break; ++ ++ default: ++ return 0; ++ } ++ ++ install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); ++ ++ return 0; ++} ++ ++static void qcom_link_stack_sanitization(void) ++{ ++ u64 tmp; ++ ++ asm volatile("mov %0, x30 \n" ++ ".rept 16 \n" ++ "bl . + 4 \n" ++ ".endr \n" ++ "mov x30, %0 \n" ++ : "=&r" (tmp)); ++} ++ ++static int qcom_enable_link_stack_sanitization(void *data) ++{ ++ const struct arm64_cpu_capabilities *entry = data; ++ ++ install_bp_hardening_cb(entry, qcom_link_stack_sanitization, ++ __qcom_hyp_sanitize_link_stack_start, ++ __qcom_hyp_sanitize_link_stack_end); ++ ++ return 0; ++} ++#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ ++ + #define MIDR_RANGE(model, min, max) \ + .def_scope = SCOPE_LOCAL_CPU, \ + .matches = is_affected_midr_range, \ +@@ -169,6 +351,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + MIDR_CPU_VAR_REV(0, 0), + MIDR_CPU_VAR_REV(0, 0)), + }, ++ { ++ .desc = "Qualcomm Technologies Kryo erratum 1003", ++ .capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003, ++ .def_scope = SCOPE_LOCAL_CPU, ++ .midr_model = MIDR_QCOM_KRYO, ++ .matches = is_kryo_midr, ++ }, + #endif + #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009 + { +@@ -186,6 +375,47 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + .capability = ARM64_WORKAROUND_858921, + MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), + }, ++#endif ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ { ++ .capability = ARM64_HARDEN_BRANCH_PREDICTOR, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), ++ .enable = enable_smccc_arch_workaround_1, ++ }, ++ { ++ .capability = ARM64_HARDEN_BRANCH_PREDICTOR, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), ++ .enable = enable_smccc_arch_workaround_1, ++ }, ++ { ++ .capability = ARM64_HARDEN_BRANCH_PREDICTOR, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), ++ .enable = enable_smccc_arch_workaround_1, ++ }, ++ { ++ .capability = ARM64_HARDEN_BRANCH_PREDICTOR, ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), ++ .enable = enable_smccc_arch_workaround_1, ++ }, ++ { ++ .capability = ARM64_HARDEN_BRANCH_PREDICTOR, ++ MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1), ++ .enable = qcom_enable_link_stack_sanitization, ++ }, ++ { ++ .capability = ARM64_HARDEN_BP_POST_GUEST_EXIT, ++ MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1), ++ }, ++ { ++ .capability = ARM64_HARDEN_BRANCH_PREDICTOR, ++ MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), ++ .enable = enable_smccc_arch_workaround_1, ++ }, ++ { ++ .capability = ARM64_HARDEN_BRANCH_PREDICTOR, ++ MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), ++ .enable = enable_smccc_arch_workaround_1, ++ }, + #endif + { + } +@@ -200,15 +430,18 @@ void verify_local_cpu_errata_workarounds(void) + { + const struct arm64_cpu_capabilities *caps = arm64_errata; + +- for (; caps->matches; caps++) +- if (!cpus_have_cap(caps->capability) && +- caps->matches(caps, SCOPE_LOCAL_CPU)) { ++ for (; caps->matches; caps++) { ++ if (cpus_have_cap(caps->capability)) { ++ if (caps->enable) ++ caps->enable((void *)caps); ++ } else if (caps->matches(caps, SCOPE_LOCAL_CPU)) { + pr_crit("CPU%d: Requires work around for %s, not detected" + " at boot time\n", + smp_processor_id(), + caps->desc ? : "an erratum"); + cpu_die_early(); + } ++ } + } + + void update_cpu_errata_workarounds(void) +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index a73a5928f09b..46dee071bab1 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -145,6 +145,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { + }; + + static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { ++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0), ++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), + FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0), +@@ -846,6 +848,86 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus + ID_AA64PFR0_FP_SHIFT) < 0; + } + ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */ ++ ++static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, ++ int __unused) ++{ ++ char const *str = "command line option"; ++ u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); ++ ++ /* ++ * For reasons that aren't entirely clear, enabling KPTI on Cavium ++ * ThunderX leads to apparent I-cache corruption of kernel text, which ++ * ends as well as you might imagine. Don't even try. ++ */ ++ if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_27456)) { ++ str = "ARM64_WORKAROUND_CAVIUM_27456"; ++ __kpti_forced = -1; ++ } ++ ++ /* Forced? */ ++ if (__kpti_forced) { ++ pr_info_once("kernel page table isolation forced %s by %s\n", ++ __kpti_forced > 0 ? "ON" : "OFF", str); ++ return __kpti_forced > 0; ++ } ++ ++ /* Useful for KASLR robustness */ ++ if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) ++ return true; ++ ++ /* Don't force KPTI for CPUs that are not vulnerable */ ++ switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) { ++ case MIDR_CAVIUM_THUNDERX2: ++ case MIDR_BRCM_VULCAN: ++ return false; ++ } ++ ++ /* Defer to CPU feature registers */ ++ return !cpuid_feature_extract_unsigned_field(pfr0, ++ ID_AA64PFR0_CSV3_SHIFT); ++} ++ ++static int kpti_install_ng_mappings(void *__unused) ++{ ++ typedef void (kpti_remap_fn)(int, int, phys_addr_t); ++ extern kpti_remap_fn idmap_kpti_install_ng_mappings; ++ kpti_remap_fn *remap_fn; ++ ++ static bool kpti_applied = false; ++ int cpu = smp_processor_id(); ++ ++ if (kpti_applied) ++ return 0; ++ ++ remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings); ++ ++ cpu_install_idmap(); ++ remap_fn(cpu, num_online_cpus(), __pa_symbol(swapper_pg_dir)); ++ cpu_uninstall_idmap(); ++ ++ if (!cpu) ++ kpti_applied = true; ++ ++ return 0; ++} ++ ++static int __init parse_kpti(char *str) ++{ ++ bool enabled; ++ int ret = strtobool(str, &enabled); ++ ++ if (ret) ++ return ret; ++ ++ __kpti_forced = enabled ? 1 : -1; ++ return 0; ++} ++__setup("kpti=", parse_kpti); ++#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ ++ + static const struct arm64_cpu_capabilities arm64_features[] = { + { + .desc = "GIC system register CPU interface", +@@ -932,6 +1014,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = { + .def_scope = SCOPE_SYSTEM, + .matches = hyp_offset_low, + }, ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ { ++ .desc = "Kernel page table isolation (KPTI)", ++ .capability = ARM64_UNMAP_KERNEL_AT_EL0, ++ .def_scope = SCOPE_SYSTEM, ++ .matches = unmap_kernel_at_el0, ++ .enable = kpti_install_ng_mappings, ++ }, ++#endif + { + /* FP/SIMD is not implemented */ + .capability = ARM64_HAS_NO_FPSIMD, +@@ -1071,6 +1162,25 @@ static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps) + cap_set_elf_hwcap(hwcaps); + } + ++/* ++ * Check if the current CPU has a given feature capability. ++ * Should be called from non-preemptible context. ++ */ ++static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array, ++ unsigned int cap) ++{ ++ const struct arm64_cpu_capabilities *caps; ++ ++ if (WARN_ON(preemptible())) ++ return false; ++ ++ for (caps = cap_array; caps->matches; caps++) ++ if (caps->capability == cap && ++ caps->matches(caps, SCOPE_LOCAL_CPU)) ++ return true; ++ return false; ++} ++ + void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, + const char *info) + { +@@ -1106,7 +1216,7 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) + * uses an IPI, giving us a PSTATE that disappears when + * we return. + */ +- stop_machine(caps->enable, NULL, cpu_online_mask); ++ stop_machine(caps->enable, (void *)caps, cpu_online_mask); + } + } + } +@@ -1134,8 +1244,9 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps) + } + + static void +-verify_local_cpu_features(const struct arm64_cpu_capabilities *caps) ++verify_local_cpu_features(const struct arm64_cpu_capabilities *caps_list) + { ++ const struct arm64_cpu_capabilities *caps = caps_list; + for (; caps->matches; caps++) { + if (!cpus_have_cap(caps->capability)) + continue; +@@ -1143,13 +1254,13 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps) + * If the new CPU misses an advertised feature, we cannot proceed + * further, park the cpu. + */ +- if (!caps->matches(caps, SCOPE_LOCAL_CPU)) { ++ if (!__this_cpu_has_cap(caps_list, caps->capability)) { + pr_crit("CPU%d: missing feature: %s\n", + smp_processor_id(), caps->desc); + cpu_die_early(); + } + if (caps->enable) +- caps->enable(NULL); ++ caps->enable((void *)caps); + } + } + +@@ -1225,25 +1336,6 @@ static void __init mark_const_caps_ready(void) + static_branch_enable(&arm64_const_caps_ready); + } + +-/* +- * Check if the current CPU has a given feature capability. +- * Should be called from non-preemptible context. +- */ +-static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array, +- unsigned int cap) +-{ +- const struct arm64_cpu_capabilities *caps; +- +- if (WARN_ON(preemptible())) +- return false; +- +- for (caps = cap_array; caps->desc; caps++) +- if (caps->capability == cap && caps->matches) +- return caps->matches(caps, SCOPE_LOCAL_CPU); +- +- return false; +-} +- + extern const struct arm64_cpu_capabilities arm64_errata[]; + + bool this_cpu_has_cap(unsigned int cap) +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index 6d14b8f29b5f..78647eda6d0d 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -69,8 +71,21 @@ + #define BAD_FIQ 2 + #define BAD_ERROR 3 + +- .macro kernel_ventry label ++ .macro kernel_ventry, el, label, regsize = 64 + .align 7 ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++alternative_if ARM64_UNMAP_KERNEL_AT_EL0 ++ .if \el == 0 ++ .if \regsize == 64 ++ mrs x30, tpidrro_el0 ++ msr tpidrro_el0, xzr ++ .else ++ mov x30, xzr ++ .endif ++ .endif ++alternative_else_nop_endif ++#endif ++ + sub sp, sp, #S_FRAME_SIZE + #ifdef CONFIG_VMAP_STACK + /* +@@ -82,7 +97,7 @@ + tbnz x0, #THREAD_SHIFT, 0f + sub x0, sp, x0 // x0'' = sp' - x0' = (sp + x0) - sp = x0 + sub sp, sp, x0 // sp'' = sp' - x0 = (sp + x0) - x0 = sp +- b \label ++ b el\()\el\()_\label + + 0: + /* +@@ -114,7 +129,12 @@ + sub sp, sp, x0 + mrs x0, tpidrro_el0 + #endif +- b \label ++ b el\()\el\()_\label ++ .endm ++ ++ .macro tramp_alias, dst, sym ++ mov_q \dst, TRAMP_VALIAS ++ add \dst, \dst, #(\sym - .entry.tramp.text) + .endm + + .macro kernel_entry, el, regsize = 64 +@@ -147,10 +167,10 @@ + .else + add x21, sp, #S_FRAME_SIZE + get_thread_info tsk +- /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */ ++ /* Save the task's original addr_limit and set USER_DS */ + ldr x20, [tsk, #TSK_TI_ADDR_LIMIT] + str x20, [sp, #S_ORIG_ADDR_LIMIT] +- mov x20, #TASK_SIZE_64 ++ mov x20, #USER_DS + str x20, [tsk, #TSK_TI_ADDR_LIMIT] + /* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */ + .endif /* \el == 0 */ +@@ -185,7 +205,7 @@ alternative_else_nop_endif + + .if \el != 0 + mrs x21, ttbr0_el1 +- tst x21, #0xffff << 48 // Check for the reserved ASID ++ tst x21, #TTBR_ASID_MASK // Check for the reserved ASID + orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR + b.eq 1f // TTBR0 access already disabled + and x23, x23, #~PSR_PAN_BIT // Clear the emulated PAN in the saved SPSR +@@ -248,7 +268,7 @@ alternative_else_nop_endif + tbnz x22, #22, 1f // Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set + .endif + +- __uaccess_ttbr0_enable x0 ++ __uaccess_ttbr0_enable x0, x1 + + .if \el == 0 + /* +@@ -257,7 +277,7 @@ alternative_else_nop_endif + * Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache + * corruption). + */ +- post_ttbr0_update_workaround ++ bl post_ttbr_update_workaround + .endif + 1: + .if \el != 0 +@@ -269,18 +289,20 @@ alternative_else_nop_endif + .if \el == 0 + ldr x23, [sp, #S_SP] // load return stack pointer + msr sp_el0, x23 ++ tst x22, #PSR_MODE32_BIT // native task? ++ b.eq 3f ++ + #ifdef CONFIG_ARM64_ERRATUM_845719 + alternative_if ARM64_WORKAROUND_845719 +- tbz x22, #4, 1f + #ifdef CONFIG_PID_IN_CONTEXTIDR + mrs x29, contextidr_el1 + msr contextidr_el1, x29 + #else + msr contextidr_el1, xzr + #endif +-1: + alternative_else_nop_endif + #endif ++3: + .endif + + msr elr_el1, x21 // set up the return data +@@ -302,7 +324,21 @@ alternative_else_nop_endif + ldp x28, x29, [sp, #16 * 14] + ldr lr, [sp, #S_LR] + add sp, sp, #S_FRAME_SIZE // restore sp +- eret // return to kernel ++ ++ .if \el == 0 ++alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ bne 4f ++ msr far_el1, x30 ++ tramp_alias x30, tramp_exit_native ++ br x30 ++4: ++ tramp_alias x30, tramp_exit_compat ++ br x30 ++#endif ++ .else ++ eret ++ .endif + .endm + + .macro irq_stack_entry +@@ -342,6 +378,7 @@ alternative_else_nop_endif + * x7 is reserved for the system call number in 32-bit mode. + */ + wsc_nr .req w25 // number of system calls ++xsc_nr .req x25 // number of system calls (zero-extended) + wscno .req w26 // syscall number + xscno .req x26 // syscall number (zero-extended) + stbl .req x27 // syscall table pointer +@@ -367,31 +404,31 @@ tsk .req x28 // current thread_info + + .align 11 + ENTRY(vectors) +- kernel_ventry el1_sync_invalid // Synchronous EL1t +- kernel_ventry el1_irq_invalid // IRQ EL1t +- kernel_ventry el1_fiq_invalid // FIQ EL1t +- kernel_ventry el1_error_invalid // Error EL1t ++ kernel_ventry 1, sync_invalid // Synchronous EL1t ++ kernel_ventry 1, irq_invalid // IRQ EL1t ++ kernel_ventry 1, fiq_invalid // FIQ EL1t ++ kernel_ventry 1, error_invalid // Error EL1t + +- kernel_ventry el1_sync // Synchronous EL1h +- kernel_ventry el1_irq // IRQ EL1h +- kernel_ventry el1_fiq_invalid // FIQ EL1h +- kernel_ventry el1_error // Error EL1h ++ kernel_ventry 1, sync // Synchronous EL1h ++ kernel_ventry 1, irq // IRQ EL1h ++ kernel_ventry 1, fiq_invalid // FIQ EL1h ++ kernel_ventry 1, error // Error EL1h + +- kernel_ventry el0_sync // Synchronous 64-bit EL0 +- kernel_ventry el0_irq // IRQ 64-bit EL0 +- kernel_ventry el0_fiq_invalid // FIQ 64-bit EL0 +- kernel_ventry el0_error // Error 64-bit EL0 ++ kernel_ventry 0, sync // Synchronous 64-bit EL0 ++ kernel_ventry 0, irq // IRQ 64-bit EL0 ++ kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0 ++ kernel_ventry 0, error // Error 64-bit EL0 + + #ifdef CONFIG_COMPAT +- kernel_ventry el0_sync_compat // Synchronous 32-bit EL0 +- kernel_ventry el0_irq_compat // IRQ 32-bit EL0 +- kernel_ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 +- kernel_ventry el0_error_compat // Error 32-bit EL0 ++ kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0 ++ kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0 ++ kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0 ++ kernel_ventry 0, error_compat, 32 // Error 32-bit EL0 + #else +- kernel_ventry el0_sync_invalid // Synchronous 32-bit EL0 +- kernel_ventry el0_irq_invalid // IRQ 32-bit EL0 +- kernel_ventry el0_fiq_invalid // FIQ 32-bit EL0 +- kernel_ventry el0_error_invalid // Error 32-bit EL0 ++ kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0 ++ kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0 ++ kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0 ++ kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0 + #endif + END(vectors) + +@@ -685,12 +722,15 @@ el0_ia: + * Instruction abort handling + */ + mrs x26, far_el1 +- enable_daif ++ enable_da_f ++#ifdef CONFIG_TRACE_IRQFLAGS ++ bl trace_hardirqs_off ++#endif + ct_user_exit + mov x0, x26 + mov x1, x25 + mov x2, sp +- bl do_mem_abort ++ bl do_el0_ia_bp_hardening + b ret_to_user + el0_fpsimd_acc: + /* +@@ -727,7 +767,10 @@ el0_sp_pc: + * Stack or PC alignment exception handling + */ + mrs x26, far_el1 +- enable_daif ++ enable_da_f ++#ifdef CONFIG_TRACE_IRQFLAGS ++ bl trace_hardirqs_off ++#endif + ct_user_exit + mov x0, x26 + mov x1, x25 +@@ -785,6 +828,11 @@ el0_irq_naked: + #endif + + ct_user_exit ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ tbz x22, #55, 1f ++ bl do_el0_irq_bp_hardening ++1: ++#endif + irq_handler + + #ifdef CONFIG_TRACE_IRQFLAGS +@@ -896,6 +944,7 @@ el0_svc_naked: // compat entry point + b.ne __sys_trace + cmp wscno, wsc_nr // check upper syscall limit + b.hs ni_sys ++ mask_nospec64 xscno, xsc_nr, x19 // enforce bounds for syscall number + ldr x16, [stbl, xscno, lsl #3] // address in the syscall table + blr x16 // call sys_* routine + b ret_fast_syscall +@@ -943,6 +992,117 @@ __ni_sys_trace: + + .popsection // .entry.text + ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++/* ++ * Exception vectors trampoline. ++ */ ++ .pushsection ".entry.tramp.text", "ax" ++ ++ .macro tramp_map_kernel, tmp ++ mrs \tmp, ttbr1_el1 ++ sub \tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) ++ bic \tmp, \tmp, #USER_ASID_FLAG ++ msr ttbr1_el1, \tmp ++#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003 ++alternative_if ARM64_WORKAROUND_QCOM_FALKOR_E1003 ++ /* ASID already in \tmp[63:48] */ ++ movk \tmp, #:abs_g2_nc:(TRAMP_VALIAS >> 12) ++ movk \tmp, #:abs_g1_nc:(TRAMP_VALIAS >> 12) ++ /* 2MB boundary containing the vectors, so we nobble the walk cache */ ++ movk \tmp, #:abs_g0_nc:((TRAMP_VALIAS & ~(SZ_2M - 1)) >> 12) ++ isb ++ tlbi vae1, \tmp ++ dsb nsh ++alternative_else_nop_endif ++#endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */ ++ .endm ++ ++ .macro tramp_unmap_kernel, tmp ++ mrs \tmp, ttbr1_el1 ++ add \tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) ++ orr \tmp, \tmp, #USER_ASID_FLAG ++ msr ttbr1_el1, \tmp ++ /* ++ * We avoid running the post_ttbr_update_workaround here because ++ * it's only needed by Cavium ThunderX, which requires KPTI to be ++ * disabled. ++ */ ++ .endm ++ ++ .macro tramp_ventry, regsize = 64 ++ .align 7 ++1: ++ .if \regsize == 64 ++ msr tpidrro_el0, x30 // Restored in kernel_ventry ++ .endif ++ /* ++ * Defend against branch aliasing attacks by pushing a dummy ++ * entry onto the return stack and using a RET instruction to ++ * enter the full-fat kernel vectors. ++ */ ++ bl 2f ++ b . ++2: ++ tramp_map_kernel x30 ++#ifdef CONFIG_RANDOMIZE_BASE ++ adr x30, tramp_vectors + PAGE_SIZE ++alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003 ++ ldr x30, [x30] ++#else ++ ldr x30, =vectors ++#endif ++ prfm plil1strm, [x30, #(1b - tramp_vectors)] ++ msr vbar_el1, x30 ++ add x30, x30, #(1b - tramp_vectors) ++ isb ++ ret ++ .endm ++ ++ .macro tramp_exit, regsize = 64 ++ adr x30, tramp_vectors ++ msr vbar_el1, x30 ++ tramp_unmap_kernel x30 ++ .if \regsize == 64 ++ mrs x30, far_el1 ++ .endif ++ eret ++ .endm ++ ++ .align 11 ++ENTRY(tramp_vectors) ++ .space 0x400 ++ ++ tramp_ventry ++ tramp_ventry ++ tramp_ventry ++ tramp_ventry ++ ++ tramp_ventry 32 ++ tramp_ventry 32 ++ tramp_ventry 32 ++ tramp_ventry 32 ++END(tramp_vectors) ++ ++ENTRY(tramp_exit_native) ++ tramp_exit ++END(tramp_exit_native) ++ ++ENTRY(tramp_exit_compat) ++ tramp_exit 32 ++END(tramp_exit_compat) ++ ++ .ltorg ++ .popsection // .entry.tramp.text ++#ifdef CONFIG_RANDOMIZE_BASE ++ .pushsection ".rodata", "a" ++ .align PAGE_SHIFT ++ .globl __entry_tramp_data_start ++__entry_tramp_data_start: ++ .quad vectors ++ .popsection // .rodata ++#endif /* CONFIG_RANDOMIZE_BASE */ ++#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ ++ + /* + * Special system call wrappers. + */ +diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S +index e3cb9fbf96b6..9b655d69c471 100644 +--- a/arch/arm64/kernel/head.S ++++ b/arch/arm64/kernel/head.S +@@ -371,7 +371,7 @@ ENDPROC(__primary_switched) + * end early head section, begin head code that is also used for + * hotplug and needs to have the same protections as the text region + */ +- .section ".idmap.text","ax" ++ .section ".idmap.text","awx" + + ENTRY(kimage_vaddr) + .quad _text - TEXT_OFFSET +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 6b7dcf4310ac..583fd8154695 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -370,16 +370,14 @@ void tls_preserve_current_state(void) + + static void tls_thread_switch(struct task_struct *next) + { +- unsigned long tpidr, tpidrro; +- + tls_preserve_current_state(); + +- tpidr = *task_user_tls(next); +- tpidrro = is_compat_thread(task_thread_info(next)) ? +- next->thread.tp_value : 0; ++ if (is_compat_thread(task_thread_info(next))) ++ write_sysreg(next->thread.tp_value, tpidrro_el0); ++ else if (!arm64_kernel_unmapped_at_el0()) ++ write_sysreg(0, tpidrro_el0); + +- write_sysreg(tpidr, tpidr_el0); +- write_sysreg(tpidrro, tpidrro_el0); ++ write_sysreg(*task_user_tls(next), tpidr_el0); + } + + /* Restore the UAO state depending on next's addr_limit */ +diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S +index 10dd16d7902d..bebec8ef9372 100644 +--- a/arch/arm64/kernel/sleep.S ++++ b/arch/arm64/kernel/sleep.S +@@ -96,7 +96,7 @@ ENTRY(__cpu_suspend_enter) + ret + ENDPROC(__cpu_suspend_enter) + +- .pushsection ".idmap.text", "ax" ++ .pushsection ".idmap.text", "awx" + ENTRY(cpu_resume) + bl el2_setup // if in EL2 drop to EL1 cleanly + bl __cpu_setup +diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S +index 7da3e5c366a0..ddfd3c0942f7 100644 +--- a/arch/arm64/kernel/vmlinux.lds.S ++++ b/arch/arm64/kernel/vmlinux.lds.S +@@ -57,6 +57,17 @@ jiffies = jiffies_64; + #define HIBERNATE_TEXT + #endif + ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++#define TRAMP_TEXT \ ++ . = ALIGN(PAGE_SIZE); \ ++ VMLINUX_SYMBOL(__entry_tramp_text_start) = .; \ ++ *(.entry.tramp.text) \ ++ . = ALIGN(PAGE_SIZE); \ ++ VMLINUX_SYMBOL(__entry_tramp_text_end) = .; ++#else ++#define TRAMP_TEXT ++#endif ++ + /* + * The size of the PE/COFF section that covers the kernel image, which + * runs from stext to _edata, must be a round multiple of the PE/COFF +@@ -113,6 +124,7 @@ SECTIONS + HYPERVISOR_TEXT + IDMAP_TEXT + HIBERNATE_TEXT ++ TRAMP_TEXT + *(.fixup) + *(.gnu.warning) + . = ALIGN(16); +@@ -214,6 +226,11 @@ SECTIONS + . += RESERVED_TTBR0_SIZE; + #endif + ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ tramp_pg_dir = .; ++ . += PAGE_SIZE; ++#endif ++ + __pecoff_data_size = ABSOLUTE(. - __initdata_begin); + _end = .; + +@@ -234,7 +251,10 @@ ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, + ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1)) + <= SZ_4K, "Hibernate exit text too big or misaligned") + #endif +- ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE, ++ "Entry trampoline text too big") ++#endif + /* + * If padding is applied before .head.text, virt<->phys conversions will fail. + */ +diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c +index e60494f1eef9..c6c59356aa88 100644 +--- a/arch/arm64/kvm/handle_exit.c ++++ b/arch/arm64/kvm/handle_exit.c +@@ -22,12 +22,13 @@ + #include + #include + ++#include ++ + #include + #include + #include + #include + #include +-#include + #include + + #define CREATE_TRACE_POINTS +@@ -43,7 +44,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) + kvm_vcpu_hvc_get_imm(vcpu)); + vcpu->stat.hvc_exit_stat++; + +- ret = kvm_psci_call(vcpu); ++ ret = kvm_hvc_call_handler(vcpu); + if (ret < 0) { + vcpu_set_reg(vcpu, 0, ~0UL); + return 1; +@@ -54,7 +55,16 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) + + static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) + { ++ /* ++ * "If an SMC instruction executed at Non-secure EL1 is ++ * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a ++ * Trap exception, not a Secure Monitor Call exception [...]" ++ * ++ * We need to advance the PC after the trap, as it would ++ * otherwise return to the same address... ++ */ + vcpu_set_reg(vcpu, 0, ~0UL); ++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 1; + } + +diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S +index 12ee62d6d410..9c45c6af1f58 100644 +--- a/arch/arm64/kvm/hyp/entry.S ++++ b/arch/arm64/kvm/hyp/entry.S +@@ -196,3 +196,15 @@ alternative_endif + + eret + ENDPROC(__fpsimd_guest_restore) ++ ++ENTRY(__qcom_hyp_sanitize_btac_predictors) ++ /** ++ * Call SMC64 with Silicon provider serviceID 23<<8 (0xc2001700) ++ * 0xC2000000-0xC200FFFF: assigned to SiP Service Calls ++ * b15-b0: contains SiP functionID ++ */ ++ movz x0, #0x1700 ++ movk x0, #0xc200, lsl #16 ++ smc #0 ++ ret ++ENDPROC(__qcom_hyp_sanitize_btac_predictors) +diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S +index 5170ce1021da..f49b53331d28 100644 +--- a/arch/arm64/kvm/hyp/hyp-entry.S ++++ b/arch/arm64/kvm/hyp/hyp-entry.S +@@ -15,6 +15,7 @@ + * along with this program. If not, see . + */ + ++#include + #include + + #include +@@ -64,10 +65,11 @@ alternative_endif + lsr x0, x1, #ESR_ELx_EC_SHIFT + + cmp x0, #ESR_ELx_EC_HVC64 ++ ccmp x0, #ESR_ELx_EC_HVC32, #4, ne + b.ne el1_trap + +- mrs x1, vttbr_el2 // If vttbr is valid, the 64bit guest +- cbnz x1, el1_trap // called HVC ++ mrs x1, vttbr_el2 // If vttbr is valid, the guest ++ cbnz x1, el1_hvc_guest // called HVC + + /* Here, we're pretty sure the host called HVC. */ + ldp x0, x1, [sp], #16 +@@ -100,6 +102,20 @@ alternative_endif + + eret + ++el1_hvc_guest: ++ /* ++ * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1. ++ * The workaround has already been applied on the host, ++ * so let's quickly get back to the guest. We don't bother ++ * restoring x1, as it can be clobbered anyway. ++ */ ++ ldr x1, [sp] // Guest's x0 ++ eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 ++ cbnz w1, el1_trap ++ mov x0, x1 ++ add sp, sp, #16 ++ eret ++ + el1_trap: + /* + * x0: ESR_EC +diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c +index f7c651f3a8c0..0b5ab4d8b57d 100644 +--- a/arch/arm64/kvm/hyp/switch.c ++++ b/arch/arm64/kvm/hyp/switch.c +@@ -17,6 +17,9 @@ + + #include + #include ++#include ++ ++#include + + #include + #include +@@ -52,7 +55,7 @@ static void __hyp_text __activate_traps_vhe(void) + val &= ~(CPACR_EL1_FPEN | CPACR_EL1_ZEN); + write_sysreg(val, cpacr_el1); + +- write_sysreg(__kvm_hyp_vector, vbar_el1); ++ write_sysreg(kvm_get_hyp_vector(), vbar_el1); + } + + static void __hyp_text __activate_traps_nvhe(void) +@@ -393,6 +396,14 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + /* 0 falls through to be handled out of EL2 */ + } + ++ if (cpus_have_const_cap(ARM64_HARDEN_BP_POST_GUEST_EXIT)) { ++ u32 midr = read_cpuid_id(); ++ ++ /* Apply BTAC predictors mitigation to all Falkor chips */ ++ if ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1) ++ __qcom_hyp_sanitize_btac_predictors(); ++ } ++ + fp_enabled = __fpsimd_enabled(); + + __sysreg_save_guest_state(guest_ctxt); +diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S +index e88fb99c1561..21ba0b29621b 100644 +--- a/arch/arm64/lib/clear_user.S ++++ b/arch/arm64/lib/clear_user.S +@@ -21,7 +21,7 @@ + + .text + +-/* Prototype: int __clear_user(void *addr, size_t sz) ++/* Prototype: int __arch_clear_user(void *addr, size_t sz) + * Purpose : clear some user memory + * Params : addr - user memory address to clear + * : sz - number of bytes to clear +@@ -29,8 +29,8 @@ + * + * Alignment fixed up by hardware. + */ +-ENTRY(__clear_user) +- uaccess_enable_not_uao x2, x3 ++ENTRY(__arch_clear_user) ++ uaccess_enable_not_uao x2, x3, x4 + mov x2, x1 // save the size for fixup return + subs x1, x1, #8 + b.mi 2f +@@ -50,9 +50,9 @@ uao_user_alternative 9f, strh, sttrh, wzr, x0, 2 + b.mi 5f + uao_user_alternative 9f, strb, sttrb, wzr, x0, 0 + 5: mov x0, #0 +- uaccess_disable_not_uao x2 ++ uaccess_disable_not_uao x2, x3 + ret +-ENDPROC(__clear_user) ++ENDPROC(__arch_clear_user) + + .section .fixup,"ax" + .align 2 +diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S +index 4b5d826895ff..20305d485046 100644 +--- a/arch/arm64/lib/copy_from_user.S ++++ b/arch/arm64/lib/copy_from_user.S +@@ -64,10 +64,10 @@ + + end .req x5 + ENTRY(__arch_copy_from_user) +- uaccess_enable_not_uao x3, x4 ++ uaccess_enable_not_uao x3, x4, x5 + add end, x0, x2 + #include "copy_template.S" +- uaccess_disable_not_uao x3 ++ uaccess_disable_not_uao x3, x4 + mov x0, #0 // Nothing to copy + ret + ENDPROC(__arch_copy_from_user) +diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S +index b24a830419ad..54b75deb1d16 100644 +--- a/arch/arm64/lib/copy_in_user.S ++++ b/arch/arm64/lib/copy_in_user.S +@@ -64,14 +64,15 @@ + .endm + + end .req x5 +-ENTRY(raw_copy_in_user) +- uaccess_enable_not_uao x3, x4 ++ ++ENTRY(__arch_copy_in_user) ++ uaccess_enable_not_uao x3, x4, x5 + add end, x0, x2 + #include "copy_template.S" +- uaccess_disable_not_uao x3 ++ uaccess_disable_not_uao x3, x4 + mov x0, #0 + ret +-ENDPROC(raw_copy_in_user) ++ENDPROC(__arch_copy_in_user) + + .section .fixup,"ax" + .align 2 +diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S +index 351f0766f7a6..fda6172d6b88 100644 +--- a/arch/arm64/lib/copy_to_user.S ++++ b/arch/arm64/lib/copy_to_user.S +@@ -63,10 +63,10 @@ + + end .req x5 + ENTRY(__arch_copy_to_user) +- uaccess_enable_not_uao x3, x4 ++ uaccess_enable_not_uao x3, x4, x5 + add end, x0, x2 + #include "copy_template.S" +- uaccess_disable_not_uao x3 ++ uaccess_disable_not_uao x3, x4 + mov x0, #0 + ret + ENDPROC(__arch_copy_to_user) +diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S +index 7f1dbe962cf5..91464e7f77cc 100644 +--- a/arch/arm64/mm/cache.S ++++ b/arch/arm64/mm/cache.S +@@ -49,7 +49,7 @@ ENTRY(flush_icache_range) + * - end - virtual end address of region + */ + ENTRY(__flush_cache_user_range) +- uaccess_ttbr0_enable x2, x3 ++ uaccess_ttbr0_enable x2, x3, x4 + dcache_line_size x2, x3 + sub x3, x2, #1 + bic x4, x0, x3 +@@ -72,7 +72,7 @@ USER(9f, ic ivau, x4 ) // invalidate I line PoU + isb + mov x0, #0 + 1: +- uaccess_ttbr0_disable x1 ++ uaccess_ttbr0_disable x1, x2 + ret + 9: + mov x0, #-EFAULT +diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c +index 6f4017046323..b1ac80fba578 100644 +--- a/arch/arm64/mm/context.c ++++ b/arch/arm64/mm/context.c +@@ -39,7 +39,16 @@ static cpumask_t tlb_flush_pending; + + #define ASID_MASK (~GENMASK(asid_bits - 1, 0)) + #define ASID_FIRST_VERSION (1UL << asid_bits) +-#define NUM_USER_ASIDS ASID_FIRST_VERSION ++ ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++#define NUM_USER_ASIDS (ASID_FIRST_VERSION >> 1) ++#define asid2idx(asid) (((asid) & ~ASID_MASK) >> 1) ++#define idx2asid(idx) (((idx) << 1) & ~ASID_MASK) ++#else ++#define NUM_USER_ASIDS (ASID_FIRST_VERSION) ++#define asid2idx(asid) ((asid) & ~ASID_MASK) ++#define idx2asid(idx) asid2idx(idx) ++#endif + + /* Get the ASIDBits supported by the current CPU */ + static u32 get_cpu_asid_bits(void) +@@ -79,13 +88,6 @@ void verify_cpu_asid_bits(void) + } + } + +-static void set_reserved_asid_bits(void) +-{ +- if (IS_ENABLED(CONFIG_QCOM_FALKOR_ERRATUM_1003) && +- cpus_have_const_cap(ARM64_WORKAROUND_QCOM_FALKOR_E1003)) +- __set_bit(FALKOR_RESERVED_ASID, asid_map); +-} +- + static void flush_context(unsigned int cpu) + { + int i; +@@ -94,8 +96,6 @@ static void flush_context(unsigned int cpu) + /* Update the list of reserved ASIDs and the ASID bitmap. */ + bitmap_clear(asid_map, 0, NUM_USER_ASIDS); + +- set_reserved_asid_bits(); +- + for_each_possible_cpu(i) { + asid = atomic64_xchg_relaxed(&per_cpu(active_asids, i), 0); + /* +@@ -107,7 +107,7 @@ static void flush_context(unsigned int cpu) + */ + if (asid == 0) + asid = per_cpu(reserved_asids, i); +- __set_bit(asid & ~ASID_MASK, asid_map); ++ __set_bit(asid2idx(asid), asid_map); + per_cpu(reserved_asids, i) = asid; + } + +@@ -162,16 +162,16 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) + * We had a valid ASID in a previous life, so try to re-use + * it if possible. + */ +- asid &= ~ASID_MASK; +- if (!__test_and_set_bit(asid, asid_map)) ++ if (!__test_and_set_bit(asid2idx(asid), asid_map)) + return newasid; + } + + /* + * Allocate a free ASID. If we can't find one, take a note of the +- * currently active ASIDs and mark the TLBs as requiring flushes. +- * We always count from ASID #1, as we use ASID #0 when setting a +- * reserved TTBR0 for the init_mm. ++ * currently active ASIDs and mark the TLBs as requiring flushes. We ++ * always count from ASID #2 (index 1), as we use ASID #0 when setting ++ * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd ++ * pairs. + */ + asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); + if (asid != NUM_USER_ASIDS) +@@ -188,7 +188,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) + set_asid: + __set_bit(asid, asid_map); + cur_idx = asid; +- return asid | generation; ++ return idx2asid(asid) | generation; + } + + void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) +@@ -231,6 +231,9 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) + raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); + + switch_mm_fastpath: ++ ++ arm64_apply_bp_hardening(); ++ + /* + * Defer TTBR0_EL1 setting for user threads to uaccess_enable() when + * emulating PAN. +@@ -239,6 +242,15 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) + cpu_switch_mm(mm->pgd, mm); + } + ++/* Errata workaround post TTBRx_EL1 update. */ ++asmlinkage void post_ttbr_update_workaround(void) ++{ ++ asm(ALTERNATIVE("nop; nop; nop", ++ "ic iallu; dsb nsh; isb", ++ ARM64_WORKAROUND_CAVIUM_27456, ++ CONFIG_CAVIUM_ERRATUM_27456)); ++} ++ + static int asids_init(void) + { + asid_bits = get_cpu_asid_bits(); +@@ -254,8 +266,6 @@ static int asids_init(void) + panic("Failed to allocate bitmap for %lu ASIDs\n", + NUM_USER_ASIDS); + +- set_reserved_asid_bits(); +- + pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS); + return 0; + } +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index 9b7f89df49db..dd8f5197b549 100644 +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -240,7 +240,7 @@ static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs, + if (fsc_type == ESR_ELx_FSC_PERM) + return true; + +- if (addr < USER_DS && system_uses_ttbr0_pan()) ++ if (addr < TASK_SIZE && system_uses_ttbr0_pan()) + return fsc_type == ESR_ELx_FSC_FAULT && + (regs->pstate & PSR_PAN_BIT); + +@@ -414,7 +414,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, + mm_flags |= FAULT_FLAG_WRITE; + } + +- if (addr < USER_DS && is_permission_fault(esr, regs, addr)) { ++ if (addr < TASK_SIZE && is_permission_fault(esr, regs, addr)) { + /* regs->orig_addr_limit may be 0 if we entered from EL0 */ + if (regs->orig_addr_limit == KERNEL_DS) + die("Accessing user space memory with fs=KERNEL_DS", regs, esr); +@@ -707,6 +707,29 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, + arm64_notify_die("", regs, &info, esr); + } + ++asmlinkage void __exception do_el0_irq_bp_hardening(void) ++{ ++ /* PC has already been checked in entry.S */ ++ arm64_apply_bp_hardening(); ++} ++ ++asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr, ++ unsigned int esr, ++ struct pt_regs *regs) ++{ ++ /* ++ * We've taken an instruction abort from userspace and not yet ++ * re-enabled IRQs. If the address is a kernel address, apply ++ * BP hardening prior to enabling IRQs and pre-emption. ++ */ ++ if (addr > TASK_SIZE) ++ arm64_apply_bp_hardening(); ++ ++ local_irq_enable(); ++ do_mem_abort(addr, esr, regs); ++} ++ ++ + asmlinkage void __exception do_sp_pc_abort(unsigned long addr, + unsigned int esr, + struct pt_regs *regs) +@@ -714,6 +737,12 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr, + struct siginfo info; + struct task_struct *tsk = current; + ++ if (user_mode(regs)) { ++ if (instruction_pointer(regs) > TASK_SIZE) ++ arm64_apply_bp_hardening(); ++ local_irq_enable(); ++ } ++ + if (show_unhandled_signals && unhandled_signal(tsk, SIGBUS)) + pr_info_ratelimited("%s[%d]: %s exception: pc=%p sp=%p\n", + tsk->comm, task_pid_nr(tsk), +@@ -773,6 +802,9 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, + if (interrupts_enabled(regs)) + trace_hardirqs_off(); + ++ if (user_mode(regs) && instruction_pointer(regs) > TASK_SIZE) ++ arm64_apply_bp_hardening(); ++ + if (!inf->fn(addr, esr, regs)) { + rv = 1; + } else { +diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c +index 267d2b79d52d..451f96f3377c 100644 +--- a/arch/arm64/mm/mmu.c ++++ b/arch/arm64/mm/mmu.c +@@ -117,6 +117,10 @@ static bool pgattr_change_is_safe(u64 old, u64 new) + if ((old | new) & PTE_CONT) + return false; + ++ /* Transitioning from Global to Non-Global is safe */ ++ if (((old ^ new) == PTE_NG) && (new & PTE_NG)) ++ return true; ++ + return ((old ^ new) & ~mask) == 0; + } + +@@ -525,6 +529,37 @@ static int __init parse_rodata(char *arg) + } + early_param("rodata", parse_rodata); + ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++static int __init map_entry_trampoline(void) ++{ ++ extern char __entry_tramp_text_start[]; ++ ++ pgprot_t prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; ++ phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); ++ ++ /* The trampoline is always mapped and can therefore be global */ ++ pgprot_val(prot) &= ~PTE_NG; ++ ++ /* Map only the text into the trampoline page table */ ++ memset(tramp_pg_dir, 0, PGD_SIZE); ++ __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE, ++ prot, pgd_pgtable_alloc, 0); ++ ++ /* Map both the text and data into the kernel page table */ ++ __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot); ++ if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { ++ extern char __entry_tramp_data_start[]; ++ ++ __set_fixmap(FIX_ENTRY_TRAMP_DATA, ++ __pa_symbol(__entry_tramp_data_start), ++ PAGE_KERNEL_RO); ++ } ++ ++ return 0; ++} ++core_initcall(map_entry_trampoline); ++#endif ++ + /* + * Create fine-grained mappings for the kernel. + */ +diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S +index 95233dfc4c39..08572f95bd8a 100644 +--- a/arch/arm64/mm/proc.S ++++ b/arch/arm64/mm/proc.S +@@ -86,7 +86,7 @@ ENDPROC(cpu_do_suspend) + * + * x0: Address of context pointer + */ +- .pushsection ".idmap.text", "ax" ++ .pushsection ".idmap.text", "awx" + ENTRY(cpu_do_resume) + ldp x2, x3, [x0] + ldp x4, x5, [x0, #16] +@@ -138,16 +138,30 @@ ENDPROC(cpu_do_resume) + * - pgd_phys - physical address of new TTB + */ + ENTRY(cpu_do_switch_mm) +- pre_ttbr0_update_workaround x0, x2, x3 ++ mrs x2, ttbr1_el1 + mmid x1, x1 // get mm->context.id +- bfi x0, x1, #48, #16 // set the ASID +- msr ttbr0_el1, x0 // set TTBR0 ++#ifdef CONFIG_ARM64_SW_TTBR0_PAN ++ bfi x0, x1, #48, #16 // set the ASID field in TTBR0 ++#endif ++ bfi x2, x1, #48, #16 // set the ASID ++ msr ttbr1_el1, x2 // in TTBR1 (since TCR.A1 is set) + isb +- post_ttbr0_update_workaround +- ret ++ msr ttbr0_el1, x0 // now update TTBR0 ++ isb ++ b post_ttbr_update_workaround // Back to C code... + ENDPROC(cpu_do_switch_mm) + +- .pushsection ".idmap.text", "ax" ++ .pushsection ".idmap.text", "awx" ++ ++.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 ++ adrp \tmp1, empty_zero_page ++ msr ttbr1_el1, \tmp2 ++ isb ++ tlbi vmalle1 ++ dsb nsh ++ isb ++.endm ++ + /* + * void idmap_cpu_replace_ttbr1(phys_addr_t new_pgd) + * +@@ -157,13 +171,7 @@ ENDPROC(cpu_do_switch_mm) + ENTRY(idmap_cpu_replace_ttbr1) + save_and_disable_daif flags=x2 + +- adrp x1, empty_zero_page +- msr ttbr1_el1, x1 +- isb +- +- tlbi vmalle1 +- dsb nsh +- isb ++ __idmap_cpu_set_reserved_ttbr1 x1, x3 + + msr ttbr1_el1, x0 + isb +@@ -174,13 +182,197 @@ ENTRY(idmap_cpu_replace_ttbr1) + ENDPROC(idmap_cpu_replace_ttbr1) + .popsection + ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ .pushsection ".idmap.text", "awx" ++ ++ .macro __idmap_kpti_get_pgtable_ent, type ++ dc cvac, cur_\()\type\()p // Ensure any existing dirty ++ dmb sy // lines are written back before ++ ldr \type, [cur_\()\type\()p] // loading the entry ++ tbz \type, #0, next_\()\type // Skip invalid entries ++ .endm ++ ++ .macro __idmap_kpti_put_pgtable_ent_ng, type ++ orr \type, \type, #PTE_NG // Same bit for blocks and pages ++ str \type, [cur_\()\type\()p] // Update the entry and ensure it ++ dc civac, cur_\()\type\()p // is visible to all CPUs. ++ .endm ++ ++/* ++ * void __kpti_install_ng_mappings(int cpu, int num_cpus, phys_addr_t swapper) ++ * ++ * Called exactly once from stop_machine context by each CPU found during boot. ++ */ ++__idmap_kpti_flag: ++ .long 1 ++ENTRY(idmap_kpti_install_ng_mappings) ++ cpu .req w0 ++ num_cpus .req w1 ++ swapper_pa .req x2 ++ swapper_ttb .req x3 ++ flag_ptr .req x4 ++ cur_pgdp .req x5 ++ end_pgdp .req x6 ++ pgd .req x7 ++ cur_pudp .req x8 ++ end_pudp .req x9 ++ pud .req x10 ++ cur_pmdp .req x11 ++ end_pmdp .req x12 ++ pmd .req x13 ++ cur_ptep .req x14 ++ end_ptep .req x15 ++ pte .req x16 ++ ++ mrs swapper_ttb, ttbr1_el1 ++ adr flag_ptr, __idmap_kpti_flag ++ ++ cbnz cpu, __idmap_kpti_secondary ++ ++ /* We're the boot CPU. Wait for the others to catch up */ ++ sevl ++1: wfe ++ ldaxr w18, [flag_ptr] ++ eor w18, w18, num_cpus ++ cbnz w18, 1b ++ ++ /* We need to walk swapper, so turn off the MMU. */ ++ pre_disable_mmu_workaround ++ mrs x18, sctlr_el1 ++ bic x18, x18, #SCTLR_ELx_M ++ msr sctlr_el1, x18 ++ isb ++ ++ /* Everybody is enjoying the idmap, so we can rewrite swapper. */ ++ /* PGD */ ++ mov cur_pgdp, swapper_pa ++ add end_pgdp, cur_pgdp, #(PTRS_PER_PGD * 8) ++do_pgd: __idmap_kpti_get_pgtable_ent pgd ++ tbnz pgd, #1, walk_puds ++ __idmap_kpti_put_pgtable_ent_ng pgd ++next_pgd: ++ add cur_pgdp, cur_pgdp, #8 ++ cmp cur_pgdp, end_pgdp ++ b.ne do_pgd ++ ++ /* Publish the updated tables and nuke all the TLBs */ ++ dsb sy ++ tlbi vmalle1is ++ dsb ish ++ isb ++ ++ /* We're done: fire up the MMU again */ ++ mrs x18, sctlr_el1 ++ orr x18, x18, #SCTLR_ELx_M ++ msr sctlr_el1, x18 ++ isb ++ ++ /* Set the flag to zero to indicate that we're all done */ ++ str wzr, [flag_ptr] ++ ret ++ ++ /* PUD */ ++walk_puds: ++ .if CONFIG_PGTABLE_LEVELS > 3 ++ pte_to_phys cur_pudp, pgd ++ add end_pudp, cur_pudp, #(PTRS_PER_PUD * 8) ++do_pud: __idmap_kpti_get_pgtable_ent pud ++ tbnz pud, #1, walk_pmds ++ __idmap_kpti_put_pgtable_ent_ng pud ++next_pud: ++ add cur_pudp, cur_pudp, 8 ++ cmp cur_pudp, end_pudp ++ b.ne do_pud ++ b next_pgd ++ .else /* CONFIG_PGTABLE_LEVELS <= 3 */ ++ mov pud, pgd ++ b walk_pmds ++next_pud: ++ b next_pgd ++ .endif ++ ++ /* PMD */ ++walk_pmds: ++ .if CONFIG_PGTABLE_LEVELS > 2 ++ pte_to_phys cur_pmdp, pud ++ add end_pmdp, cur_pmdp, #(PTRS_PER_PMD * 8) ++do_pmd: __idmap_kpti_get_pgtable_ent pmd ++ tbnz pmd, #1, walk_ptes ++ __idmap_kpti_put_pgtable_ent_ng pmd ++next_pmd: ++ add cur_pmdp, cur_pmdp, #8 ++ cmp cur_pmdp, end_pmdp ++ b.ne do_pmd ++ b next_pud ++ .else /* CONFIG_PGTABLE_LEVELS <= 2 */ ++ mov pmd, pud ++ b walk_ptes ++next_pmd: ++ b next_pud ++ .endif ++ ++ /* PTE */ ++walk_ptes: ++ pte_to_phys cur_ptep, pmd ++ add end_ptep, cur_ptep, #(PTRS_PER_PTE * 8) ++do_pte: __idmap_kpti_get_pgtable_ent pte ++ __idmap_kpti_put_pgtable_ent_ng pte ++next_pte: ++ add cur_ptep, cur_ptep, #8 ++ cmp cur_ptep, end_ptep ++ b.ne do_pte ++ b next_pmd ++ ++ /* Secondary CPUs end up here */ ++__idmap_kpti_secondary: ++ /* Uninstall swapper before surgery begins */ ++ __idmap_cpu_set_reserved_ttbr1 x18, x17 ++ ++ /* Increment the flag to let the boot CPU we're ready */ ++1: ldxr w18, [flag_ptr] ++ add w18, w18, #1 ++ stxr w17, w18, [flag_ptr] ++ cbnz w17, 1b ++ ++ /* Wait for the boot CPU to finish messing around with swapper */ ++ sevl ++1: wfe ++ ldxr w18, [flag_ptr] ++ cbnz w18, 1b ++ ++ /* All done, act like nothing happened */ ++ msr ttbr1_el1, swapper_ttb ++ isb ++ ret ++ ++ .unreq cpu ++ .unreq num_cpus ++ .unreq swapper_pa ++ .unreq swapper_ttb ++ .unreq flag_ptr ++ .unreq cur_pgdp ++ .unreq end_pgdp ++ .unreq pgd ++ .unreq cur_pudp ++ .unreq end_pudp ++ .unreq pud ++ .unreq cur_pmdp ++ .unreq end_pmdp ++ .unreq pmd ++ .unreq cur_ptep ++ .unreq end_ptep ++ .unreq pte ++ENDPROC(idmap_kpti_install_ng_mappings) ++ .popsection ++#endif ++ + /* + * __cpu_setup + * + * Initialise the processor for turning the MMU on. Return in x0 the + * value of the SCTLR_EL1 register. + */ +- .pushsection ".idmap.text", "ax" ++ .pushsection ".idmap.text", "awx" + ENTRY(__cpu_setup) + tlbi vmalle1 // Invalidate local TLB + dsb nsh +@@ -224,7 +416,7 @@ ENTRY(__cpu_setup) + * both user and kernel. + */ + ldr x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \ +- TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0 ++ TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0 | TCR_A1 + tcr_set_idmap_t0sz x10, x9 + + /* +diff --git a/arch/arm64/xen/hypercall.S b/arch/arm64/xen/hypercall.S +index 401ceb71540c..c5f05c4a4d00 100644 +--- a/arch/arm64/xen/hypercall.S ++++ b/arch/arm64/xen/hypercall.S +@@ -101,12 +101,12 @@ ENTRY(privcmd_call) + * need the explicit uaccess_enable/disable if the TTBR0 PAN emulation + * is enabled (it implies that hardware UAO and PAN disabled). + */ +- uaccess_ttbr0_enable x6, x7 ++ uaccess_ttbr0_enable x6, x7, x8 + hvc XEN_IMM + + /* + * Disable userspace access from kernel once the hyp call completed. + */ +- uaccess_ttbr0_disable x6 ++ uaccess_ttbr0_disable x6, x7 + ret + ENDPROC(privcmd_call); +diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c +index b39a388825ae..8ace89617c1c 100644 +--- a/arch/mn10300/mm/misalignment.c ++++ b/arch/mn10300/mm/misalignment.c +@@ -437,7 +437,7 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code) + + info.si_signo = SIGSEGV; + info.si_errno = 0; +- info.si_code = 0; ++ info.si_code = SEGV_MAPERR; + info.si_addr = (void *) regs->pc; + force_sig_info(SIGSEGV, &info, current); + return; +diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c +index 4085d72fa5ae..9e38dc66c9e4 100644 +--- a/arch/openrisc/kernel/traps.c ++++ b/arch/openrisc/kernel/traps.c +@@ -266,12 +266,12 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address) + siginfo_t info; + + if (user_mode(regs)) { +- /* Send a SIGSEGV */ +- info.si_signo = SIGSEGV; ++ /* Send a SIGBUS */ ++ info.si_signo = SIGBUS; + info.si_errno = 0; +- /* info.si_code has been set above */ +- info.si_addr = (void *)address; +- force_sig_info(SIGSEGV, &info, current); ++ info.si_code = BUS_ADRALN; ++ info.si_addr = (void __user *)address; ++ force_sig_info(SIGBUS, &info, current); + } else { + printk("KERNEL: Unaligned Access 0x%.8lx\n", address); + show_registers(regs); +diff --git a/arch/powerpc/crypto/crc32c-vpmsum_glue.c b/arch/powerpc/crypto/crc32c-vpmsum_glue.c +index f058e0c3e4d4..fd1d6c83f0c0 100644 +--- a/arch/powerpc/crypto/crc32c-vpmsum_glue.c ++++ b/arch/powerpc/crypto/crc32c-vpmsum_glue.c +@@ -141,6 +141,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-vpmsum", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig +index b12b8eb39c29..648160334abf 100644 +--- a/arch/powerpc/kvm/Kconfig ++++ b/arch/powerpc/kvm/Kconfig +@@ -68,7 +68,7 @@ config KVM_BOOK3S_64 + select KVM_BOOK3S_64_HANDLER + select KVM + select KVM_BOOK3S_PR_POSSIBLE if !KVM_BOOK3S_HV_POSSIBLE +- select SPAPR_TCE_IOMMU if IOMMU_SUPPORT && (PPC_SERIES || PPC_POWERNV) ++ select SPAPR_TCE_IOMMU if IOMMU_SUPPORT && (PPC_PSERIES || PPC_POWERNV) + ---help--- + Support running unmodified book3s_64 and book3s_32 guest kernels + in virtual machines on book3s_64 host processors. +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 2d46037ce936..6c402f6c4940 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -1005,8 +1005,6 @@ static int kvmppc_emulate_doorbell_instr(struct kvm_vcpu *vcpu) + struct kvm *kvm = vcpu->kvm; + struct kvm_vcpu *tvcpu; + +- if (!cpu_has_feature(CPU_FTR_ARCH_300)) +- return EMULATE_FAIL; + if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst) != EMULATE_DONE) + return RESUME_GUEST; + if (get_op(inst) != 31) +@@ -1056,6 +1054,7 @@ static int kvmppc_emulate_doorbell_instr(struct kvm_vcpu *vcpu) + return RESUME_GUEST; + } + ++/* Called with vcpu->arch.vcore->lock held */ + static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, + struct task_struct *tsk) + { +@@ -1176,7 +1175,10 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, + swab32(vcpu->arch.emul_inst) : + vcpu->arch.emul_inst; + if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) { ++ /* Need vcore unlocked to call kvmppc_get_last_inst */ ++ spin_unlock(&vcpu->arch.vcore->lock); + r = kvmppc_emulate_debug_inst(run, vcpu); ++ spin_lock(&vcpu->arch.vcore->lock); + } else { + kvmppc_core_queue_program(vcpu, SRR1_PROGILL); + r = RESUME_GUEST; +@@ -1191,8 +1193,13 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, + */ + case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: + r = EMULATE_FAIL; +- if ((vcpu->arch.hfscr >> 56) == FSCR_MSGP_LG) ++ if (((vcpu->arch.hfscr >> 56) == FSCR_MSGP_LG) && ++ cpu_has_feature(CPU_FTR_ARCH_300)) { ++ /* Need vcore unlocked to call kvmppc_get_last_inst */ ++ spin_unlock(&vcpu->arch.vcore->lock); + r = kvmppc_emulate_doorbell_instr(vcpu); ++ spin_lock(&vcpu->arch.vcore->lock); ++ } + if (r == EMULATE_FAIL) { + kvmppc_core_queue_program(vcpu, SRR1_PROGILL); + r = RESUME_GUEST; +@@ -2934,13 +2941,14 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) + /* make sure updates to secondary vcpu structs are visible now */ + smp_mb(); + ++ preempt_enable(); ++ + for (sub = 0; sub < core_info.n_subcores; ++sub) { + pvc = core_info.vc[sub]; + post_guest_process(pvc, pvc == vc); + } + + spin_lock(&vc->lock); +- preempt_enable(); + + out: + vc->vcore_state = VCORE_INACTIVE; +diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +index 9c61f736c75b..ffec37062f3b 100644 +--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S ++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +@@ -1423,6 +1423,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) + blt deliver_guest_interrupt + + guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ ++ /* Save more register state */ ++ mfdar r6 ++ mfdsisr r7 ++ std r6, VCPU_DAR(r9) ++ stw r7, VCPU_DSISR(r9) ++ /* don't overwrite fault_dar/fault_dsisr if HDSI */ ++ cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE ++ beq mc_cont ++ std r6, VCPU_FAULT_DAR(r9) ++ stw r7, VCPU_FAULT_DSISR(r9) ++ ++ /* See if it is a machine check */ ++ cmpwi r12, BOOK3S_INTERRUPT_MACHINE_CHECK ++ beq machine_check_realmode ++mc_cont: ++#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING ++ addi r3, r9, VCPU_TB_RMEXIT ++ mr r4, r9 ++ bl kvmhv_accumulate_time ++#endif + #ifdef CONFIG_KVM_XICS + /* We are exiting, pull the VP from the XIVE */ + lwz r0, VCPU_XIVE_PUSHED(r9) +@@ -1460,26 +1480,6 @@ guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ + eieio + 1: + #endif /* CONFIG_KVM_XICS */ +- /* Save more register state */ +- mfdar r6 +- mfdsisr r7 +- std r6, VCPU_DAR(r9) +- stw r7, VCPU_DSISR(r9) +- /* don't overwrite fault_dar/fault_dsisr if HDSI */ +- cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE +- beq mc_cont +- std r6, VCPU_FAULT_DAR(r9) +- stw r7, VCPU_FAULT_DSISR(r9) +- +- /* See if it is a machine check */ +- cmpwi r12, BOOK3S_INTERRUPT_MACHINE_CHECK +- beq machine_check_realmode +-mc_cont: +-#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING +- addi r3, r9, VCPU_TB_RMEXIT +- mr r4, r9 +- bl kvmhv_accumulate_time +-#endif + + mr r3, r12 + /* Increment exit count, poke other threads to exit */ +diff --git a/arch/s390/crypto/crc32-vx.c b/arch/s390/crypto/crc32-vx.c +index 436865926c26..423ee05887e6 100644 +--- a/arch/s390/crypto/crc32-vx.c ++++ b/arch/s390/crypto/crc32-vx.c +@@ -239,6 +239,7 @@ static struct shash_alg crc32_vx_algs[] = { + .cra_name = "crc32", + .cra_driver_name = "crc32-vx", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CRC32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crc_ctx), + .cra_module = THIS_MODULE, +@@ -259,6 +260,7 @@ static struct shash_alg crc32_vx_algs[] = { + .cra_name = "crc32be", + .cra_driver_name = "crc32be-vx", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CRC32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crc_ctx), + .cra_module = THIS_MODULE, +@@ -279,6 +281,7 @@ static struct shash_alg crc32_vx_algs[] = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-vx", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CRC32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crc_ctx), + .cra_module = THIS_MODULE, +diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c +index 57cff00cad17..b3770bb26211 100644 +--- a/arch/sh/kernel/traps_32.c ++++ b/arch/sh/kernel/traps_32.c +@@ -609,7 +609,8 @@ asmlinkage void do_divide_error(unsigned long r4) + break; + } + +- force_sig_info(SIGFPE, &info, current); ++ info.si_signo = SIGFPE; ++ force_sig_info(info.si_signo, &info, current); + } + #endif + +diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c +index d1064e46efe8..8aa664638c3c 100644 +--- a/arch/sparc/crypto/crc32c_glue.c ++++ b/arch/sparc/crypto/crc32c_glue.c +@@ -133,6 +133,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-sparc64", + .cra_priority = SPARC_CR_OPCODE_PRIORITY, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_alignmask = 7, +diff --git a/arch/x86/crypto/crc32-pclmul_glue.c b/arch/x86/crypto/crc32-pclmul_glue.c +index 27226df3f7d8..c8d9cdacbf10 100644 +--- a/arch/x86/crypto/crc32-pclmul_glue.c ++++ b/arch/x86/crypto/crc32-pclmul_glue.c +@@ -162,6 +162,7 @@ static struct shash_alg alg = { + .cra_name = "crc32", + .cra_driver_name = "crc32-pclmul", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c +index c194d5717ae5..5773e1161072 100644 +--- a/arch/x86/crypto/crc32c-intel_glue.c ++++ b/arch/x86/crypto/crc32c-intel_glue.c +@@ -226,6 +226,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-intel", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c +index e32142bc071d..28c372003e44 100644 +--- a/arch/x86/crypto/poly1305_glue.c ++++ b/arch/x86/crypto/poly1305_glue.c +@@ -164,7 +164,6 @@ static struct shash_alg alg = { + .init = poly1305_simd_init, + .update = poly1305_simd_update, + .final = crypto_poly1305_final, +- .setkey = crypto_poly1305_setkey, + .descsize = sizeof(struct poly1305_simd_desc_ctx), + .base = { + .cra_name = "poly1305", +diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c +index 36870b26067a..d08805032f01 100644 +--- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c ++++ b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c +@@ -57,10 +57,12 @@ void sha512_mb_mgr_init_avx2(struct sha512_mb_mgr *state) + { + unsigned int j; + +- state->lens[0] = 0; +- state->lens[1] = 1; +- state->lens[2] = 2; +- state->lens[3] = 3; ++ /* initially all lanes are unused */ ++ state->lens[0] = 0xFFFFFFFF00000000; ++ state->lens[1] = 0xFFFFFFFF00000001; ++ state->lens[2] = 0xFFFFFFFF00000002; ++ state->lens[3] = 0xFFFFFFFF00000003; ++ + state->unused_lanes = 0xFF03020100; + for (j = 0; j < 4; j++) + state->ldata[j].job_in_lane = NULL; +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index bee4c49f6dd0..6f623848260f 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -5323,14 +5323,15 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu, + + if (is_guest_mode(vcpu) && + vector == vmx->nested.posted_intr_nv) { +- /* the PIR and ON have been set by L1. */ +- kvm_vcpu_trigger_posted_interrupt(vcpu, true); + /* + * If a posted intr is not recognized by hardware, + * we will accomplish it in the next vmentry. + */ + vmx->nested.pi_pending = true; + kvm_make_request(KVM_REQ_EVENT, vcpu); ++ /* the PIR and ON have been set by L1. */ ++ if (!kvm_vcpu_trigger_posted_interrupt(vcpu, true)) ++ kvm_vcpu_kick(vcpu); + return 0; + } + return -1; +@@ -11254,7 +11255,6 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr) + if (block_nested_events) + return -EBUSY; + nested_vmx_inject_exception_vmexit(vcpu, exit_qual); +- vcpu->arch.exception.pending = false; + return 0; + } + +diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h +index d0b95b7a90b4..6d112d8f799c 100644 +--- a/arch/x86/kvm/x86.h ++++ b/arch/x86/kvm/x86.h +@@ -12,6 +12,7 @@ + + static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu) + { ++ vcpu->arch.exception.pending = false; + vcpu->arch.exception.injected = false; + } + +diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h +index eaaf1ebcc7a4..5bfbc1c401d4 100644 +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -92,7 +92,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + u32 oldval, u32 newval) + { + int ret = 0; +- u32 prev; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; +@@ -103,26 +102,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + + __asm__ __volatile__ ( + " # futex_atomic_cmpxchg_inatomic\n" +- "1: l32i %1, %3, 0\n" +- " mov %0, %5\n" +- " wsr %1, scompare1\n" +- "2: s32c1i %0, %3, 0\n" +- "3:\n" ++ " wsr %5, scompare1\n" ++ "1: s32c1i %1, %4, 0\n" ++ " s32i %1, %6, 0\n" ++ "2:\n" + " .section .fixup,\"ax\"\n" + " .align 4\n" +- "4: .long 3b\n" +- "5: l32r %1, 4b\n" +- " movi %0, %6\n" ++ "3: .long 2b\n" ++ "4: l32r %1, 3b\n" ++ " movi %0, %7\n" + " jx %1\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- " .long 1b,5b,2b,5b\n" ++ " .long 1b,4b\n" + " .previous\n" +- : "+r" (ret), "=&r" (prev), "+m" (*uaddr) +- : "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT) ++ : "+r" (ret), "+r" (newval), "+m" (*uaddr), "+m" (*uval) ++ : "r" (uaddr), "r" (oldval), "r" (uval), "I" (-EFAULT) + : "memory"); + +- *uval = prev; + return ret; + } + +diff --git a/block/blk-core.c b/block/blk-core.c +index 3ba4326a63b5..82b92adf3477 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -699,6 +699,15 @@ void blk_cleanup_queue(struct request_queue *q) + queue_flag_set(QUEUE_FLAG_DEAD, q); + spin_unlock_irq(lock); + ++ /* ++ * make sure all in-progress dispatch are completed because ++ * blk_freeze_queue() can only complete all requests, and ++ * dispatch may still be in-progress since we dispatch requests ++ * from more than one contexts ++ */ ++ if (q->mq_ops) ++ blk_mq_quiesce_queue(q); ++ + /* for synchronous bio-based driver finish in-flight integrity i/o */ + blk_flush_integrity(); + +diff --git a/crypto/ahash.c b/crypto/ahash.c +index 3a35d67de7d9..266fc1d64f61 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -193,11 +193,18 @@ int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen) + { + unsigned long alignmask = crypto_ahash_alignmask(tfm); ++ int err; + + if ((unsigned long)key & alignmask) +- return ahash_setkey_unaligned(tfm, key, keylen); ++ err = ahash_setkey_unaligned(tfm, key, keylen); ++ else ++ err = tfm->setkey(tfm, key, keylen); ++ ++ if (err) ++ return err; + +- return tfm->setkey(tfm, key, keylen); ++ crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); ++ return 0; + } + EXPORT_SYMBOL_GPL(crypto_ahash_setkey); + +@@ -368,7 +375,12 @@ EXPORT_SYMBOL_GPL(crypto_ahash_finup); + + int crypto_ahash_digest(struct ahash_request *req) + { +- return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->digest); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return crypto_ahash_op(req, tfm->digest); + } + EXPORT_SYMBOL_GPL(crypto_ahash_digest); + +@@ -450,7 +462,6 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) + struct ahash_alg *alg = crypto_ahash_alg(hash); + + hash->setkey = ahash_nosetkey; +- hash->has_setkey = false; + hash->export = ahash_no_export; + hash->import = ahash_no_import; + +@@ -465,7 +476,8 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) + + if (alg->setkey) { + hash->setkey = alg->setkey; +- hash->has_setkey = true; ++ if (!(alg->halg.base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY)) ++ crypto_ahash_set_flags(hash, CRYPTO_TFM_NEED_KEY); + } + if (alg->export) + hash->export = alg->export; +@@ -649,5 +661,16 @@ struct hash_alg_common *ahash_attr_alg(struct rtattr *rta, u32 type, u32 mask) + } + EXPORT_SYMBOL_GPL(ahash_attr_alg); + ++bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg) ++{ ++ struct crypto_alg *alg = &halg->base; ++ ++ if (alg->cra_type != &crypto_ahash_type) ++ return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg)); ++ ++ return __crypto_ahash_alg(alg)->setkey != NULL; ++} ++EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey); ++ + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Asynchronous cryptographic hash type"); +diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c +index 76d2e716c792..6c9b1927a520 100644 +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -34,11 +34,6 @@ struct hash_ctx { + struct ahash_request req; + }; + +-struct algif_hash_tfm { +- struct crypto_ahash *hash; +- bool has_key; +-}; +- + static int hash_alloc_result(struct sock *sk, struct hash_ctx *ctx) + { + unsigned ds; +@@ -307,7 +302,7 @@ static int hash_check_key(struct socket *sock) + int err = 0; + struct sock *psk; + struct alg_sock *pask; +- struct algif_hash_tfm *tfm; ++ struct crypto_ahash *tfm; + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + +@@ -321,7 +316,7 @@ static int hash_check_key(struct socket *sock) + + err = -ENOKEY; + lock_sock_nested(psk, SINGLE_DEPTH_NESTING); +- if (!tfm->has_key) ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + goto unlock; + + if (!pask->refcnt++) +@@ -412,41 +407,17 @@ static struct proto_ops algif_hash_ops_nokey = { + + static void *hash_bind(const char *name, u32 type, u32 mask) + { +- struct algif_hash_tfm *tfm; +- struct crypto_ahash *hash; +- +- tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); +- if (!tfm) +- return ERR_PTR(-ENOMEM); +- +- hash = crypto_alloc_ahash(name, type, mask); +- if (IS_ERR(hash)) { +- kfree(tfm); +- return ERR_CAST(hash); +- } +- +- tfm->hash = hash; +- +- return tfm; ++ return crypto_alloc_ahash(name, type, mask); + } + + static void hash_release(void *private) + { +- struct algif_hash_tfm *tfm = private; +- +- crypto_free_ahash(tfm->hash); +- kfree(tfm); ++ crypto_free_ahash(private); + } + + static int hash_setkey(void *private, const u8 *key, unsigned int keylen) + { +- struct algif_hash_tfm *tfm = private; +- int err; +- +- err = crypto_ahash_setkey(tfm->hash, key, keylen); +- tfm->has_key = !err; +- +- return err; ++ return crypto_ahash_setkey(private, key, keylen); + } + + static void hash_sock_destruct(struct sock *sk) +@@ -461,11 +432,10 @@ static void hash_sock_destruct(struct sock *sk) + + static int hash_accept_parent_nokey(void *private, struct sock *sk) + { +- struct hash_ctx *ctx; ++ struct crypto_ahash *tfm = private; + struct alg_sock *ask = alg_sk(sk); +- struct algif_hash_tfm *tfm = private; +- struct crypto_ahash *hash = tfm->hash; +- unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash); ++ struct hash_ctx *ctx; ++ unsigned int len = sizeof(*ctx) + crypto_ahash_reqsize(tfm); + + ctx = sock_kmalloc(sk, len, GFP_KERNEL); + if (!ctx) +@@ -478,7 +448,7 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk) + + ask->private = ctx; + +- ahash_request_set_tfm(&ctx->req, hash); ++ ahash_request_set_tfm(&ctx->req, tfm); + ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &ctx->wait); + +@@ -489,9 +459,9 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk) + + static int hash_accept_parent(void *private, struct sock *sk) + { +- struct algif_hash_tfm *tfm = private; ++ struct crypto_ahash *tfm = private; + +- if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash)) ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + return -ENOKEY; + + return hash_accept_parent_nokey(private, sk); +diff --git a/crypto/crc32_generic.c b/crypto/crc32_generic.c +index aa2a25fc7482..718cbce8d169 100644 +--- a/crypto/crc32_generic.c ++++ b/crypto/crc32_generic.c +@@ -133,6 +133,7 @@ static struct shash_alg alg = { + .cra_name = "crc32", + .cra_driver_name = "crc32-generic", + .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c +index 4c0a0e271876..372320399622 100644 +--- a/crypto/crc32c_generic.c ++++ b/crypto/crc32c_generic.c +@@ -146,6 +146,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-generic", + .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(struct chksum_ctx), +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index bd43cf5be14c..c32b98b5daf8 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -893,10 +893,9 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, + if (err) + goto out_free_inst; + +- type = CRYPTO_ALG_ASYNC; +- if (alg->cra_flags & CRYPTO_ALG_INTERNAL) +- type |= CRYPTO_ALG_INTERNAL; +- inst->alg.halg.base.cra_flags = type; ++ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC | ++ (alg->cra_flags & (CRYPTO_ALG_INTERNAL | ++ CRYPTO_ALG_OPTIONAL_KEY)); + + inst->alg.halg.digestsize = salg->digestsize; + inst->alg.halg.statesize = salg->statesize; +@@ -911,7 +910,8 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, + inst->alg.finup = cryptd_hash_finup_enqueue; + inst->alg.export = cryptd_hash_export; + inst->alg.import = cryptd_hash_import; +- inst->alg.setkey = cryptd_hash_setkey; ++ if (crypto_shash_alg_has_setkey(salg)) ++ inst->alg.setkey = cryptd_hash_setkey; + inst->alg.digest = cryptd_hash_digest_enqueue; + + err = ahash_register_instance(tmpl, inst); +diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c +index eca04d3729b3..e0732d979e3b 100644 +--- a/crypto/mcryptd.c ++++ b/crypto/mcryptd.c +@@ -517,10 +517,9 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, + if (err) + goto out_free_inst; + +- type = CRYPTO_ALG_ASYNC; +- if (alg->cra_flags & CRYPTO_ALG_INTERNAL) +- type |= CRYPTO_ALG_INTERNAL; +- inst->alg.halg.base.cra_flags = type; ++ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC | ++ (alg->cra_flags & (CRYPTO_ALG_INTERNAL | ++ CRYPTO_ALG_OPTIONAL_KEY)); + + inst->alg.halg.digestsize = halg->digestsize; + inst->alg.halg.statesize = halg->statesize; +@@ -535,7 +534,8 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, + inst->alg.finup = mcryptd_hash_finup_enqueue; + inst->alg.export = mcryptd_hash_export; + inst->alg.import = mcryptd_hash_import; +- inst->alg.setkey = mcryptd_hash_setkey; ++ if (crypto_hash_alg_has_setkey(halg)) ++ inst->alg.setkey = mcryptd_hash_setkey; + inst->alg.digest = mcryptd_hash_digest_enqueue; + + err = ahash_register_instance(tmpl, inst); +diff --git a/crypto/poly1305_generic.c b/crypto/poly1305_generic.c +index b1c2d57dc734..ba39eb308c79 100644 +--- a/crypto/poly1305_generic.c ++++ b/crypto/poly1305_generic.c +@@ -47,17 +47,6 @@ int crypto_poly1305_init(struct shash_desc *desc) + } + EXPORT_SYMBOL_GPL(crypto_poly1305_init); + +-int crypto_poly1305_setkey(struct crypto_shash *tfm, +- const u8 *key, unsigned int keylen) +-{ +- /* Poly1305 requires a unique key for each tag, which implies that +- * we can't set it on the tfm that gets accessed by multiple users +- * simultaneously. Instead we expect the key as the first 32 bytes in +- * the update() call. */ +- return -ENOTSUPP; +-} +-EXPORT_SYMBOL_GPL(crypto_poly1305_setkey); +- + static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key) + { + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ +@@ -76,6 +65,11 @@ static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key) + dctx->s[3] = get_unaligned_le32(key + 12); + } + ++/* ++ * Poly1305 requires a unique key for each tag, which implies that we can't set ++ * it on the tfm that gets accessed by multiple users simultaneously. Instead we ++ * expect the key as the first 32 bytes in the update() call. ++ */ + unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, + const u8 *src, unsigned int srclen) + { +@@ -281,7 +275,6 @@ static struct shash_alg poly1305_alg = { + .init = crypto_poly1305_init, + .update = crypto_poly1305_update, + .final = crypto_poly1305_final, +- .setkey = crypto_poly1305_setkey, + .descsize = sizeof(struct poly1305_desc_ctx), + .base = { + .cra_name = "poly1305", +diff --git a/crypto/shash.c b/crypto/shash.c +index e849d3ee2e27..5d732c6bb4b2 100644 +--- a/crypto/shash.c ++++ b/crypto/shash.c +@@ -58,11 +58,18 @@ int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key, + { + struct shash_alg *shash = crypto_shash_alg(tfm); + unsigned long alignmask = crypto_shash_alignmask(tfm); ++ int err; + + if ((unsigned long)key & alignmask) +- return shash_setkey_unaligned(tfm, key, keylen); ++ err = shash_setkey_unaligned(tfm, key, keylen); ++ else ++ err = shash->setkey(tfm, key, keylen); ++ ++ if (err) ++ return err; + +- return shash->setkey(tfm, key, keylen); ++ crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); ++ return 0; + } + EXPORT_SYMBOL_GPL(crypto_shash_setkey); + +@@ -181,6 +188,9 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data, + struct shash_alg *shash = crypto_shash_alg(tfm); + unsigned long alignmask = crypto_shash_alignmask(tfm); + ++ if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ + if (((unsigned long)data | (unsigned long)out) & alignmask) + return shash_digest_unaligned(desc, data, len, out); + +@@ -360,7 +370,8 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm) + crt->digest = shash_async_digest; + crt->setkey = shash_async_setkey; + +- crt->has_setkey = alg->setkey != shash_no_setkey; ++ crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) & ++ CRYPTO_TFM_NEED_KEY); + + if (alg->export) + crt->export = shash_async_export; +@@ -375,8 +386,14 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm) + static int crypto_shash_init_tfm(struct crypto_tfm *tfm) + { + struct crypto_shash *hash = __crypto_shash_cast(tfm); ++ struct shash_alg *alg = crypto_shash_alg(hash); ++ ++ hash->descsize = alg->descsize; ++ ++ if (crypto_shash_alg_has_setkey(alg) && ++ !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY)) ++ crypto_shash_set_flags(hash, CRYPTO_TFM_NEED_KEY); + +- hash->descsize = crypto_shash_alg(hash)->descsize; + return 0; + } + +diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c +index abeb4df4f22e..b28ce440a06f 100644 +--- a/drivers/acpi/nfit/core.c ++++ b/drivers/acpi/nfit/core.c +@@ -1867,6 +1867,9 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc) + struct kernfs_node *nfit_kernfs; + + nvdimm = nfit_mem->nvdimm; ++ if (!nvdimm) ++ continue; ++ + nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit"); + if (nfit_kernfs) + nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs, +diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c +index 2fa8304171e0..7a3431018e0a 100644 +--- a/drivers/acpi/sbshc.c ++++ b/drivers/acpi/sbshc.c +@@ -275,8 +275,8 @@ static int acpi_smbus_hc_add(struct acpi_device *device) + device->driver_data = hc; + + acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); +- printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", +- hc->ec, hc->offset, hc->query_bit); ++ dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n", ++ hc->offset, hc->query_bit); + + return 0; + } +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 5443cb71d7ba..44a9d630b7ac 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -268,9 +268,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ +- { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */ ++ { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH M AHCI */ + { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ +- { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ ++ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH M RAID */ + { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */ +@@ -293,9 +293,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ +- { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ ++ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT M AHCI */ + { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ +- { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ ++ { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT M RAID */ + { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ +@@ -304,20 +304,20 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ + { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ +- { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ ++ { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point M AHCI */ + { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ +- { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point M RAID */ + { PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ + { PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ +- { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point M AHCI */ + { PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ +- { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point M RAID */ + { PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ +- { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point M RAID */ + { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ +- { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point M RAID */ + { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ +@@ -358,21 +358,21 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ +- { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series M AHCI */ + { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ +- { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ +- { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ +- { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series M RAID */ + { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */ +- { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ ++ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H M AHCI */ + { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */ +- { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H M RAID */ + { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/ +@@ -386,6 +386,11 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ + { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ ++ { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ ++ { PCI_VDEVICE(INTEL, 0x0f22), board_ahci }, /* Bay Trail AHCI */ ++ { PCI_VDEVICE(INTEL, 0x0f23), board_ahci }, /* Bay Trail AHCI */ ++ { PCI_VDEVICE(INTEL, 0x22a3), board_ahci }, /* Cherry Trail AHCI */ ++ { PCI_VDEVICE(INTEL, 0x5ae3), board_ahci }, /* Apollo Lake AHCI */ + + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, +diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c +index 67974796c350..531a0915066b 100644 +--- a/drivers/block/pktcdvd.c ++++ b/drivers/block/pktcdvd.c +@@ -2579,14 +2579,14 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) + bdev = bdget(dev); + if (!bdev) + return -ENOMEM; ++ ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY, NULL); ++ if (ret) ++ return ret; + if (!blk_queue_scsi_passthrough(bdev_get_queue(bdev))) { + WARN_ONCE(true, "Attempt to register a non-SCSI queue\n"); +- bdput(bdev); ++ blkdev_put(bdev, FMODE_READ | FMODE_NDELAY); + return -EINVAL; + } +- ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY, NULL); +- if (ret) +- return ret; + + /* This is safe, since we have a reference from open(). */ + __module_get(THIS_MODULE); +@@ -2745,7 +2745,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) + pd->pkt_dev = MKDEV(pktdev_major, idx); + ret = pkt_new_dev(pd, dev); + if (ret) +- goto out_new_dev; ++ goto out_mem2; + + /* inherit events of the host device */ + disk->events = pd->bdev->bd_disk->events; +@@ -2763,8 +2763,6 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) + mutex_unlock(&ctl_mutex); + return 0; + +-out_new_dev: +- blk_cleanup_queue(disk->queue); + out_mem2: + put_disk(disk); + out_mem: +diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c +index c8e945d19ffe..20142bc77554 100644 +--- a/drivers/bluetooth/btsdio.c ++++ b/drivers/bluetooth/btsdio.c +@@ -31,6 +31,7 @@ + #include + #include + ++#include + #include + #include + +@@ -292,6 +293,14 @@ static int btsdio_probe(struct sdio_func *func, + tuple = tuple->next; + } + ++ /* BCM43341 devices soldered onto the PCB (non-removable) use an ++ * uart connection for bluetooth, ignore the BT SDIO interface. ++ */ ++ if (func->vendor == SDIO_VENDOR_ID_BROADCOM && ++ func->device == SDIO_DEVICE_ID_BROADCOM_43341 && ++ !mmc_card_is_removable(func->card->host)) ++ return -ENODEV; ++ + data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index f7120c9eb9bd..76980e78ae56 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -23,6 +23,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -387,9 +388,8 @@ static const struct usb_device_id blacklist_table[] = { + #define BTUSB_FIRMWARE_LOADED 7 + #define BTUSB_FIRMWARE_FAILED 8 + #define BTUSB_BOOTING 9 +-#define BTUSB_RESET_RESUME 10 +-#define BTUSB_DIAG_RUNNING 11 +-#define BTUSB_OOB_WAKE_ENABLED 12 ++#define BTUSB_DIAG_RUNNING 10 ++#define BTUSB_OOB_WAKE_ENABLED 11 + + struct btusb_data { + struct hci_dev *hdev; +@@ -3120,9 +3120,9 @@ static int btusb_probe(struct usb_interface *intf, + + /* QCA Rome devices lose their updated firmware over suspend, + * but the USB hub doesn't notice any status change. +- * Explicitly request a device reset on resume. ++ * explicitly request a device reset on resume. + */ +- set_bit(BTUSB_RESET_RESUME, &data->flags); ++ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; + } + + #ifdef CONFIG_BT_HCIBTUSB_RTL +@@ -3133,7 +3133,7 @@ static int btusb_probe(struct usb_interface *intf, + * but the USB hub doesn't notice any status change. + * Explicitly request a device reset on resume. + */ +- set_bit(BTUSB_RESET_RESUME, &data->flags); ++ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; + } + #endif + +@@ -3299,14 +3299,6 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) + enable_irq(data->oob_wake_irq); + } + +- /* Optionally request a device reset on resume, but only when +- * wakeups are disabled. If wakeups are enabled we assume the +- * device will stay powered up throughout suspend. +- */ +- if (test_bit(BTUSB_RESET_RESUME, &data->flags) && +- !device_may_wakeup(&data->udev->dev)) +- data->udev->reset_resume = 1; +- + return 0; + } + +diff --git a/drivers/char/ipmi/ipmi_dmi.c b/drivers/char/ipmi/ipmi_dmi.c +index ab78b3be7e33..c5112b17d7ea 100644 +--- a/drivers/char/ipmi/ipmi_dmi.c ++++ b/drivers/char/ipmi/ipmi_dmi.c +@@ -106,7 +106,10 @@ static void __init dmi_add_platform_ipmi(unsigned long base_addr, + pr_err("ipmi:dmi: Error allocation IPMI platform device\n"); + return; + } +- pdev->driver_override = override; ++ pdev->driver_override = kasprintf(GFP_KERNEL, "%s", ++ override); ++ if (!pdev->driver_override) ++ goto err; + + if (type == IPMI_DMI_TYPE_SSIF) { + set_prop_entry(p[pidx++], "i2c-addr", u16, base_addr); +diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c +index 8f2423789ba9..4bfeb9929ab2 100644 +--- a/drivers/clocksource/timer-stm32.c ++++ b/drivers/clocksource/timer-stm32.c +@@ -106,6 +106,10 @@ static int __init stm32_clockevent_init(struct device_node *np) + unsigned long rate, max_delta; + int irq, ret, bits, prescaler = 1; + ++ data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); +@@ -156,8 +160,8 @@ static int __init stm32_clockevent_init(struct device_node *np) + + writel_relaxed(prescaler - 1, data->base + TIM_PSC); + writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR); +- writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER); + writel_relaxed(0, data->base + TIM_SR); ++ writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER); + + data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ); + +@@ -184,6 +188,7 @@ static int __init stm32_clockevent_init(struct device_node *np) + err_clk_enable: + clk_put(clk); + err_clk_get: ++ kfree(data); + return ret; + } + +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index ecc56e26f8f6..3b585e4bfac5 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -108,6 +108,14 @@ static const struct of_device_id blacklist[] __initconst = { + + { .compatible = "marvell,armadaxp", }, + ++ { .compatible = "mediatek,mt2701", }, ++ { .compatible = "mediatek,mt2712", }, ++ { .compatible = "mediatek,mt7622", }, ++ { .compatible = "mediatek,mt7623", }, ++ { .compatible = "mediatek,mt817x", }, ++ { .compatible = "mediatek,mt8173", }, ++ { .compatible = "mediatek,mt8176", }, ++ + { .compatible = "nvidia,tegra124", }, + + { .compatible = "st,stih407", }, +diff --git a/drivers/crypto/bfin_crc.c b/drivers/crypto/bfin_crc.c +index a118b9bed669..bfbf8bf77f03 100644 +--- a/drivers/crypto/bfin_crc.c ++++ b/drivers/crypto/bfin_crc.c +@@ -494,7 +494,8 @@ static struct ahash_alg algs = { + .cra_driver_name = DRIVER_NAME, + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | +- CRYPTO_ALG_ASYNC, ++ CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct bfin_crypto_crc_ctx), + .cra_alignmask = 3, +diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c +index 027e121c6f70..e1d4ae1153c4 100644 +--- a/drivers/crypto/caam/ctrl.c ++++ b/drivers/crypto/caam/ctrl.c +@@ -228,12 +228,16 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask, + * without any error (HW optimizations for later + * CAAM eras), then try again. + */ ++ if (ret) ++ break; ++ + rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK; + if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) || +- !(rdsta_val & (1 << sh_idx))) ++ !(rdsta_val & (1 << sh_idx))) { + ret = -EAGAIN; +- if (ret) + break; ++ } ++ + dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx); + /* Clear the contents before recreating the descriptor */ + memset(desc, 0x00, CAAM_CMD_SZ * 7); +diff --git a/drivers/crypto/stm32/stm32_crc32.c b/drivers/crypto/stm32/stm32_crc32.c +index 090582baecfe..8f09b8430893 100644 +--- a/drivers/crypto/stm32/stm32_crc32.c ++++ b/drivers/crypto/stm32/stm32_crc32.c +@@ -208,6 +208,7 @@ static struct shash_alg algs[] = { + .cra_name = "crc32", + .cra_driver_name = DRIVER_NAME, + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(struct stm32_crc_ctx), +@@ -229,6 +230,7 @@ static struct shash_alg algs[] = { + .cra_name = "crc32c", + .cra_driver_name = DRIVER_NAME, + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(struct stm32_crc_ctx), +diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c +index 9c80e0cb1664..6882fa2f8bad 100644 +--- a/drivers/crypto/talitos.c ++++ b/drivers/crypto/talitos.c +@@ -1138,6 +1138,10 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src, + struct talitos_private *priv = dev_get_drvdata(dev); + bool is_sec1 = has_ftr_sec1(priv); + ++ if (!src) { ++ to_talitos_ptr(ptr, 0, 0, is_sec1); ++ return 1; ++ } + if (sg_count == 1) { + to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1); + return sg_count; +diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c +index ec5f9d2bc820..80cc2be6483c 100644 +--- a/drivers/dma/dmatest.c ++++ b/drivers/dma/dmatest.c +@@ -355,7 +355,7 @@ static void dmatest_callback(void *arg) + { + struct dmatest_done *done = arg; + struct dmatest_thread *thread = +- container_of(arg, struct dmatest_thread, done_wait); ++ container_of(done, struct dmatest_thread, test_done); + if (!thread->done) { + done->done = true; + wake_up_all(done->wait); +diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c +index 9c1ffe3e912b..aeb222ca3ed1 100644 +--- a/drivers/edac/octeon_edac-lmc.c ++++ b/drivers/edac/octeon_edac-lmc.c +@@ -78,6 +78,7 @@ static void octeon_lmc_edac_poll_o2(struct mem_ctl_info *mci) + if (!pvt->inject) + int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx)); + else { ++ int_reg.u64 = 0; + if (pvt->error_type == 1) + int_reg.s.sec_err = 1; + if (pvt->error_type == 2) +diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c +index d687ca3d5049..c80ec1d03274 100644 +--- a/drivers/firmware/psci.c ++++ b/drivers/firmware/psci.c +@@ -59,7 +59,10 @@ bool psci_tos_resident_on(int cpu) + return cpu == resident_cpu; + } + +-struct psci_operations psci_ops; ++struct psci_operations psci_ops = { ++ .conduit = PSCI_CONDUIT_NONE, ++ .smccc_version = SMCCC_VERSION_1_0, ++}; + + typedef unsigned long (psci_fn)(unsigned long, unsigned long, + unsigned long, unsigned long); +@@ -210,6 +213,22 @@ static unsigned long psci_migrate_info_up_cpu(void) + 0, 0, 0); + } + ++static void set_conduit(enum psci_conduit conduit) ++{ ++ switch (conduit) { ++ case PSCI_CONDUIT_HVC: ++ invoke_psci_fn = __invoke_psci_fn_hvc; ++ break; ++ case PSCI_CONDUIT_SMC: ++ invoke_psci_fn = __invoke_psci_fn_smc; ++ break; ++ default: ++ WARN(1, "Unexpected PSCI conduit %d\n", conduit); ++ } ++ ++ psci_ops.conduit = conduit; ++} ++ + static int get_set_conduit_method(struct device_node *np) + { + const char *method; +@@ -222,9 +241,9 @@ static int get_set_conduit_method(struct device_node *np) + } + + if (!strcmp("hvc", method)) { +- invoke_psci_fn = __invoke_psci_fn_hvc; ++ set_conduit(PSCI_CONDUIT_HVC); + } else if (!strcmp("smc", method)) { +- invoke_psci_fn = __invoke_psci_fn_smc; ++ set_conduit(PSCI_CONDUIT_SMC); + } else { + pr_warn("invalid \"method\" property: %s\n", method); + return -EINVAL; +@@ -493,9 +512,36 @@ static void __init psci_init_migrate(void) + pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid); + } + ++static void __init psci_init_smccc(void) ++{ ++ u32 ver = ARM_SMCCC_VERSION_1_0; ++ int feature; ++ ++ feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID); ++ ++ if (feature != PSCI_RET_NOT_SUPPORTED) { ++ u32 ret; ++ ret = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0); ++ if (ret == ARM_SMCCC_VERSION_1_1) { ++ psci_ops.smccc_version = SMCCC_VERSION_1_1; ++ ver = ret; ++ } ++ } ++ ++ /* ++ * Conveniently, the SMCCC and PSCI versions are encoded the ++ * same way. No, this isn't accidental. ++ */ ++ pr_info("SMC Calling Convention v%d.%d\n", ++ PSCI_VERSION_MAJOR(ver), PSCI_VERSION_MINOR(ver)); ++ ++} ++ + static void __init psci_0_2_set_functions(void) + { + pr_info("Using standard PSCI v0.2 function IDs\n"); ++ psci_ops.get_version = psci_get_version; ++ + psci_function_id[PSCI_FN_CPU_SUSPEND] = + PSCI_FN_NATIVE(0_2, CPU_SUSPEND); + psci_ops.cpu_suspend = psci_cpu_suspend; +@@ -539,6 +585,7 @@ static int __init psci_probe(void) + psci_init_migrate(); + + if (PSCI_VERSION_MAJOR(ver) >= 1) { ++ psci_init_smccc(); + psci_init_cpu_suspend(); + psci_init_system_suspend(); + } +@@ -652,9 +699,9 @@ int __init psci_acpi_init(void) + pr_info("probing for conduit method from ACPI.\n"); + + if (acpi_psci_use_hvc()) +- invoke_psci_fn = __invoke_psci_fn_hvc; ++ set_conduit(PSCI_CONDUIT_HVC); + else +- invoke_psci_fn = __invoke_psci_fn_smc; ++ set_conduit(PSCI_CONDUIT_SMC); + + return psci_probe(); + } +diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c +index 6458c309c039..756aad504ed5 100644 +--- a/drivers/gpu/drm/i915/i915_pci.c ++++ b/drivers/gpu/drm/i915/i915_pci.c +@@ -74,19 +74,19 @@ + GEN_DEFAULT_PAGE_SIZES, \ + CURSOR_OFFSETS + +-static const struct intel_device_info intel_i830_info __initconst = { ++static const struct intel_device_info intel_i830_info = { + GEN2_FEATURES, + .platform = INTEL_I830, + .is_mobile = 1, .cursor_needs_physical = 1, + .num_pipes = 2, /* legal, last one wins */ + }; + +-static const struct intel_device_info intel_i845g_info __initconst = { ++static const struct intel_device_info intel_i845g_info = { + GEN2_FEATURES, + .platform = INTEL_I845G, + }; + +-static const struct intel_device_info intel_i85x_info __initconst = { ++static const struct intel_device_info intel_i85x_info = { + GEN2_FEATURES, + .platform = INTEL_I85X, .is_mobile = 1, + .num_pipes = 2, /* legal, last one wins */ +@@ -94,7 +94,7 @@ static const struct intel_device_info intel_i85x_info __initconst = { + .has_fbc = 1, + }; + +-static const struct intel_device_info intel_i865g_info __initconst = { ++static const struct intel_device_info intel_i865g_info = { + GEN2_FEATURES, + .platform = INTEL_I865G, + }; +@@ -108,7 +108,7 @@ static const struct intel_device_info intel_i865g_info __initconst = { + GEN_DEFAULT_PAGE_SIZES, \ + CURSOR_OFFSETS + +-static const struct intel_device_info intel_i915g_info __initconst = { ++static const struct intel_device_info intel_i915g_info = { + GEN3_FEATURES, + .platform = INTEL_I915G, .cursor_needs_physical = 1, + .has_overlay = 1, .overlay_needs_physical = 1, +@@ -116,7 +116,7 @@ static const struct intel_device_info intel_i915g_info __initconst = { + .unfenced_needs_alignment = 1, + }; + +-static const struct intel_device_info intel_i915gm_info __initconst = { ++static const struct intel_device_info intel_i915gm_info = { + GEN3_FEATURES, + .platform = INTEL_I915GM, + .is_mobile = 1, +@@ -128,7 +128,7 @@ static const struct intel_device_info intel_i915gm_info __initconst = { + .unfenced_needs_alignment = 1, + }; + +-static const struct intel_device_info intel_i945g_info __initconst = { ++static const struct intel_device_info intel_i945g_info = { + GEN3_FEATURES, + .platform = INTEL_I945G, + .has_hotplug = 1, .cursor_needs_physical = 1, +@@ -137,7 +137,7 @@ static const struct intel_device_info intel_i945g_info __initconst = { + .unfenced_needs_alignment = 1, + }; + +-static const struct intel_device_info intel_i945gm_info __initconst = { ++static const struct intel_device_info intel_i945gm_info = { + GEN3_FEATURES, + .platform = INTEL_I945GM, .is_mobile = 1, + .has_hotplug = 1, .cursor_needs_physical = 1, +@@ -148,14 +148,14 @@ static const struct intel_device_info intel_i945gm_info __initconst = { + .unfenced_needs_alignment = 1, + }; + +-static const struct intel_device_info intel_g33_info __initconst = { ++static const struct intel_device_info intel_g33_info = { + GEN3_FEATURES, + .platform = INTEL_G33, + .has_hotplug = 1, + .has_overlay = 1, + }; + +-static const struct intel_device_info intel_pineview_info __initconst = { ++static const struct intel_device_info intel_pineview_info = { + GEN3_FEATURES, + .platform = INTEL_PINEVIEW, .is_mobile = 1, + .has_hotplug = 1, +@@ -172,7 +172,7 @@ static const struct intel_device_info intel_pineview_info __initconst = { + GEN_DEFAULT_PAGE_SIZES, \ + CURSOR_OFFSETS + +-static const struct intel_device_info intel_i965g_info __initconst = { ++static const struct intel_device_info intel_i965g_info = { + GEN4_FEATURES, + .platform = INTEL_I965G, + .has_overlay = 1, +@@ -180,7 +180,7 @@ static const struct intel_device_info intel_i965g_info __initconst = { + .has_snoop = false, + }; + +-static const struct intel_device_info intel_i965gm_info __initconst = { ++static const struct intel_device_info intel_i965gm_info = { + GEN4_FEATURES, + .platform = INTEL_I965GM, + .is_mobile = 1, .has_fbc = 1, +@@ -190,13 +190,13 @@ static const struct intel_device_info intel_i965gm_info __initconst = { + .has_snoop = false, + }; + +-static const struct intel_device_info intel_g45_info __initconst = { ++static const struct intel_device_info intel_g45_info = { + GEN4_FEATURES, + .platform = INTEL_G45, + .ring_mask = RENDER_RING | BSD_RING, + }; + +-static const struct intel_device_info intel_gm45_info __initconst = { ++static const struct intel_device_info intel_gm45_info = { + GEN4_FEATURES, + .platform = INTEL_GM45, + .is_mobile = 1, .has_fbc = 1, +@@ -213,12 +213,12 @@ static const struct intel_device_info intel_gm45_info __initconst = { + GEN_DEFAULT_PAGE_SIZES, \ + CURSOR_OFFSETS + +-static const struct intel_device_info intel_ironlake_d_info __initconst = { ++static const struct intel_device_info intel_ironlake_d_info = { + GEN5_FEATURES, + .platform = INTEL_IRONLAKE, + }; + +-static const struct intel_device_info intel_ironlake_m_info __initconst = { ++static const struct intel_device_info intel_ironlake_m_info = { + GEN5_FEATURES, + .platform = INTEL_IRONLAKE, + .is_mobile = 1, .has_fbc = 1, +@@ -241,12 +241,12 @@ static const struct intel_device_info intel_ironlake_m_info __initconst = { + GEN6_FEATURES, \ + .platform = INTEL_SANDYBRIDGE + +-static const struct intel_device_info intel_sandybridge_d_gt1_info __initconst = { ++static const struct intel_device_info intel_sandybridge_d_gt1_info = { + SNB_D_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_sandybridge_d_gt2_info __initconst = { ++static const struct intel_device_info intel_sandybridge_d_gt2_info = { + SNB_D_PLATFORM, + .gt = 2, + }; +@@ -257,12 +257,12 @@ static const struct intel_device_info intel_sandybridge_d_gt2_info __initconst = + .is_mobile = 1 + + +-static const struct intel_device_info intel_sandybridge_m_gt1_info __initconst = { ++static const struct intel_device_info intel_sandybridge_m_gt1_info = { + SNB_M_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst = { ++static const struct intel_device_info intel_sandybridge_m_gt2_info = { + SNB_M_PLATFORM, + .gt = 2, + }; +@@ -286,12 +286,12 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst = + .platform = INTEL_IVYBRIDGE, \ + .has_l3_dpf = 1 + +-static const struct intel_device_info intel_ivybridge_d_gt1_info __initconst = { ++static const struct intel_device_info intel_ivybridge_d_gt1_info = { + IVB_D_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_ivybridge_d_gt2_info __initconst = { ++static const struct intel_device_info intel_ivybridge_d_gt2_info = { + IVB_D_PLATFORM, + .gt = 2, + }; +@@ -302,17 +302,17 @@ static const struct intel_device_info intel_ivybridge_d_gt2_info __initconst = { + .is_mobile = 1, \ + .has_l3_dpf = 1 + +-static const struct intel_device_info intel_ivybridge_m_gt1_info __initconst = { ++static const struct intel_device_info intel_ivybridge_m_gt1_info = { + IVB_M_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_ivybridge_m_gt2_info __initconst = { ++static const struct intel_device_info intel_ivybridge_m_gt2_info = { + IVB_M_PLATFORM, + .gt = 2, + }; + +-static const struct intel_device_info intel_ivybridge_q_info __initconst = { ++static const struct intel_device_info intel_ivybridge_q_info = { + GEN7_FEATURES, + .platform = INTEL_IVYBRIDGE, + .gt = 2, +@@ -320,7 +320,7 @@ static const struct intel_device_info intel_ivybridge_q_info __initconst = { + .has_l3_dpf = 1, + }; + +-static const struct intel_device_info intel_valleyview_info __initconst = { ++static const struct intel_device_info intel_valleyview_info = { + .platform = INTEL_VALLEYVIEW, + .gen = 7, + .is_lp = 1, +@@ -356,17 +356,17 @@ static const struct intel_device_info intel_valleyview_info __initconst = { + .platform = INTEL_HASWELL, \ + .has_l3_dpf = 1 + +-static const struct intel_device_info intel_haswell_gt1_info __initconst = { ++static const struct intel_device_info intel_haswell_gt1_info = { + HSW_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_haswell_gt2_info __initconst = { ++static const struct intel_device_info intel_haswell_gt2_info = { + HSW_PLATFORM, + .gt = 2, + }; + +-static const struct intel_device_info intel_haswell_gt3_info __initconst = { ++static const struct intel_device_info intel_haswell_gt3_info = { + HSW_PLATFORM, + .gt = 3, + }; +@@ -386,17 +386,17 @@ static const struct intel_device_info intel_haswell_gt3_info __initconst = { + .gen = 8, \ + .platform = INTEL_BROADWELL + +-static const struct intel_device_info intel_broadwell_gt1_info __initconst = { ++static const struct intel_device_info intel_broadwell_gt1_info = { + BDW_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_broadwell_gt2_info __initconst = { ++static const struct intel_device_info intel_broadwell_gt2_info = { + BDW_PLATFORM, + .gt = 2, + }; + +-static const struct intel_device_info intel_broadwell_rsvd_info __initconst = { ++static const struct intel_device_info intel_broadwell_rsvd_info = { + BDW_PLATFORM, + .gt = 3, + /* According to the device ID those devices are GT3, they were +@@ -404,13 +404,13 @@ static const struct intel_device_info intel_broadwell_rsvd_info __initconst = { + */ + }; + +-static const struct intel_device_info intel_broadwell_gt3_info __initconst = { ++static const struct intel_device_info intel_broadwell_gt3_info = { + BDW_PLATFORM, + .gt = 3, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, + }; + +-static const struct intel_device_info intel_cherryview_info __initconst = { ++static const struct intel_device_info intel_cherryview_info = { + .gen = 8, .num_pipes = 3, + .has_hotplug = 1, + .is_lp = 1, +@@ -453,12 +453,12 @@ static const struct intel_device_info intel_cherryview_info __initconst = { + .gen = 9, \ + .platform = INTEL_SKYLAKE + +-static const struct intel_device_info intel_skylake_gt1_info __initconst = { ++static const struct intel_device_info intel_skylake_gt1_info = { + SKL_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_skylake_gt2_info __initconst = { ++static const struct intel_device_info intel_skylake_gt2_info = { + SKL_PLATFORM, + .gt = 2, + }; +@@ -468,12 +468,12 @@ static const struct intel_device_info intel_skylake_gt2_info __initconst = { + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING + + +-static const struct intel_device_info intel_skylake_gt3_info __initconst = { ++static const struct intel_device_info intel_skylake_gt3_info = { + SKL_GT3_PLUS_PLATFORM, + .gt = 3, + }; + +-static const struct intel_device_info intel_skylake_gt4_info __initconst = { ++static const struct intel_device_info intel_skylake_gt4_info = { + SKL_GT3_PLUS_PLATFORM, + .gt = 4, + }; +@@ -509,13 +509,13 @@ static const struct intel_device_info intel_skylake_gt4_info __initconst = { + IVB_CURSOR_OFFSETS, \ + BDW_COLORS + +-static const struct intel_device_info intel_broxton_info __initconst = { ++static const struct intel_device_info intel_broxton_info = { + GEN9_LP_FEATURES, + .platform = INTEL_BROXTON, + .ddb_size = 512, + }; + +-static const struct intel_device_info intel_geminilake_info __initconst = { ++static const struct intel_device_info intel_geminilake_info = { + GEN9_LP_FEATURES, + .platform = INTEL_GEMINILAKE, + .ddb_size = 1024, +@@ -527,17 +527,17 @@ static const struct intel_device_info intel_geminilake_info __initconst = { + .gen = 9, \ + .platform = INTEL_KABYLAKE + +-static const struct intel_device_info intel_kabylake_gt1_info __initconst = { ++static const struct intel_device_info intel_kabylake_gt1_info = { + KBL_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_kabylake_gt2_info __initconst = { ++static const struct intel_device_info intel_kabylake_gt2_info = { + KBL_PLATFORM, + .gt = 2, + }; + +-static const struct intel_device_info intel_kabylake_gt3_info __initconst = { ++static const struct intel_device_info intel_kabylake_gt3_info = { + KBL_PLATFORM, + .gt = 3, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, +@@ -548,17 +548,17 @@ static const struct intel_device_info intel_kabylake_gt3_info __initconst = { + .gen = 9, \ + .platform = INTEL_COFFEELAKE + +-static const struct intel_device_info intel_coffeelake_gt1_info __initconst = { ++static const struct intel_device_info intel_coffeelake_gt1_info = { + CFL_PLATFORM, + .gt = 1, + }; + +-static const struct intel_device_info intel_coffeelake_gt2_info __initconst = { ++static const struct intel_device_info intel_coffeelake_gt2_info = { + CFL_PLATFORM, + .gt = 2, + }; + +-static const struct intel_device_info intel_coffeelake_gt3_info __initconst = { ++static const struct intel_device_info intel_coffeelake_gt3_info = { + CFL_PLATFORM, + .gt = 3, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, +@@ -569,7 +569,7 @@ static const struct intel_device_info intel_coffeelake_gt3_info __initconst = { + .ddb_size = 1024, \ + GLK_COLORS + +-static const struct intel_device_info intel_cannonlake_gt2_info __initconst = { ++static const struct intel_device_info intel_cannonlake_gt2_info = { + GEN10_FEATURES, + .is_alpha_support = 1, + .platform = INTEL_CANNONLAKE, +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index 158438bb0389..add4b2434aa3 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -5336,6 +5336,12 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, + */ + final->t8 = 1; + final->t9 = 1; ++ ++ /* ++ * HW has only a 100msec granularity for t11_t12 so round it up ++ * accordingly. ++ */ ++ final->t11_t12 = roundup(final->t11_t12, 100 * 10); + } + + static void +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 0c3f608131cf..b5f85d6f6bef 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -2643,7 +2643,6 @@ static const struct hid_device_id hid_ignore_list[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) }, +- { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, +@@ -2913,6 +2912,17 @@ bool hid_ignore(struct hid_device *hdev) + strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0) + return true; + break; ++ case USB_VENDOR_ID_ELAN: ++ /* ++ * Many Elan devices have a product id of 0x0401 and are handled ++ * by the elan_i2c input driver. But the ACPI HID ELAN0800 dev ++ * is not (and cannot be) handled by that driver -> ++ * Ignore all 0x0401 devs except for the ELAN0800 dev. ++ */ ++ if (hdev->product == 0x0401 && ++ strncmp(hdev->name, "ELAN0800", 8) != 0) ++ return true; ++ break; + } + + if (hdev->type == HID_TYPE_USBMOUSE && +diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c +index 2afaa8226342..46f977177faf 100644 +--- a/drivers/media/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb-core/dvb_frontend.c +@@ -2110,7 +2110,7 @@ static int dvb_frontend_handle_ioctl(struct file *file, + struct dvb_frontend *fe = dvbdev->priv; + struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; +- int i, err; ++ int i, err = -EOPNOTSUPP; + + dev_dbg(fe->dvb->device, "%s:\n", __func__); + +@@ -2145,6 +2145,7 @@ static int dvb_frontend_handle_ioctl(struct file *file, + } + } + kfree(tvp); ++ err = 0; + break; + } + case FE_GET_PROPERTY: { +@@ -2196,6 +2197,7 @@ static int dvb_frontend_handle_ioctl(struct file *file, + return -EFAULT; + } + kfree(tvp); ++ err = 0; + break; + } + +diff --git a/drivers/media/dvb-frontends/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c +index 0ee0df53b91b..79d5d89bc95e 100644 +--- a/drivers/media/dvb-frontends/ascot2e.c ++++ b/drivers/media/dvb-frontends/ascot2e.c +@@ -155,7 +155,9 @@ static int ascot2e_write_regs(struct ascot2e_priv *priv, + + static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val) + { +- return ascot2e_write_regs(priv, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return ascot2e_write_regs(priv, reg, &tmp, 1); + } + + static int ascot2e_read_regs(struct ascot2e_priv *priv, +diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c +index 48ee9bc00c06..ccbd84fd6428 100644 +--- a/drivers/media/dvb-frontends/cxd2841er.c ++++ b/drivers/media/dvb-frontends/cxd2841er.c +@@ -257,7 +257,9 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv, + static int cxd2841er_write_reg(struct cxd2841er_priv *priv, + u8 addr, u8 reg, u8 val) + { +- return cxd2841er_write_regs(priv, addr, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return cxd2841er_write_regs(priv, addr, reg, &tmp, 1); + } + + static int cxd2841er_read_regs(struct cxd2841er_priv *priv, +diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c +index 4bf5a551ba40..2ab8d83e5576 100644 +--- a/drivers/media/dvb-frontends/helene.c ++++ b/drivers/media/dvb-frontends/helene.c +@@ -331,7 +331,9 @@ static int helene_write_regs(struct helene_priv *priv, + + static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val) + { +- return helene_write_regs(priv, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return helene_write_regs(priv, reg, &tmp, 1); + } + + static int helene_read_regs(struct helene_priv *priv, +diff --git a/drivers/media/dvb-frontends/horus3a.c b/drivers/media/dvb-frontends/horus3a.c +index 68d759c4c52e..5c8b405f2ddc 100644 +--- a/drivers/media/dvb-frontends/horus3a.c ++++ b/drivers/media/dvb-frontends/horus3a.c +@@ -89,7 +89,9 @@ static int horus3a_write_regs(struct horus3a_priv *priv, + + static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val) + { +- return horus3a_write_regs(priv, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return horus3a_write_regs(priv, reg, &tmp, 1); + } + + static int horus3a_enter_power_save(struct horus3a_priv *priv) +diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c +index 5bb1e73a10b4..ce7c443d3eac 100644 +--- a/drivers/media/dvb-frontends/itd1000.c ++++ b/drivers/media/dvb-frontends/itd1000.c +@@ -95,8 +95,9 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg) + + static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v) + { +- int ret = itd1000_write_regs(state, r, &v, 1); +- state->shadow[r] = v; ++ u8 tmp = v; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ int ret = itd1000_write_regs(state, r, &tmp, 1); ++ state->shadow[r] = tmp; + return ret; + } + +diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c +index 961b9a2508e0..0b23cbc021b8 100644 +--- a/drivers/media/dvb-frontends/mt312.c ++++ b/drivers/media/dvb-frontends/mt312.c +@@ -142,7 +142,10 @@ static inline int mt312_readreg(struct mt312_state *state, + static inline int mt312_writereg(struct mt312_state *state, + const enum mt312_reg_addr reg, const u8 val) + { +- return mt312_write(state, reg, &val, 1); ++ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ ++ return mt312_write(state, reg, &tmp, 1); + } + + static inline u32 mt312_div(u32 a, u32 b) +diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c +index 02347598277a..db5dde3215f0 100644 +--- a/drivers/media/dvb-frontends/stb0899_drv.c ++++ b/drivers/media/dvb-frontends/stb0899_drv.c +@@ -539,7 +539,8 @@ int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, + + int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data) + { +- return stb0899_write_regs(state, reg, &data, 1); ++ u8 tmp = data; ++ return stb0899_write_regs(state, reg, &tmp, 1); + } + + /* +diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c +index 17a955d0031b..75509bec66e4 100644 +--- a/drivers/media/dvb-frontends/stb6100.c ++++ b/drivers/media/dvb-frontends/stb6100.c +@@ -226,12 +226,14 @@ static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int st + + static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data) + { ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ + if (unlikely(reg >= STB6100_NUMREGS)) { + dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg); + return -EREMOTEIO; + } +- data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set; +- return stb6100_write_reg_range(state, &data, reg, 1); ++ tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set; ++ return stb6100_write_reg_range(state, &tmp, reg, 1); + } + + +diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c +index f3529df8211d..1a726196c126 100644 +--- a/drivers/media/dvb-frontends/stv0367.c ++++ b/drivers/media/dvb-frontends/stv0367.c +@@ -166,7 +166,9 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len) + + static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data) + { +- return stv0367_writeregs(state, reg, &data, 1); ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return stv0367_writeregs(state, reg, &tmp, 1); + } + + static u8 stv0367_readreg(struct stv0367_state *state, u16 reg) +diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c +index 7ef469c0c866..2695e1eb6d9c 100644 +--- a/drivers/media/dvb-frontends/stv090x.c ++++ b/drivers/media/dvb-frontends/stv090x.c +@@ -755,7 +755,9 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 + + static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data) + { +- return stv090x_write_regs(state, reg, &data, 1); ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return stv090x_write_regs(state, reg, &tmp, 1); + } + + static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) +diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c +index 66eba38f1014..7e8e01389c55 100644 +--- a/drivers/media/dvb-frontends/stv6110x.c ++++ b/drivers/media/dvb-frontends/stv6110x.c +@@ -97,7 +97,9 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da + + static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) + { +- return stv6110x_write_regs(stv6110x, reg, &data, 1); ++ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return stv6110x_write_regs(stv6110x, reg, &tmp, 1); + } + + static int stv6110x_init(struct dvb_frontend *fe) +diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c +index 931e5c98da8a..b879e1571469 100644 +--- a/drivers/media/dvb-frontends/ts2020.c ++++ b/drivers/media/dvb-frontends/ts2020.c +@@ -368,7 +368,7 @@ static int ts2020_read_tuner_gain(struct dvb_frontend *fe, unsigned v_agc, + gain2 = clamp_t(long, gain2, 0, 13); + v_agc = clamp_t(long, v_agc, 400, 1100); + +- *_gain = -(gain1 * 2330 + ++ *_gain = -((__s64)gain1 * 2330 + + gain2 * 3500 + + v_agc * 24 / 10 * 10 + + 10000); +@@ -386,7 +386,7 @@ static int ts2020_read_tuner_gain(struct dvb_frontend *fe, unsigned v_agc, + gain3 = clamp_t(long, gain3, 0, 6); + v_agc = clamp_t(long, v_agc, 600, 1600); + +- *_gain = -(gain1 * 2650 + ++ *_gain = -((__s64)gain1 * 2650 + + gain2 * 3380 + + gain3 * 2850 + + v_agc * 176 / 100 * 10 - +diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c +index 623355fc2666..3208b866d1cb 100644 +--- a/drivers/media/dvb-frontends/zl10039.c ++++ b/drivers/media/dvb-frontends/zl10039.c +@@ -134,7 +134,9 @@ static inline int zl10039_writereg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, + const u8 val) + { +- return zl10039_write(state, reg, &val, 1); ++ const u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ ++ ++ return zl10039_write(state, reg, &tmp, 1); + } + + static int zl10039_init(struct dvb_frontend *fe) +diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h +index 5cdf95bdc4d1..0de136b0d8c8 100644 +--- a/drivers/media/platform/vivid/vivid-core.h ++++ b/drivers/media/platform/vivid/vivid-core.h +@@ -154,6 +154,7 @@ struct vivid_dev { + struct v4l2_ctrl_handler ctrl_hdl_streaming; + struct v4l2_ctrl_handler ctrl_hdl_sdtv_cap; + struct v4l2_ctrl_handler ctrl_hdl_loop_cap; ++ struct v4l2_ctrl_handler ctrl_hdl_fb; + struct video_device vid_cap_dev; + struct v4l2_ctrl_handler ctrl_hdl_vid_cap; + struct video_device vid_out_dev; +diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c +index 34731f71cc00..3f9d354827af 100644 +--- a/drivers/media/platform/vivid/vivid-ctrls.c ++++ b/drivers/media/platform/vivid/vivid-ctrls.c +@@ -120,9 +120,6 @@ static int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl) + clear_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags); + clear_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags); + break; +- case VIVID_CID_CLEAR_FB: +- vivid_clear_fb(dev); +- break; + case VIVID_CID_BUTTON: + dev->button_pressed = 30; + break; +@@ -274,8 +271,28 @@ static const struct v4l2_ctrl_config vivid_ctrl_disconnect = { + .type = V4L2_CTRL_TYPE_BUTTON, + }; + ++ ++/* Framebuffer Controls */ ++ ++static int vivid_fb_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct vivid_dev *dev = container_of(ctrl->handler, ++ struct vivid_dev, ctrl_hdl_fb); ++ ++ switch (ctrl->id) { ++ case VIVID_CID_CLEAR_FB: ++ vivid_clear_fb(dev); ++ break; ++ } ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops vivid_fb_ctrl_ops = { ++ .s_ctrl = vivid_fb_s_ctrl, ++}; ++ + static const struct v4l2_ctrl_config vivid_ctrl_clear_fb = { +- .ops = &vivid_user_gen_ctrl_ops, ++ .ops = &vivid_fb_ctrl_ops, + .id = VIVID_CID_CLEAR_FB, + .name = "Clear Framebuffer", + .type = V4L2_CTRL_TYPE_BUTTON, +@@ -1357,6 +1374,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, + struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming; + struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap; + struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap; ++ struct v4l2_ctrl_handler *hdl_fb = &dev->ctrl_hdl_fb; + struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap; + struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out; + struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap; +@@ -1384,10 +1402,12 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, + v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL); + v4l2_ctrl_handler_init(hdl_loop_cap, 1); + v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL); ++ v4l2_ctrl_handler_init(hdl_fb, 1); ++ v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_class, NULL); + v4l2_ctrl_handler_init(hdl_vid_cap, 55); + v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL); + v4l2_ctrl_handler_init(hdl_vid_out, 26); +- if (!no_error_inj) ++ if (!no_error_inj || dev->has_fb) + v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL); + v4l2_ctrl_handler_init(hdl_vbi_cap, 21); + v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL); +@@ -1561,7 +1581,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, + v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL); + + if (dev->has_fb) +- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_clear_fb, NULL); ++ v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_clear_fb, NULL); + + if (dev->has_radio_rx) { + v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL); +@@ -1658,6 +1678,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, + v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL); + v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL); + v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL); ++ v4l2_ctrl_add_handler(hdl_vid_cap, hdl_fb, NULL); + if (hdl_vid_cap->error) + return hdl_vid_cap->error; + dev->vid_cap_dev.ctrl_handler = hdl_vid_cap; +@@ -1666,6 +1687,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, + v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL); + v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL); + v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL); ++ v4l2_ctrl_add_handler(hdl_vid_out, hdl_fb, NULL); + if (hdl_vid_out->error) + return hdl_vid_out->error; + dev->vid_out_dev.ctrl_handler = hdl_vid_out; +@@ -1725,4 +1747,5 @@ void vivid_free_controls(struct vivid_dev *dev) + v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming); + v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap); + v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap); ++ v4l2_ctrl_handler_free(&dev->ctrl_hdl_fb); + } +diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c +index 5e320fa4a795..be26c029546b 100644 +--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c ++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c +@@ -494,18 +494,23 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, + + static int lme2510_return_status(struct dvb_usb_device *d) + { +- int ret = 0; ++ int ret; + u8 *data; + +- data = kzalloc(10, GFP_KERNEL); ++ data = kzalloc(6, GFP_KERNEL); + if (!data) + return -ENOMEM; + +- ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), +- 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); +- info("Firmware Status: %x (%x)", ret , data[2]); ++ ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), ++ 0x06, 0x80, 0x0302, 0x00, ++ data, 0x6, 200); ++ if (ret != 6) ++ ret = -EINVAL; ++ else ++ ret = data[2]; ++ ++ info("Firmware Status: %6ph", data); + +- ret = (ret < 0) ? -ENODEV : data[2]; + kfree(data); + return ret; + } +@@ -1071,8 +1076,6 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) + + if (adap->fe[0]) { + info("FE Found M88RS2000"); +- dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config, +- &d->i2c_adap); + st->i2c_tuner_gate_w = 5; + st->i2c_tuner_gate_r = 5; + st->i2c_tuner_addr = 0x60; +@@ -1138,17 +1141,18 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) + ret = st->tuner_config; + break; + case TUNER_RS2000: +- ret = st->tuner_config; ++ if (dvb_attach(ts2020_attach, adap->fe[0], ++ &ts2020_config, &d->i2c_adap)) ++ ret = st->tuner_config; + break; + default: + break; + } + +- if (ret) ++ if (ret) { + info("TUN Found %s tuner", tun_msg[ret]); +- else { +- info("TUN No tuner found --- resetting device"); +- lme_coldreset(d); ++ } else { ++ info("TUN No tuner found"); + return -ENODEV; + } + +@@ -1189,6 +1193,7 @@ static int lme2510_get_adapter_count(struct dvb_usb_device *d) + static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) + { + struct lme2510_state *st = d->priv; ++ int status; + + usb_reset_configuration(d->udev); + +@@ -1197,12 +1202,16 @@ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) + + st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; + +- if (lme2510_return_status(d) == 0x44) { ++ status = lme2510_return_status(d); ++ if (status == 0x44) { + *name = lme_firmware_switch(d, 0); + return COLD; + } + +- return 0; ++ if (status != 0x47) ++ return -EINVAL; ++ ++ return WARM; + } + + static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, +diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c +index 37dea0adc695..cfe86b4864b3 100644 +--- a/drivers/media/usb/dvb-usb/cxusb.c ++++ b/drivers/media/usb/dvb-usb/cxusb.c +@@ -677,6 +677,8 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int component, + case XC2028_RESET_CLK: + deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg); + break; ++ case XC2028_I2C_FLUSH: ++ break; + default: + deb_info("%s: unknown command %d, arg %d\n", __func__, + command, arg); +diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c +index 366b05529915..a9968fb1e8e4 100644 +--- a/drivers/media/usb/dvb-usb/dib0700_devices.c ++++ b/drivers/media/usb/dvb-usb/dib0700_devices.c +@@ -430,6 +430,7 @@ static int stk7700ph_xc3028_callback(void *ptr, int component, + state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); + break; + case XC2028_RESET_CLK: ++ case XC2028_I2C_FLUSH: + break; + default: + err("%s: unknown command %d, arg %d\n", __func__, +diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c +index dbe29c6c4d8b..1e8cbaf36896 100644 +--- a/drivers/media/usb/hdpvr/hdpvr-core.c ++++ b/drivers/media/usb/hdpvr/hdpvr-core.c +@@ -292,7 +292,7 @@ static int hdpvr_probe(struct usb_interface *interface, + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { + dev_err(&interface->dev, "v4l2_device_register failed\n"); +- goto error; ++ goto error_free_dev; + } + + mutex_init(&dev->io_mutex); +@@ -301,7 +301,7 @@ static int hdpvr_probe(struct usb_interface *interface, + dev->usbc_buf = kmalloc(64, GFP_KERNEL); + if (!dev->usbc_buf) { + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); +- goto error; ++ goto error_v4l2_unregister; + } + + init_waitqueue_head(&dev->wait_buffer); +@@ -339,13 +339,13 @@ static int hdpvr_probe(struct usb_interface *interface, + } + if (!dev->bulk_in_endpointAddr) { + v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n"); +- goto error; ++ goto error_put_usb; + } + + /* init the device */ + if (hdpvr_device_init(dev)) { + v4l2_err(&dev->v4l2_dev, "device init failed\n"); +- goto error; ++ goto error_put_usb; + } + + mutex_lock(&dev->io_mutex); +@@ -353,7 +353,7 @@ static int hdpvr_probe(struct usb_interface *interface, + mutex_unlock(&dev->io_mutex); + v4l2_err(&dev->v4l2_dev, + "allocating transfer buffers failed\n"); +- goto error; ++ goto error_put_usb; + } + mutex_unlock(&dev->io_mutex); + +@@ -361,7 +361,7 @@ static int hdpvr_probe(struct usb_interface *interface, + retval = hdpvr_register_i2c_adapter(dev); + if (retval < 0) { + v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n"); +- goto error; ++ goto error_free_buffers; + } + + client = hdpvr_register_ir_rx_i2c(dev); +@@ -394,13 +394,17 @@ static int hdpvr_probe(struct usb_interface *interface, + reg_fail: + #if IS_ENABLED(CONFIG_I2C) + i2c_del_adapter(&dev->i2c_adapter); ++error_free_buffers: + #endif ++ hdpvr_free_buffers(dev); ++error_put_usb: ++ usb_put_dev(dev->udev); ++ kfree(dev->usbc_buf); ++error_v4l2_unregister: ++ v4l2_device_unregister(&dev->v4l2_dev); ++error_free_dev: ++ kfree(dev); + error: +- if (dev) { +- flush_work(&dev->worker); +- /* this frees allocated memory */ +- hdpvr_delete(dev); +- } + return retval; + } + +diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +index 821f2aa299ae..cbeea8343a5c 100644 +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -18,8 +18,18 @@ + #include + #include + #include ++#include ++#include + #include + ++/* Use the same argument order as copy_in_user */ ++#define assign_in_user(to, from) \ ++({ \ ++ typeof(*from) __assign_tmp; \ ++ \ ++ get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \ ++}) ++ + static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { + long ret = -ENOIOCTLCMD; +@@ -46,135 +56,75 @@ struct v4l2_window32 { + __u8 global_alpha; + }; + +-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +-{ +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || +- copy_from_user(&kp->w, &up->w, sizeof(up->w)) || +- get_user(kp->field, &up->field) || +- get_user(kp->chromakey, &up->chromakey) || +- get_user(kp->clipcount, &up->clipcount) || +- get_user(kp->global_alpha, &up->global_alpha)) +- return -EFAULT; +- if (kp->clipcount > 2048) +- return -EINVAL; +- if (kp->clipcount) { +- struct v4l2_clip32 __user *uclips; +- struct v4l2_clip __user *kclips; +- int n = kp->clipcount; +- compat_caddr_t p; +- +- if (get_user(p, &up->clips)) +- return -EFAULT; +- uclips = compat_ptr(p); +- kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); +- kp->clips = kclips; +- while (--n >= 0) { +- if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) +- return -EFAULT; +- if (put_user(n ? kclips + 1 : NULL, &kclips->next)) +- return -EFAULT; +- uclips += 1; +- kclips += 1; +- } +- } else +- kp->clips = NULL; +- return 0; +-} +- +-static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +-{ +- if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || +- put_user(kp->field, &up->field) || +- put_user(kp->chromakey, &up->chromakey) || +- put_user(kp->clipcount, &up->clipcount) || +- put_user(kp->global_alpha, &up->global_alpha)) +- return -EFAULT; +- return 0; +-} +- +-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) +- return -EFAULT; +- return 0; +-} +- +-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, +- struct v4l2_pix_format_mplane __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane))) +- return -EFAULT; +- return 0; +-} +- +-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) ++static int get_v4l2_window32(struct v4l2_window __user *kp, ++ struct v4l2_window32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { +- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) +- return -EFAULT; +- return 0; +-} +- +-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, +- struct v4l2_pix_format_mplane __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane))) +- return -EFAULT; +- return 0; +-} +- +-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) +- return -EFAULT; +- return 0; +-} +- +-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) ++ struct v4l2_clip32 __user *uclips; ++ struct v4l2_clip __user *kclips; ++ compat_caddr_t p; ++ u32 clipcount; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ copy_in_user(&kp->w, &up->w, sizeof(up->w)) || ++ assign_in_user(&kp->field, &up->field) || ++ assign_in_user(&kp->chromakey, &up->chromakey) || ++ assign_in_user(&kp->global_alpha, &up->global_alpha) || ++ get_user(clipcount, &up->clipcount) || ++ put_user(clipcount, &kp->clipcount)) + return -EFAULT; +- return 0; +-} ++ if (clipcount > 2048) ++ return -EINVAL; ++ if (!clipcount) ++ return put_user(NULL, &kp->clips); + +-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format))) ++ if (get_user(p, &up->clips)) + return -EFAULT; +- return 0; +-} +- +-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format))) ++ uclips = compat_ptr(p); ++ if (aux_space < clipcount * sizeof(*kclips)) + return -EFAULT; +- return 0; +-} +- +-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up) +-{ +- if (copy_from_user(kp, up, sizeof(struct v4l2_sdr_format))) ++ kclips = aux_buf; ++ if (put_user(kclips, &kp->clips)) + return -EFAULT; +- return 0; +-} + +-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format *kp, struct v4l2_sdr_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_sdr_format))) +- return -EFAULT; ++ while (clipcount--) { ++ if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) ++ return -EFAULT; ++ if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next)) ++ return -EFAULT; ++ uclips++; ++ kclips++; ++ } + return 0; + } + +-static inline int get_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up) ++static int put_v4l2_window32(struct v4l2_window __user *kp, ++ struct v4l2_window32 __user *up) + { +- if (copy_from_user(kp, up, sizeof(struct v4l2_meta_format))) ++ struct v4l2_clip __user *kclips = kp->clips; ++ struct v4l2_clip32 __user *uclips; ++ compat_caddr_t p; ++ u32 clipcount; ++ ++ if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) || ++ assign_in_user(&up->field, &kp->field) || ++ assign_in_user(&up->chromakey, &kp->chromakey) || ++ assign_in_user(&up->global_alpha, &kp->global_alpha) || ++ get_user(clipcount, &kp->clipcount) || ++ put_user(clipcount, &up->clipcount)) + return -EFAULT; +- return 0; +-} ++ if (!clipcount) ++ return 0; + +-static inline int put_v4l2_meta_format(struct v4l2_meta_format *kp, struct v4l2_meta_format __user *up) +-{ +- if (copy_to_user(up, kp, sizeof(struct v4l2_meta_format))) ++ if (get_user(p, &up->clips)) + return -EFAULT; ++ uclips = compat_ptr(p); ++ while (clipcount--) { ++ if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c))) ++ return -EFAULT; ++ uclips++; ++ kclips++; ++ } + return 0; + } + +@@ -209,101 +159,164 @@ struct v4l2_create_buffers32 { + __u32 reserved[8]; + }; + +-static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size) + { +- if (get_user(kp->type, &up->type)) ++ u32 type; ++ ++ if (get_user(type, &up->type)) + return -EFAULT; + +- switch (kp->type) { ++ switch (type) { ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: { ++ u32 clipcount; ++ ++ if (get_user(clipcount, &up->fmt.win.clipcount)) ++ return -EFAULT; ++ if (clipcount > 2048) ++ return -EINVAL; ++ *size = clipcount * sizeof(struct v4l2_clip); ++ return 0; ++ } ++ default: ++ *size = 0; ++ return 0; ++ } ++} ++ ++static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size) ++{ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up))) ++ return -EFAULT; ++ return __bufsize_v4l2_format(up, size); ++} ++ ++static int __get_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up, ++ void __user *aux_buf, u32 aux_space) ++{ ++ u32 type; ++ ++ if (get_user(type, &up->type) || put_user(type, &kp->type)) ++ return -EFAULT; ++ ++ switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); ++ return copy_in_user(&kp->fmt.pix, &up->fmt.pix, ++ sizeof(kp->fmt.pix)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp, +- &up->fmt.pix_mp); ++ return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp, ++ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: +- return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); ++ return get_v4l2_window32(&kp->fmt.win, &up->fmt.win, ++ aux_buf, aux_space); + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: +- return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); ++ return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi, ++ sizeof(kp->fmt.vbi)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: +- return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); ++ return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced, ++ sizeof(kp->fmt.sliced)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: +- return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr); ++ return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr, ++ sizeof(kp->fmt.sdr)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_META_CAPTURE: +- return get_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta); ++ return copy_in_user(&kp->fmt.meta, &up->fmt.meta, ++ sizeof(kp->fmt.meta)) ? -EFAULT : 0; + default: +- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n", +- kp->type); + return -EINVAL; + } + } + +-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int get_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up, ++ void __user *aux_buf, u32 aux_space) ++{ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up))) ++ return -EFAULT; ++ return __get_v4l2_format32(kp, up, aux_buf, aux_space); ++} ++ ++static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up, ++ u32 *size) + { +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32))) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up))) + return -EFAULT; +- return __get_v4l2_format32(kp, up); ++ return __bufsize_v4l2_format(&up->format, size); + } + +-static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) ++static int get_v4l2_create32(struct v4l2_create_buffers __user *kp, ++ struct v4l2_create_buffers32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) || +- copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format))) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ copy_in_user(kp, up, ++ offsetof(struct v4l2_create_buffers32, format))) + return -EFAULT; +- return __get_v4l2_format32(&kp->format, &up->format); ++ return __get_v4l2_format32(&kp->format, &up->format, ++ aux_buf, aux_space); + } + +-static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int __put_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up) + { +- if (put_user(kp->type, &up->type)) ++ u32 type; ++ ++ if (get_user(type, &kp->type)) + return -EFAULT; + +- switch (kp->type) { ++ switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); ++ return copy_in_user(&up->fmt.pix, &kp->fmt.pix, ++ sizeof(kp->fmt.pix)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp, +- &up->fmt.pix_mp); ++ return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp, ++ sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); + case V4L2_BUF_TYPE_VBI_CAPTURE: + case V4L2_BUF_TYPE_VBI_OUTPUT: +- return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); ++ return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi, ++ sizeof(kp->fmt.vbi)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: +- return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); ++ return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced, ++ sizeof(kp->fmt.sliced)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_SDR_CAPTURE: + case V4L2_BUF_TYPE_SDR_OUTPUT: +- return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr); ++ return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr, ++ sizeof(kp->fmt.sdr)) ? -EFAULT : 0; + case V4L2_BUF_TYPE_META_CAPTURE: +- return put_v4l2_meta_format(&kp->fmt.meta, &up->fmt.meta); ++ return copy_in_user(&up->fmt.meta, &kp->fmt.meta, ++ sizeof(kp->fmt.meta)) ? -EFAULT : 0; + default: +- pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n", +- kp->type); + return -EINVAL; + } + } + +-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) ++static int put_v4l2_format32(struct v4l2_format __user *kp, ++ struct v4l2_format32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32))) ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) + return -EFAULT; + return __put_v4l2_format32(kp, up); + } + +-static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) ++static int put_v4l2_create32(struct v4l2_create_buffers __user *kp, ++ struct v4l2_create_buffers32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || +- copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) || +- copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ copy_in_user(up, kp, ++ offsetof(struct v4l2_create_buffers32, format)) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved))) + return -EFAULT; + return __put_v4l2_format32(&kp->format, &up->format); + } +@@ -317,25 +330,28 @@ struct v4l2_standard32 { + __u32 reserved[4]; + }; + +-static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) ++static int get_v4l2_standard32(struct v4l2_standard __user *kp, ++ struct v4l2_standard32 __user *up) + { + /* other fields are not set by the user, nor used by the driver */ +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || +- get_user(kp->index, &up->index)) ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->index, &up->index)) + return -EFAULT; + return 0; + } + +-static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) ++static int put_v4l2_standard32(struct v4l2_standard __user *kp, ++ struct v4l2_standard32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || +- put_user(kp->index, &up->index) || +- put_user(kp->id, &up->id) || +- copy_to_user(up->name, kp->name, 24) || +- copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || +- put_user(kp->framelines, &up->framelines) || +- copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) +- return -EFAULT; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->index, &kp->index) || ++ assign_in_user(&up->id, &kp->id) || ++ copy_in_user(up->name, kp->name, sizeof(up->name)) || ++ copy_in_user(&up->frameperiod, &kp->frameperiod, ++ sizeof(up->frameperiod)) || ++ assign_in_user(&up->framelines, &kp->framelines) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) ++ return -EFAULT; + return 0; + } + +@@ -374,136 +390,186 @@ struct v4l2_buffer32 { + __u32 reserved; + }; + +-static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, +- enum v4l2_memory memory) ++static int get_v4l2_plane32(struct v4l2_plane __user *up, ++ struct v4l2_plane32 __user *up32, ++ enum v4l2_memory memory) + { +- void __user *up_pln; +- compat_long_t p; ++ compat_ulong_t p; + + if (copy_in_user(up, up32, 2 * sizeof(__u32)) || +- copy_in_user(&up->data_offset, &up32->data_offset, +- sizeof(__u32))) ++ copy_in_user(&up->data_offset, &up32->data_offset, ++ sizeof(up->data_offset))) + return -EFAULT; + +- if (memory == V4L2_MEMORY_USERPTR) { +- if (get_user(p, &up32->m.userptr)) +- return -EFAULT; +- up_pln = compat_ptr(p); +- if (put_user((unsigned long)up_pln, &up->m.userptr)) ++ switch (memory) { ++ case V4L2_MEMORY_MMAP: ++ case V4L2_MEMORY_OVERLAY: ++ if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, ++ sizeof(up32->m.mem_offset))) + return -EFAULT; +- } else if (memory == V4L2_MEMORY_DMABUF) { +- if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int))) ++ break; ++ case V4L2_MEMORY_USERPTR: ++ if (get_user(p, &up32->m.userptr) || ++ put_user((unsigned long)compat_ptr(p), &up->m.userptr)) + return -EFAULT; +- } else { +- if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, +- sizeof(__u32))) ++ break; ++ case V4L2_MEMORY_DMABUF: ++ if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd))) + return -EFAULT; ++ break; + } + + return 0; + } + +-static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, +- enum v4l2_memory memory) ++static int put_v4l2_plane32(struct v4l2_plane __user *up, ++ struct v4l2_plane32 __user *up32, ++ enum v4l2_memory memory) + { ++ unsigned long p; ++ + if (copy_in_user(up32, up, 2 * sizeof(__u32)) || +- copy_in_user(&up32->data_offset, &up->data_offset, +- sizeof(__u32))) ++ copy_in_user(&up32->data_offset, &up->data_offset, ++ sizeof(up->data_offset))) + return -EFAULT; + +- /* For MMAP, driver might've set up the offset, so copy it back. +- * USERPTR stays the same (was userspace-provided), so no copying. */ +- if (memory == V4L2_MEMORY_MMAP) ++ switch (memory) { ++ case V4L2_MEMORY_MMAP: ++ case V4L2_MEMORY_OVERLAY: + if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, +- sizeof(__u32))) ++ sizeof(up->m.mem_offset))) ++ return -EFAULT; ++ break; ++ case V4L2_MEMORY_USERPTR: ++ if (get_user(p, &up->m.userptr) || ++ put_user((compat_ulong_t)ptr_to_compat((__force void *)p), ++ &up32->m.userptr)) + return -EFAULT; +- /* For DMABUF, driver might've set up the fd, so copy it back. */ +- if (memory == V4L2_MEMORY_DMABUF) +- if (copy_in_user(&up32->m.fd, &up->m.fd, +- sizeof(int))) ++ break; ++ case V4L2_MEMORY_DMABUF: ++ if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd))) + return -EFAULT; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size) ++{ ++ u32 type; ++ u32 length; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ get_user(type, &up->type) || ++ get_user(length, &up->length)) ++ return -EFAULT; + ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ if (length > VIDEO_MAX_PLANES) ++ return -EINVAL; ++ ++ /* ++ * We don't really care if userspace decides to kill itself ++ * by passing a very big length value ++ */ ++ *size = length * sizeof(struct v4l2_plane); ++ } else { ++ *size = 0; ++ } + return 0; + } + +-static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) ++static int get_v4l2_buffer32(struct v4l2_buffer __user *kp, ++ struct v4l2_buffer32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { ++ u32 type; ++ u32 length; ++ enum v4l2_memory memory; + struct v4l2_plane32 __user *uplane32; + struct v4l2_plane __user *uplane; + compat_caddr_t p; + int ret; + +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || +- get_user(kp->index, &up->index) || +- get_user(kp->type, &up->type) || +- get_user(kp->flags, &up->flags) || +- get_user(kp->memory, &up->memory) || +- get_user(kp->length, &up->length)) +- return -EFAULT; ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->index, &up->index) || ++ get_user(type, &up->type) || ++ put_user(type, &kp->type) || ++ assign_in_user(&kp->flags, &up->flags) || ++ get_user(memory, &up->memory) || ++ put_user(memory, &kp->memory) || ++ get_user(length, &up->length) || ++ put_user(length, &kp->length)) ++ return -EFAULT; + +- if (V4L2_TYPE_IS_OUTPUT(kp->type)) +- if (get_user(kp->bytesused, &up->bytesused) || +- get_user(kp->field, &up->field) || +- get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || +- get_user(kp->timestamp.tv_usec, +- &up->timestamp.tv_usec)) ++ if (V4L2_TYPE_IS_OUTPUT(type)) ++ if (assign_in_user(&kp->bytesused, &up->bytesused) || ++ assign_in_user(&kp->field, &up->field) || ++ assign_in_user(&kp->timestamp.tv_sec, ++ &up->timestamp.tv_sec) || ++ assign_in_user(&kp->timestamp.tv_usec, ++ &up->timestamp.tv_usec)) + return -EFAULT; + +- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { +- unsigned int num_planes; ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ u32 num_planes = length; + +- if (kp->length == 0) { +- kp->m.planes = NULL; +- /* num_planes == 0 is legal, e.g. when userspace doesn't +- * need planes array on DQBUF*/ +- return 0; +- } else if (kp->length > VIDEO_MAX_PLANES) { +- return -EINVAL; ++ if (num_planes == 0) { ++ /* ++ * num_planes == 0 is legal, e.g. when userspace doesn't ++ * need planes array on DQBUF ++ */ ++ return put_user(NULL, &kp->m.planes); + } ++ if (num_planes > VIDEO_MAX_PLANES) ++ return -EINVAL; + + if (get_user(p, &up->m.planes)) + return -EFAULT; + + uplane32 = compat_ptr(p); + if (!access_ok(VERIFY_READ, uplane32, +- kp->length * sizeof(struct v4l2_plane32))) ++ num_planes * sizeof(*uplane32))) + return -EFAULT; + +- /* We don't really care if userspace decides to kill itself +- * by passing a very big num_planes value */ +- uplane = compat_alloc_user_space(kp->length * +- sizeof(struct v4l2_plane)); +- kp->m.planes = (__force struct v4l2_plane *)uplane; ++ /* ++ * We don't really care if userspace decides to kill itself ++ * by passing a very big num_planes value ++ */ ++ if (aux_space < num_planes * sizeof(*uplane)) ++ return -EFAULT; + +- for (num_planes = 0; num_planes < kp->length; num_planes++) { +- ret = get_v4l2_plane32(uplane, uplane32, kp->memory); ++ uplane = aux_buf; ++ if (put_user((__force struct v4l2_plane *)uplane, ++ &kp->m.planes)) ++ return -EFAULT; ++ ++ while (num_planes--) { ++ ret = get_v4l2_plane32(uplane, uplane32, memory); + if (ret) + return ret; +- ++uplane; +- ++uplane32; ++ uplane++; ++ uplane32++; + } + } else { +- switch (kp->memory) { ++ switch (memory) { + case V4L2_MEMORY_MMAP: +- if (get_user(kp->m.offset, &up->m.offset)) ++ case V4L2_MEMORY_OVERLAY: ++ if (assign_in_user(&kp->m.offset, &up->m.offset)) + return -EFAULT; + break; +- case V4L2_MEMORY_USERPTR: +- { +- compat_long_t tmp; ++ case V4L2_MEMORY_USERPTR: { ++ compat_ulong_t userptr; + +- if (get_user(tmp, &up->m.userptr)) +- return -EFAULT; +- +- kp->m.userptr = (unsigned long)compat_ptr(tmp); +- } +- break; +- case V4L2_MEMORY_OVERLAY: +- if (get_user(kp->m.offset, &up->m.offset)) ++ if (get_user(userptr, &up->m.userptr) || ++ put_user((unsigned long)compat_ptr(userptr), ++ &kp->m.userptr)) + return -EFAULT; + break; ++ } + case V4L2_MEMORY_DMABUF: +- if (get_user(kp->m.fd, &up->m.fd)) ++ if (assign_in_user(&kp->m.fd, &up->m.fd)) + return -EFAULT; + break; + } +@@ -512,65 +578,70 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user + return 0; + } + +-static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) ++static int put_v4l2_buffer32(struct v4l2_buffer __user *kp, ++ struct v4l2_buffer32 __user *up) + { ++ u32 type; ++ u32 length; ++ enum v4l2_memory memory; + struct v4l2_plane32 __user *uplane32; + struct v4l2_plane __user *uplane; + compat_caddr_t p; +- int num_planes; + int ret; + +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || +- put_user(kp->index, &up->index) || +- put_user(kp->type, &up->type) || +- put_user(kp->flags, &up->flags) || +- put_user(kp->memory, &up->memory)) +- return -EFAULT; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->index, &kp->index) || ++ get_user(type, &kp->type) || ++ put_user(type, &up->type) || ++ assign_in_user(&up->flags, &kp->flags) || ++ get_user(memory, &kp->memory) || ++ put_user(memory, &up->memory)) ++ return -EFAULT; + +- if (put_user(kp->bytesused, &up->bytesused) || +- put_user(kp->field, &up->field) || +- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || +- put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || +- copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || +- put_user(kp->sequence, &up->sequence) || +- put_user(kp->reserved2, &up->reserved2) || +- put_user(kp->reserved, &up->reserved) || +- put_user(kp->length, &up->length)) +- return -EFAULT; ++ if (assign_in_user(&up->bytesused, &kp->bytesused) || ++ assign_in_user(&up->field, &kp->field) || ++ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) || ++ assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) || ++ copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) || ++ assign_in_user(&up->sequence, &kp->sequence) || ++ assign_in_user(&up->reserved2, &kp->reserved2) || ++ assign_in_user(&up->reserved, &kp->reserved) || ++ get_user(length, &kp->length) || ++ put_user(length, &up->length)) ++ return -EFAULT; ++ ++ if (V4L2_TYPE_IS_MULTIPLANAR(type)) { ++ u32 num_planes = length; + +- if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { +- num_planes = kp->length; + if (num_planes == 0) + return 0; + +- uplane = (__force struct v4l2_plane __user *)kp->m.planes; ++ if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes))) ++ return -EFAULT; + if (get_user(p, &up->m.planes)) + return -EFAULT; + uplane32 = compat_ptr(p); + +- while (--num_planes >= 0) { +- ret = put_v4l2_plane32(uplane, uplane32, kp->memory); ++ while (num_planes--) { ++ ret = put_v4l2_plane32(uplane, uplane32, memory); + if (ret) + return ret; + ++uplane; + ++uplane32; + } + } else { +- switch (kp->memory) { ++ switch (memory) { + case V4L2_MEMORY_MMAP: +- if (put_user(kp->m.offset, &up->m.offset)) ++ case V4L2_MEMORY_OVERLAY: ++ if (assign_in_user(&up->m.offset, &kp->m.offset)) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: +- if (put_user(kp->m.userptr, &up->m.userptr)) +- return -EFAULT; +- break; +- case V4L2_MEMORY_OVERLAY: +- if (put_user(kp->m.offset, &up->m.offset)) ++ if (assign_in_user(&up->m.userptr, &kp->m.userptr)) + return -EFAULT; + break; + case V4L2_MEMORY_DMABUF: +- if (put_user(kp->m.fd, &up->m.fd)) ++ if (assign_in_user(&up->m.fd, &kp->m.fd)) + return -EFAULT; + break; + } +@@ -595,30 +666,33 @@ struct v4l2_framebuffer32 { + } fmt; + }; + +-static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) ++static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp, ++ struct v4l2_framebuffer32 __user *up) + { +- u32 tmp; +- +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || +- get_user(tmp, &up->base) || +- get_user(kp->capability, &up->capability) || +- get_user(kp->flags, &up->flags) || +- copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt))) +- return -EFAULT; +- kp->base = (__force void *)compat_ptr(tmp); ++ compat_caddr_t tmp; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ get_user(tmp, &up->base) || ++ put_user((__force void *)compat_ptr(tmp), &kp->base) || ++ assign_in_user(&kp->capability, &up->capability) || ++ assign_in_user(&kp->flags, &up->flags) || ++ copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt))) ++ return -EFAULT; + return 0; + } + +-static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) ++static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp, ++ struct v4l2_framebuffer32 __user *up) + { +- u32 tmp = (u32)((unsigned long)kp->base); +- +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || +- put_user(tmp, &up->base) || +- put_user(kp->capability, &up->capability) || +- put_user(kp->flags, &up->flags) || +- copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt))) +- return -EFAULT; ++ void *base; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ get_user(base, &kp->base) || ++ put_user(ptr_to_compat(base), &up->base) || ++ assign_in_user(&up->capability, &kp->capability) || ++ assign_in_user(&up->flags, &kp->flags) || ++ copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt))) ++ return -EFAULT; + return 0; + } + +@@ -634,18 +708,22 @@ struct v4l2_input32 { + __u32 reserved[3]; + }; + +-/* The 64-bit v4l2_input struct has extra padding at the end of the struct. +- Otherwise it is identical to the 32-bit version. */ +-static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) ++/* ++ * The 64-bit v4l2_input struct has extra padding at the end of the struct. ++ * Otherwise it is identical to the 32-bit version. ++ */ ++static inline int get_v4l2_input32(struct v4l2_input __user *kp, ++ struct v4l2_input32 __user *up) + { +- if (copy_from_user(kp, up, sizeof(struct v4l2_input32))) ++ if (copy_in_user(kp, up, sizeof(*up))) + return -EFAULT; + return 0; + } + +-static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up) ++static inline int put_v4l2_input32(struct v4l2_input __user *kp, ++ struct v4l2_input32 __user *up) + { +- if (copy_to_user(up, kp, sizeof(struct v4l2_input32))) ++ if (copy_in_user(up, kp, sizeof(*up))) + return -EFAULT; + return 0; + } +@@ -669,60 +747,95 @@ struct v4l2_ext_control32 { + }; + } __attribute__ ((packed)); + +-/* The following function really belong in v4l2-common, but that causes +- a circular dependency between modules. We need to think about this, but +- for now this will do. */ +- +-/* Return non-zero if this control is a pointer type. Currently only +- type STRING is a pointer type. */ +-static inline int ctrl_is_pointer(u32 id) ++/* Return true if this control is a pointer type. */ ++static inline bool ctrl_is_pointer(struct file *file, u32 id) + { +- switch (id) { +- case V4L2_CID_RDS_TX_PS_NAME: +- case V4L2_CID_RDS_TX_RADIO_TEXT: +- return 1; +- default: +- return 0; ++ struct video_device *vdev = video_devdata(file); ++ struct v4l2_fh *fh = NULL; ++ struct v4l2_ctrl_handler *hdl = NULL; ++ struct v4l2_query_ext_ctrl qec = { id }; ++ const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; ++ ++ if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) ++ fh = file->private_data; ++ ++ if (fh && fh->ctrl_handler) ++ hdl = fh->ctrl_handler; ++ else if (vdev->ctrl_handler) ++ hdl = vdev->ctrl_handler; ++ ++ if (hdl) { ++ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id); ++ ++ return ctrl && ctrl->is_ptr; + } ++ ++ if (!ops || !ops->vidioc_query_ext_ctrl) ++ return false; ++ ++ return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && ++ (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD); ++} ++ ++static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up, ++ u32 *size) ++{ ++ u32 count; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ get_user(count, &up->count)) ++ return -EFAULT; ++ if (count > V4L2_CID_MAX_CTRLS) ++ return -EINVAL; ++ *size = count * sizeof(struct v4l2_ext_control); ++ return 0; + } + +-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) ++static int get_v4l2_ext_controls32(struct file *file, ++ struct v4l2_ext_controls __user *kp, ++ struct v4l2_ext_controls32 __user *up, ++ void __user *aux_buf, u32 aux_space) + { + struct v4l2_ext_control32 __user *ucontrols; + struct v4l2_ext_control __user *kcontrols; +- unsigned int n; ++ u32 count; ++ u32 n; + compat_caddr_t p; + +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || +- get_user(kp->which, &up->which) || +- get_user(kp->count, &up->count) || +- get_user(kp->error_idx, &up->error_idx) || +- copy_from_user(kp->reserved, up->reserved, +- sizeof(kp->reserved))) +- return -EFAULT; +- if (kp->count == 0) { +- kp->controls = NULL; +- return 0; +- } else if (kp->count > V4L2_CID_MAX_CTRLS) { ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->which, &up->which) || ++ get_user(count, &up->count) || ++ put_user(count, &kp->count) || ++ assign_in_user(&kp->error_idx, &up->error_idx) || ++ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved))) ++ return -EFAULT; ++ ++ if (count == 0) ++ return put_user(NULL, &kp->controls); ++ if (count > V4L2_CID_MAX_CTRLS) + return -EINVAL; +- } + if (get_user(p, &up->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); +- if (!access_ok(VERIFY_READ, ucontrols, +- kp->count * sizeof(struct v4l2_ext_control32))) ++ if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols))) + return -EFAULT; +- kcontrols = compat_alloc_user_space(kp->count * +- sizeof(struct v4l2_ext_control)); +- kp->controls = (__force struct v4l2_ext_control *)kcontrols; +- for (n = 0; n < kp->count; n++) { ++ if (aux_space < count * sizeof(*kcontrols)) ++ return -EFAULT; ++ kcontrols = aux_buf; ++ if (put_user((__force struct v4l2_ext_control *)kcontrols, ++ &kp->controls)) ++ return -EFAULT; ++ ++ for (n = 0; n < count; n++) { + u32 id; + + if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols))) + return -EFAULT; ++ + if (get_user(id, &kcontrols->id)) + return -EFAULT; +- if (ctrl_is_pointer(id)) { ++ ++ if (ctrl_is_pointer(file, id)) { + void __user *s; + + if (get_user(p, &ucontrols->string)) +@@ -737,43 +850,55 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext + return 0; + } + +-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) ++static int put_v4l2_ext_controls32(struct file *file, ++ struct v4l2_ext_controls __user *kp, ++ struct v4l2_ext_controls32 __user *up) + { + struct v4l2_ext_control32 __user *ucontrols; +- struct v4l2_ext_control __user *kcontrols = +- (__force struct v4l2_ext_control __user *)kp->controls; +- int n = kp->count; ++ struct v4l2_ext_control __user *kcontrols; ++ u32 count; ++ u32 n; + compat_caddr_t p; + +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || +- put_user(kp->which, &up->which) || +- put_user(kp->count, &up->count) || +- put_user(kp->error_idx, &up->error_idx) || +- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) +- return -EFAULT; +- if (!kp->count) +- return 0; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->which, &kp->which) || ++ get_user(count, &kp->count) || ++ put_user(count, &up->count) || ++ assign_in_user(&up->error_idx, &kp->error_idx) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) || ++ get_user(kcontrols, &kp->controls)) ++ return -EFAULT; + ++ if (!count) ++ return 0; + if (get_user(p, &up->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); +- if (!access_ok(VERIFY_WRITE, ucontrols, +- n * sizeof(struct v4l2_ext_control32))) ++ if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols))) + return -EFAULT; + +- while (--n >= 0) { +- unsigned size = sizeof(*ucontrols); ++ for (n = 0; n < count; n++) { ++ unsigned int size = sizeof(*ucontrols); + u32 id; + +- if (get_user(id, &kcontrols->id)) ++ if (get_user(id, &kcontrols->id) || ++ put_user(id, &ucontrols->id) || ++ assign_in_user(&ucontrols->size, &kcontrols->size) || ++ copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2, ++ sizeof(ucontrols->reserved2))) + return -EFAULT; +- /* Do not modify the pointer when copying a pointer control. +- The contents of the pointer was changed, not the pointer +- itself. */ +- if (ctrl_is_pointer(id)) ++ ++ /* ++ * Do not modify the pointer when copying a pointer control. ++ * The contents of the pointer was changed, not the pointer ++ * itself. ++ */ ++ if (ctrl_is_pointer(file, id)) + size -= sizeof(ucontrols->value64); ++ + if (copy_in_user(ucontrols, kcontrols, size)) + return -EFAULT; ++ + ucontrols++; + kcontrols++; + } +@@ -793,18 +918,19 @@ struct v4l2_event32 { + __u32 reserved[8]; + }; + +-static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up) ++static int put_v4l2_event32(struct v4l2_event __user *kp, ++ struct v4l2_event32 __user *up) + { +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) || +- put_user(kp->type, &up->type) || +- copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || +- put_user(kp->pending, &up->pending) || +- put_user(kp->sequence, &up->sequence) || +- put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || +- put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) || +- put_user(kp->id, &up->id) || +- copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) +- return -EFAULT; ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->type, &kp->type) || ++ copy_in_user(&up->u, &kp->u, sizeof(kp->u)) || ++ assign_in_user(&up->pending, &kp->pending) || ++ assign_in_user(&up->sequence, &kp->sequence) || ++ assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) || ++ assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) || ++ assign_in_user(&up->id, &kp->id) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) ++ return -EFAULT; + return 0; + } + +@@ -816,32 +942,35 @@ struct v4l2_edid32 { + compat_caddr_t edid; + }; + +-static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) ++static int get_v4l2_edid32(struct v4l2_edid __user *kp, ++ struct v4l2_edid32 __user *up) + { +- u32 tmp; +- +- if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) || +- get_user(kp->pad, &up->pad) || +- get_user(kp->start_block, &up->start_block) || +- get_user(kp->blocks, &up->blocks) || +- get_user(tmp, &up->edid) || +- copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved))) +- return -EFAULT; +- kp->edid = (__force u8 *)compat_ptr(tmp); ++ compat_uptr_t tmp; ++ ++ if (!access_ok(VERIFY_READ, up, sizeof(*up)) || ++ assign_in_user(&kp->pad, &up->pad) || ++ assign_in_user(&kp->start_block, &up->start_block) || ++ assign_in_user(&kp->blocks, &up->blocks) || ++ get_user(tmp, &up->edid) || ++ put_user(compat_ptr(tmp), &kp->edid) || ++ copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved))) ++ return -EFAULT; + return 0; + } + +-static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) ++static int put_v4l2_edid32(struct v4l2_edid __user *kp, ++ struct v4l2_edid32 __user *up) + { +- u32 tmp = (u32)((unsigned long)kp->edid); +- +- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) || +- put_user(kp->pad, &up->pad) || +- put_user(kp->start_block, &up->start_block) || +- put_user(kp->blocks, &up->blocks) || +- put_user(tmp, &up->edid) || +- copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved))) +- return -EFAULT; ++ void *edid; ++ ++ if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || ++ assign_in_user(&up->pad, &kp->pad) || ++ assign_in_user(&up->start_block, &kp->start_block) || ++ assign_in_user(&up->blocks, &kp->blocks) || ++ get_user(edid, &kp->edid) || ++ put_user(ptr_to_compat(edid), &up->edid) || ++ copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved))) ++ return -EFAULT; + return 0; + } + +@@ -873,22 +1002,23 @@ static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up) + #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32) + #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32) + ++static int alloc_userspace(unsigned int size, u32 aux_space, ++ void __user **up_native) ++{ ++ *up_native = compat_alloc_user_space(size + aux_space); ++ if (!*up_native) ++ return -ENOMEM; ++ if (clear_user(*up_native, size)) ++ return -EFAULT; ++ return 0; ++} ++ + static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +- union { +- struct v4l2_format v2f; +- struct v4l2_buffer v2b; +- struct v4l2_framebuffer v2fb; +- struct v4l2_input v2i; +- struct v4l2_standard v2s; +- struct v4l2_ext_controls v2ecs; +- struct v4l2_event v2ev; +- struct v4l2_create_buffers v2crt; +- struct v4l2_edid v2edid; +- unsigned long vx; +- int vi; +- } karg; + void __user *up = compat_ptr(arg); ++ void __user *up_native = NULL; ++ void __user *aux_buf; ++ u32 aux_space; + int compatible_arg = 1; + long err = 0; + +@@ -927,30 +1057,52 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + case VIDIOC_STREAMOFF: + case VIDIOC_S_INPUT: + case VIDIOC_S_OUTPUT: +- err = get_user(karg.vi, (s32 __user *)up); ++ err = alloc_userspace(sizeof(unsigned int), 0, &up_native); ++ if (!err && assign_in_user((unsigned int __user *)up_native, ++ (compat_uint_t __user *)up)) ++ err = -EFAULT; + compatible_arg = 0; + break; + + case VIDIOC_G_INPUT: + case VIDIOC_G_OUTPUT: ++ err = alloc_userspace(sizeof(unsigned int), 0, &up_native); + compatible_arg = 0; + break; + + case VIDIOC_G_EDID: + case VIDIOC_S_EDID: +- err = get_v4l2_edid32(&karg.v2edid, up); ++ err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native); ++ if (!err) ++ err = get_v4l2_edid32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: +- err = get_v4l2_format32(&karg.v2f, up); ++ err = bufsize_v4l2_format(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_format), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_format); ++ err = get_v4l2_format32(up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + + case VIDIOC_CREATE_BUFS: +- err = get_v4l2_create32(&karg.v2crt, up); ++ err = bufsize_v4l2_create(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_create_buffers), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_create_buffers); ++ err = get_v4l2_create32(up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + +@@ -958,36 +1110,63 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: +- err = get_v4l2_buffer32(&karg.v2b, up); ++ err = bufsize_v4l2_buffer(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_buffer), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_buffer); ++ err = get_v4l2_buffer32(up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + + case VIDIOC_S_FBUF: +- err = get_v4l2_framebuffer32(&karg.v2fb, up); ++ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, ++ &up_native); ++ if (!err) ++ err = get_v4l2_framebuffer32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_G_FBUF: ++ err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0, ++ &up_native); + compatible_arg = 0; + break; + + case VIDIOC_ENUMSTD: +- err = get_v4l2_standard32(&karg.v2s, up); ++ err = alloc_userspace(sizeof(struct v4l2_standard), 0, ++ &up_native); ++ if (!err) ++ err = get_v4l2_standard32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_ENUMINPUT: +- err = get_v4l2_input32(&karg.v2i, up); ++ err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native); ++ if (!err) ++ err = get_v4l2_input32(up_native, up); + compatible_arg = 0; + break; + + case VIDIOC_G_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: +- err = get_v4l2_ext_controls32(&karg.v2ecs, up); ++ err = bufsize_v4l2_ext_controls(up, &aux_space); ++ if (!err) ++ err = alloc_userspace(sizeof(struct v4l2_ext_controls), ++ aux_space, &up_native); ++ if (!err) { ++ aux_buf = up_native + sizeof(struct v4l2_ext_controls); ++ err = get_v4l2_ext_controls32(file, up_native, up, ++ aux_buf, aux_space); ++ } + compatible_arg = 0; + break; + case VIDIOC_DQEVENT: ++ err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native); + compatible_arg = 0; + break; + } +@@ -996,26 +1175,26 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + + if (compatible_arg) + err = native_ioctl(file, cmd, (unsigned long)up); +- else { +- mm_segment_t old_fs = get_fs(); ++ else ++ err = native_ioctl(file, cmd, (unsigned long)up_native); + +- set_fs(KERNEL_DS); +- err = native_ioctl(file, cmd, (unsigned long)&karg); +- set_fs(old_fs); +- } ++ if (err == -ENOTTY) ++ return err; + +- /* Special case: even after an error we need to put the +- results back for these ioctls since the error_idx will +- contain information on which control failed. */ ++ /* ++ * Special case: even after an error we need to put the ++ * results back for these ioctls since the error_idx will ++ * contain information on which control failed. ++ */ + switch (cmd) { + case VIDIOC_G_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: +- if (put_v4l2_ext_controls32(&karg.v2ecs, up)) ++ if (put_v4l2_ext_controls32(file, up_native, up)) + err = -EFAULT; + break; + case VIDIOC_S_EDID: +- if (put_v4l2_edid32(&karg.v2edid, up)) ++ if (put_v4l2_edid32(up_native, up)) + err = -EFAULT; + break; + } +@@ -1027,43 +1206,46 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar + case VIDIOC_S_OUTPUT: + case VIDIOC_G_INPUT: + case VIDIOC_G_OUTPUT: +- err = put_user(((s32)karg.vi), (s32 __user *)up); ++ if (assign_in_user((compat_uint_t __user *)up, ++ ((unsigned int __user *)up_native))) ++ err = -EFAULT; + break; + + case VIDIOC_G_FBUF: +- err = put_v4l2_framebuffer32(&karg.v2fb, up); ++ err = put_v4l2_framebuffer32(up_native, up); + break; + + case VIDIOC_DQEVENT: +- err = put_v4l2_event32(&karg.v2ev, up); ++ err = put_v4l2_event32(up_native, up); + break; + + case VIDIOC_G_EDID: +- err = put_v4l2_edid32(&karg.v2edid, up); ++ err = put_v4l2_edid32(up_native, up); + break; + + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: +- err = put_v4l2_format32(&karg.v2f, up); ++ err = put_v4l2_format32(up_native, up); + break; + + case VIDIOC_CREATE_BUFS: +- err = put_v4l2_create32(&karg.v2crt, up); ++ err = put_v4l2_create32(up_native, up); + break; + ++ case VIDIOC_PREPARE_BUF: + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: +- err = put_v4l2_buffer32(&karg.v2b, up); ++ err = put_v4l2_buffer32(up_native, up); + break; + + case VIDIOC_ENUMSTD: +- err = put_v4l2_standard32(&karg.v2s, up); ++ err = put_v4l2_standard32(up_native, up); + break; + + case VIDIOC_ENUMINPUT: +- err = put_v4l2_input32(&karg.v2i, up); ++ err = put_v4l2_input32(up_native, up); + break; + } + return err; +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 79614992ee21..89e0878ce0a0 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1311,52 +1311,50 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_fmtdesc *p = arg; +- struct video_device *vfd = video_devdata(file); +- bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; +- bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; +- bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; +- bool is_rx = vfd->vfl_dir != VFL_DIR_TX; +- bool is_tx = vfd->vfl_dir != VFL_DIR_RX; +- int ret = -EINVAL; ++ int ret = check_fmt(file, p->type); ++ ++ if (ret) ++ return ret; ++ ret = -EINVAL; + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: +- if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_enum_fmt_vid_cap)) ++ if (unlikely(!ops->vidioc_enum_fmt_vid_cap)) + break; + ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg); + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane)) ++ if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane)) + break; + ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay)) ++ if (unlikely(!ops->vidioc_enum_fmt_vid_overlay)) + break; + ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out)) ++ if (unlikely(!ops->vidioc_enum_fmt_vid_out)) + break; + ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane)) ++ if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane)) + break; + ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); + break; + case V4L2_BUF_TYPE_SDR_CAPTURE: +- if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap)) ++ if (unlikely(!ops->vidioc_enum_fmt_sdr_cap)) + break; + ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg); + break; + case V4L2_BUF_TYPE_SDR_OUTPUT: +- if (unlikely(!is_tx || !is_sdr || !ops->vidioc_enum_fmt_sdr_out)) ++ if (unlikely(!ops->vidioc_enum_fmt_sdr_out)) + break; + ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg); + break; + case V4L2_BUF_TYPE_META_CAPTURE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_meta_cap)) ++ if (unlikely(!ops->vidioc_enum_fmt_meta_cap)) + break; + ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg); + break; +@@ -1370,13 +1368,10 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_format *p = arg; +- struct video_device *vfd = video_devdata(file); +- bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; +- bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; +- bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; +- bool is_rx = vfd->vfl_dir != VFL_DIR_TX; +- bool is_tx = vfd->vfl_dir != VFL_DIR_RX; +- int ret; ++ int ret = check_fmt(file, p->type); ++ ++ if (ret) ++ return ret; + + /* + * fmt can't be cleared for these overlay types due to the 'clips' +@@ -1404,7 +1399,7 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: +- if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_g_fmt_vid_cap)) ++ if (unlikely(!ops->vidioc_g_fmt_vid_cap)) + break; + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); +@@ -1412,23 +1407,15 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane)) +- break; + return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay)) +- break; + return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: +- if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap)) +- break; + return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: +- if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap)) +- break; + return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out)) ++ if (unlikely(!ops->vidioc_g_fmt_vid_out)) + break; + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); +@@ -1436,32 +1423,18 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane)) +- break; + return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay)) +- break; + return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: +- if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out)) +- break; + return ops->vidioc_g_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: +- if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out)) +- break; + return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SDR_CAPTURE: +- if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap)) +- break; + return ops->vidioc_g_fmt_sdr_cap(file, fh, arg); + case V4L2_BUF_TYPE_SDR_OUTPUT: +- if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out)) +- break; + return ops->vidioc_g_fmt_sdr_out(file, fh, arg); + case V4L2_BUF_TYPE_META_CAPTURE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_meta_cap)) +- break; + return ops->vidioc_g_fmt_meta_cap(file, fh, arg); + } + return -EINVAL; +@@ -1487,12 +1460,10 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, + { + struct v4l2_format *p = arg; + struct video_device *vfd = video_devdata(file); +- bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; +- bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; +- bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; +- bool is_rx = vfd->vfl_dir != VFL_DIR_TX; +- bool is_tx = vfd->vfl_dir != VFL_DIR_RX; +- int ret; ++ int ret = check_fmt(file, p->type); ++ ++ if (ret) ++ return ret; + + ret = v4l_enable_media_source(vfd); + if (ret) +@@ -1501,37 +1472,37 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: +- if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_s_fmt_vid_cap)) ++ if (unlikely(!ops->vidioc_s_fmt_vid_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); + /* just in case the driver zeroed it again */ + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; +- if (is_tch) ++ if (vfd->vfl_type == VFL_TYPE_TOUCH) + v4l_pix_format_touch(&p->fmt.pix); + return ret; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane)) ++ if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay)) ++ if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_s_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: +- if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap)) ++ if (unlikely(!ops->vidioc_s_fmt_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: +- if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap)) ++ if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out)) ++ if (unlikely(!ops->vidioc_s_fmt_vid_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_s_fmt_vid_out(file, fh, arg); +@@ -1539,37 +1510,37 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane)) ++ if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay)) ++ if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: +- if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out)) ++ if (unlikely(!ops->vidioc_s_fmt_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_s_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: +- if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out)) ++ if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SDR_CAPTURE: +- if (unlikely(!is_rx || !is_sdr || !ops->vidioc_s_fmt_sdr_cap)) ++ if (unlikely(!ops->vidioc_s_fmt_sdr_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sdr); + return ops->vidioc_s_fmt_sdr_cap(file, fh, arg); + case V4L2_BUF_TYPE_SDR_OUTPUT: +- if (unlikely(!is_tx || !is_sdr || !ops->vidioc_s_fmt_sdr_out)) ++ if (unlikely(!ops->vidioc_s_fmt_sdr_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sdr); + return ops->vidioc_s_fmt_sdr_out(file, fh, arg); + case V4L2_BUF_TYPE_META_CAPTURE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_meta_cap)) ++ if (unlikely(!ops->vidioc_s_fmt_meta_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.meta); + return ops->vidioc_s_fmt_meta_cap(file, fh, arg); +@@ -1581,19 +1552,16 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_format *p = arg; +- struct video_device *vfd = video_devdata(file); +- bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; +- bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; +- bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH; +- bool is_rx = vfd->vfl_dir != VFL_DIR_TX; +- bool is_tx = vfd->vfl_dir != VFL_DIR_RX; +- int ret; ++ int ret = check_fmt(file, p->type); ++ ++ if (ret) ++ return ret; + + v4l_sanitize_format(p); + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: +- if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_try_fmt_vid_cap)) ++ if (unlikely(!ops->vidioc_try_fmt_vid_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); +@@ -1601,27 +1569,27 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane)) ++ if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay)) ++ if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_try_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: +- if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap)) ++ if (unlikely(!ops->vidioc_try_fmt_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: +- if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap)) ++ if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out)) ++ if (unlikely(!ops->vidioc_try_fmt_vid_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix); + ret = ops->vidioc_try_fmt_vid_out(file, fh, arg); +@@ -1629,37 +1597,37 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, + p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; + return ret; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane)) ++ if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane)) + break; + CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func); + return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: +- if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay)) ++ if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) + break; + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: +- if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out)) ++ if (unlikely(!ops->vidioc_try_fmt_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_try_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: +- if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out)) ++ if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SDR_CAPTURE: +- if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap)) ++ if (unlikely(!ops->vidioc_try_fmt_sdr_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.sdr); + return ops->vidioc_try_fmt_sdr_cap(file, fh, arg); + case V4L2_BUF_TYPE_SDR_OUTPUT: +- if (unlikely(!is_tx || !is_sdr || !ops->vidioc_try_fmt_sdr_out)) ++ if (unlikely(!ops->vidioc_try_fmt_sdr_out)) + break; + CLEAR_AFTER_FIELD(p, fmt.sdr); + return ops->vidioc_try_fmt_sdr_out(file, fh, arg); + case V4L2_BUF_TYPE_META_CAPTURE: +- if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_meta_cap)) ++ if (unlikely(!ops->vidioc_try_fmt_meta_cap)) + break; + CLEAR_AFTER_FIELD(p, fmt.meta); + return ops->vidioc_try_fmt_meta_cap(file, fh, arg); +@@ -2927,8 +2895,11 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + + /* Handles IOCTL */ + err = func(file, cmd, parg); +- if (err == -ENOIOCTLCMD) ++ if (err == -ENOTTY || err == -ENOIOCTLCMD) { + err = -ENOTTY; ++ goto out; ++ } ++ + if (err == 0) { + if (cmd == VIDIOC_DQBUF) + trace_v4l2_dqbuf(video_devdata(file)->minor, parg); +diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c +index dd56a671ea42..2a978d9832a7 100644 +--- a/drivers/mtd/nand/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/brcmnand/brcmnand.c +@@ -2193,16 +2193,9 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) + if (ctrl->nand_version >= 0x0702) + tmp |= ACC_CONTROL_RD_ERASED; + tmp &= ~ACC_CONTROL_FAST_PGM_RDIN; +- if (ctrl->features & BRCMNAND_HAS_PREFETCH) { +- /* +- * FIXME: Flash DMA + prefetch may see spurious erased-page ECC +- * errors +- */ +- if (has_flash_dma(ctrl)) +- tmp &= ~ACC_CONTROL_PREFETCH; +- else +- tmp |= ACC_CONTROL_PREFETCH; +- } ++ if (ctrl->features & BRCMNAND_HAS_PREFETCH) ++ tmp &= ~ACC_CONTROL_PREFETCH; ++ + nand_writereg(ctrl, offs, tmp); + + return 0; +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 6135d007a068..9c702b46c6ee 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2199,6 +2199,7 @@ EXPORT_SYMBOL(nand_write_oob_syndrome); + static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) + { ++ unsigned int max_bitflips = 0; + int page, realpage, chipnr; + struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_ecc_stats stats; +@@ -2256,6 +2257,8 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, + nand_wait_ready(mtd); + } + ++ max_bitflips = max_t(unsigned int, max_bitflips, ret); ++ + readlen -= len; + if (!readlen) + break; +@@ -2281,7 +2284,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, + if (mtd->ecc_stats.failed - stats.failed) + return -EBADMSG; + +- return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; ++ return max_bitflips; + } + + /** +diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c +index 82244be3e766..958974821582 100644 +--- a/drivers/mtd/nand/sunxi_nand.c ++++ b/drivers/mtd/nand/sunxi_nand.c +@@ -1853,8 +1853,14 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, + + /* Add ECC info retrieval from DT */ + for (i = 0; i < ARRAY_SIZE(strengths); i++) { +- if (ecc->strength <= strengths[i]) ++ if (ecc->strength <= strengths[i]) { ++ /* ++ * Update ecc->strength value with the actual strength ++ * that will be used by the ECC engine. ++ */ ++ ecc->strength = strengths[i]; + break; ++ } + } + + if (i >= ARRAY_SIZE(strengths)) { +diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c +index b210fdb31c98..b1fc28f63882 100644 +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -99,6 +99,8 @@ struct ubiblock { + + /* Linked list of all ubiblock instances */ + static LIST_HEAD(ubiblock_devices); ++static DEFINE_IDR(ubiblock_minor_idr); ++/* Protects ubiblock_devices and ubiblock_minor_idr */ + static DEFINE_MUTEX(devices_mutex); + static int ubiblock_major; + +@@ -351,8 +353,6 @@ static const struct blk_mq_ops ubiblock_mq_ops = { + .init_request = ubiblock_init_request, + }; + +-static DEFINE_IDR(ubiblock_minor_idr); +- + int ubiblock_create(struct ubi_volume_info *vi) + { + struct ubiblock *dev; +@@ -365,14 +365,15 @@ int ubiblock_create(struct ubi_volume_info *vi) + /* Check that the volume isn't already handled */ + mutex_lock(&devices_mutex); + if (find_dev_nolock(vi->ubi_num, vi->vol_id)) { +- mutex_unlock(&devices_mutex); +- return -EEXIST; ++ ret = -EEXIST; ++ goto out_unlock; + } +- mutex_unlock(&devices_mutex); + + dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL); +- if (!dev) +- return -ENOMEM; ++ if (!dev) { ++ ret = -ENOMEM; ++ goto out_unlock; ++ } + + mutex_init(&dev->dev_mutex); + +@@ -437,14 +438,13 @@ int ubiblock_create(struct ubi_volume_info *vi) + goto out_free_queue; + } + +- mutex_lock(&devices_mutex); + list_add_tail(&dev->list, &ubiblock_devices); +- mutex_unlock(&devices_mutex); + + /* Must be the last step: anyone can call file ops from now on */ + add_disk(dev->gd); + dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", + dev->ubi_num, dev->vol_id, vi->name); ++ mutex_unlock(&devices_mutex); + return 0; + + out_free_queue: +@@ -457,6 +457,8 @@ int ubiblock_create(struct ubi_volume_info *vi) + put_disk(dev->gd); + out_free_dev: + kfree(dev); ++out_unlock: ++ mutex_unlock(&devices_mutex); + + return ret; + } +@@ -478,30 +480,36 @@ static void ubiblock_cleanup(struct ubiblock *dev) + int ubiblock_remove(struct ubi_volume_info *vi) + { + struct ubiblock *dev; ++ int ret; + + mutex_lock(&devices_mutex); + dev = find_dev_nolock(vi->ubi_num, vi->vol_id); + if (!dev) { +- mutex_unlock(&devices_mutex); +- return -ENODEV; ++ ret = -ENODEV; ++ goto out_unlock; + } + + /* Found a device, let's lock it so we can check if it's busy */ + mutex_lock(&dev->dev_mutex); + if (dev->refcnt > 0) { +- mutex_unlock(&dev->dev_mutex); +- mutex_unlock(&devices_mutex); +- return -EBUSY; ++ ret = -EBUSY; ++ goto out_unlock_dev; + } + + /* Remove from device list */ + list_del(&dev->list); +- mutex_unlock(&devices_mutex); +- + ubiblock_cleanup(dev); + mutex_unlock(&dev->dev_mutex); ++ mutex_unlock(&devices_mutex); ++ + kfree(dev); + return 0; ++ ++out_unlock_dev: ++ mutex_unlock(&dev->dev_mutex); ++out_unlock: ++ mutex_unlock(&devices_mutex); ++ return ret; + } + + static int ubiblock_resize(struct ubi_volume_info *vi) +@@ -630,6 +638,7 @@ static void ubiblock_remove_all(void) + struct ubiblock *next; + struct ubiblock *dev; + ++ mutex_lock(&devices_mutex); + list_for_each_entry_safe(dev, next, &ubiblock_devices, list) { + /* The module is being forcefully removed */ + WARN_ON(dev->desc); +@@ -638,6 +647,7 @@ static void ubiblock_remove_all(void) + ubiblock_cleanup(dev); + kfree(dev); + } ++ mutex_unlock(&devices_mutex); + } + + int __init ubiblock_init(void) +diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c +index 85237cf661f9..3fd8d7ff7a02 100644 +--- a/drivers/mtd/ubi/vmt.c ++++ b/drivers/mtd/ubi/vmt.c +@@ -270,6 +270,12 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) + vol->last_eb_bytes = vol->usable_leb_size; + } + ++ /* Make volume "available" before it becomes accessible via sysfs */ ++ spin_lock(&ubi->volumes_lock); ++ ubi->volumes[vol_id] = vol; ++ ubi->vol_count += 1; ++ spin_unlock(&ubi->volumes_lock); ++ + /* Register character device for the volume */ + cdev_init(&vol->cdev, &ubi_vol_cdev_operations); + vol->cdev.owner = THIS_MODULE; +@@ -298,11 +304,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) + if (err) + goto out_sysfs; + +- spin_lock(&ubi->volumes_lock); +- ubi->volumes[vol_id] = vol; +- ubi->vol_count += 1; +- spin_unlock(&ubi->volumes_lock); +- + ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED); + self_check_volumes(ubi); + return err; +@@ -315,6 +316,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) + */ + cdev_device_del(&vol->cdev, &vol->dev); + out_mapping: ++ spin_lock(&ubi->volumes_lock); ++ ubi->volumes[vol_id] = NULL; ++ ubi->vol_count -= 1; ++ spin_unlock(&ubi->volumes_lock); + ubi_eba_destroy_table(eba_tbl); + out_acc: + spin_lock(&ubi->volumes_lock); +diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index b5b8cd6f481c..668b46202507 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -1528,6 +1528,46 @@ static void shutdown_work(struct ubi_device *ubi) + } + } + ++/** ++ * erase_aeb - erase a PEB given in UBI attach info PEB ++ * @ubi: UBI device description object ++ * @aeb: UBI attach info PEB ++ * @sync: If true, erase synchronously. Otherwise schedule for erasure ++ */ ++static int erase_aeb(struct ubi_device *ubi, struct ubi_ainf_peb *aeb, bool sync) ++{ ++ struct ubi_wl_entry *e; ++ int err; ++ ++ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); ++ if (!e) ++ return -ENOMEM; ++ ++ e->pnum = aeb->pnum; ++ e->ec = aeb->ec; ++ ubi->lookuptbl[e->pnum] = e; ++ ++ if (sync) { ++ err = sync_erase(ubi, e, false); ++ if (err) ++ goto out_free; ++ ++ wl_tree_add(e, &ubi->free); ++ ubi->free_count++; ++ } else { ++ err = schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false); ++ if (err) ++ goto out_free; ++ } ++ ++ return 0; ++ ++out_free: ++ wl_entry_destroy(ubi, e); ++ ++ return err; ++} ++ + /** + * ubi_wl_init - initialize the WL sub-system using attaching information. + * @ubi: UBI device description object +@@ -1566,18 +1606,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) { + cond_resched(); + +- e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); +- if (!e) ++ err = erase_aeb(ubi, aeb, false); ++ if (err) + goto out_free; + +- e->pnum = aeb->pnum; +- e->ec = aeb->ec; +- ubi->lookuptbl[e->pnum] = e; +- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) { +- wl_entry_destroy(ubi, e); +- goto out_free; +- } +- + found_pebs++; + } + +@@ -1635,6 +1667,8 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + ubi_assert(!ubi->lookuptbl[e->pnum]); + ubi->lookuptbl[e->pnum] = e; + } else { ++ bool sync = false; ++ + /* + * Usually old Fastmap PEBs are scheduled for erasure + * and we don't have to care about them but if we face +@@ -1644,18 +1678,21 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + if (ubi->lookuptbl[aeb->pnum]) + continue; + +- e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); +- if (!e) +- goto out_free; ++ /* ++ * The fastmap update code might not find a free PEB for ++ * writing the fastmap anchor to and then reuses the ++ * current fastmap anchor PEB. When this PEB gets erased ++ * and a power cut happens before it is written again we ++ * must make sure that the fastmap attach code doesn't ++ * find any outdated fastmap anchors, hence we erase the ++ * outdated fastmap anchor PEBs synchronously here. ++ */ ++ if (aeb->vol_id == UBI_FM_SB_VOLUME_ID) ++ sync = true; + +- e->pnum = aeb->pnum; +- e->ec = aeb->ec; +- ubi_assert(!ubi->lookuptbl[e->pnum]); +- ubi->lookuptbl[e->pnum] = e; +- if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) { +- wl_entry_destroy(ubi, e); ++ err = erase_aeb(ubi, aeb, sync); ++ if (err) + goto out_free; +- } + } + + found_pebs++; +diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c +index 8ce262fc2561..51b40aecb776 100644 +--- a/drivers/perf/arm_spe_pmu.c ++++ b/drivers/perf/arm_spe_pmu.c +@@ -1164,6 +1164,15 @@ static int arm_spe_pmu_device_dt_probe(struct platform_device *pdev) + struct arm_spe_pmu *spe_pmu; + struct device *dev = &pdev->dev; + ++ /* ++ * If kernelspace is unmapped when running at EL0, then the SPE ++ * buffer will fault and prematurely terminate the AUX session. ++ */ ++ if (arm64_kernel_unmapped_at_el0()) { ++ dev_warn_once(dev, "profiling buffer inaccessible. Try passing \"kpti=off\" on the kernel command line\n"); ++ return -EPERM; ++ } ++ + spe_pmu = devm_kzalloc(dev, sizeof(*spe_pmu), GFP_KERNEL); + if (!spe_pmu) { + dev_err(dev, "failed to allocate spe_pmu\n"); +diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c +index 12a1af45acb9..32209f37b2be 100644 +--- a/drivers/pinctrl/intel/pinctrl-intel.c ++++ b/drivers/pinctrl/intel/pinctrl-intel.c +@@ -425,6 +425,18 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input) + writel(value, padcfg0); + } + ++static void intel_gpio_set_gpio_mode(void __iomem *padcfg0) ++{ ++ u32 value; ++ ++ /* Put the pad into GPIO mode */ ++ value = readl(padcfg0) & ~PADCFG0_PMODE_MASK; ++ /* Disable SCI/SMI/NMI generation */ ++ value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); ++ value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); ++ writel(value, padcfg0); ++} ++ + static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned pin) +@@ -432,7 +444,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, + struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + void __iomem *padcfg0; + unsigned long flags; +- u32 value; + + raw_spin_lock_irqsave(&pctrl->lock, flags); + +@@ -442,13 +453,7 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, + } + + padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); +- /* Put the pad into GPIO mode */ +- value = readl(padcfg0) & ~PADCFG0_PMODE_MASK; +- /* Disable SCI/SMI/NMI generation */ +- value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); +- value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); +- writel(value, padcfg0); +- ++ intel_gpio_set_gpio_mode(padcfg0); + /* Disable TX buffer and enable RX (this will be input) */ + __intel_gpio_set_direction(padcfg0, true); + +@@ -935,6 +940,8 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type) + + raw_spin_lock_irqsave(&pctrl->lock, flags); + ++ intel_gpio_set_gpio_mode(reg); ++ + value = readl(reg); + + value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); +diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c +index 4a6ea159c65d..c490899b77e5 100644 +--- a/drivers/pinctrl/pinctrl-mcp23s08.c ++++ b/drivers/pinctrl/pinctrl-mcp23s08.c +@@ -896,16 +896,16 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, + goto fail; + } + +- ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp); +- if (ret < 0) +- goto fail; +- + if (mcp->irq && mcp->irq_controller) { + ret = mcp23s08_irq_setup(mcp); + if (ret) + goto fail; + } + ++ ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp); ++ if (ret < 0) ++ goto fail; ++ + mcp->pinctrl_desc.name = "mcp23xxx-pinctrl"; + mcp->pinctrl_desc.pctlops = &mcp_pinctrl_ops; + mcp->pinctrl_desc.confops = &mcp_pinconf_ops; +diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c +index fb242c542dc9..cbf58a10113d 100644 +--- a/drivers/pinctrl/pinctrl-sx150x.c ++++ b/drivers/pinctrl/pinctrl-sx150x.c +@@ -1144,6 +1144,27 @@ static int sx150x_probe(struct i2c_client *client, + if (ret) + return ret; + ++ /* Pinctrl_desc */ ++ pctl->pinctrl_desc.name = "sx150x-pinctrl"; ++ pctl->pinctrl_desc.pctlops = &sx150x_pinctrl_ops; ++ pctl->pinctrl_desc.confops = &sx150x_pinconf_ops; ++ pctl->pinctrl_desc.pins = pctl->data->pins; ++ pctl->pinctrl_desc.npins = pctl->data->npins; ++ pctl->pinctrl_desc.owner = THIS_MODULE; ++ ++ ret = devm_pinctrl_register_and_init(dev, &pctl->pinctrl_desc, ++ pctl, &pctl->pctldev); ++ if (ret) { ++ dev_err(dev, "Failed to register pinctrl device\n"); ++ return ret; ++ } ++ ++ ret = pinctrl_enable(pctl->pctldev); ++ if (ret) { ++ dev_err(dev, "Failed to enable pinctrl device\n"); ++ return ret; ++ } ++ + /* Register GPIO controller */ + pctl->gpio.label = devm_kstrdup(dev, client->name, GFP_KERNEL); + pctl->gpio.base = -1; +@@ -1172,6 +1193,11 @@ static int sx150x_probe(struct i2c_client *client, + if (ret) + return ret; + ++ ret = gpiochip_add_pin_range(&pctl->gpio, dev_name(dev), ++ 0, 0, pctl->data->npins); ++ if (ret) ++ return ret; ++ + /* Add Interrupt support if an irq is specified */ + if (client->irq > 0) { + pctl->irq_chip.name = devm_kstrdup(dev, client->name, +@@ -1217,20 +1243,6 @@ static int sx150x_probe(struct i2c_client *client, + client->irq); + } + +- /* Pinctrl_desc */ +- pctl->pinctrl_desc.name = "sx150x-pinctrl"; +- pctl->pinctrl_desc.pctlops = &sx150x_pinctrl_ops; +- pctl->pinctrl_desc.confops = &sx150x_pinconf_ops; +- pctl->pinctrl_desc.pins = pctl->data->pins; +- pctl->pinctrl_desc.npins = pctl->data->npins; +- pctl->pinctrl_desc.owner = THIS_MODULE; +- +- pctl->pctldev = pinctrl_register(&pctl->pinctrl_desc, dev, pctl); +- if (IS_ERR(pctl->pctldev)) { +- dev_err(dev, "Failed to register pinctrl device\n"); +- return PTR_ERR(pctl->pctldev); +- } +- + return 0; + } + +diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c +index 38b3a9c84fd1..48d366304582 100644 +--- a/drivers/scsi/cxlflash/main.c ++++ b/drivers/scsi/cxlflash/main.c +@@ -620,6 +620,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp) + cmd->parent = afu; + cmd->hwq_index = hwq_index; + ++ cmd->sa.ioasc = 0; + cmd->rcb.ctx_id = hwq->ctx_hndl; + cmd->rcb.msi = SISL_MSI_RRQ_UPDATED; + cmd->rcb.port_sel = CHAN2PORTMASK(scp->device->channel); +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index fe3a0da3ec97..57bf43e34863 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -318,6 +318,9 @@ static void scsi_host_dev_release(struct device *dev) + + scsi_proc_hostdir_rm(shost->hostt); + ++ /* Wait for functions invoked through call_rcu(&shost->rcu, ...) */ ++ rcu_barrier(); ++ + if (shost->tmf_work_q) + destroy_workqueue(shost->tmf_work_q); + if (shost->ehandler) +@@ -325,6 +328,8 @@ static void scsi_host_dev_release(struct device *dev) + if (shost->work_q) + destroy_workqueue(shost->work_q); + ++ destroy_rcu_head(&shost->rcu); ++ + if (shost->shost_state == SHOST_CREATED) { + /* + * Free the shost_dev device name here if scsi_host_alloc() +@@ -399,6 +404,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) + INIT_LIST_HEAD(&shost->starved_list); + init_waitqueue_head(&shost->host_wait); + mutex_init(&shost->scan_mutex); ++ init_rcu_head(&shost->rcu); + + index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL); + if (index < 0) +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index 2b7ea7e53e12..a28b2994b009 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -9421,44 +9421,62 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) + lpfc_sli4_bar0_register_memmap(phba, if_type); + } + +- if ((if_type == LPFC_SLI_INTF_IF_TYPE_0) && +- (pci_resource_start(pdev, PCI_64BIT_BAR2))) { +- /* +- * Map SLI4 if type 0 HBA Control Register base to a kernel +- * virtual address and setup the registers. +- */ +- phba->pci_bar1_map = pci_resource_start(pdev, PCI_64BIT_BAR2); +- bar1map_len = pci_resource_len(pdev, PCI_64BIT_BAR2); +- phba->sli4_hba.ctrl_regs_memmap_p = +- ioremap(phba->pci_bar1_map, bar1map_len); +- if (!phba->sli4_hba.ctrl_regs_memmap_p) { +- dev_printk(KERN_ERR, &pdev->dev, +- "ioremap failed for SLI4 HBA control registers.\n"); ++ if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { ++ if (pci_resource_start(pdev, PCI_64BIT_BAR2)) { ++ /* ++ * Map SLI4 if type 0 HBA Control Register base to a ++ * kernel virtual address and setup the registers. ++ */ ++ phba->pci_bar1_map = pci_resource_start(pdev, ++ PCI_64BIT_BAR2); ++ bar1map_len = pci_resource_len(pdev, PCI_64BIT_BAR2); ++ phba->sli4_hba.ctrl_regs_memmap_p = ++ ioremap(phba->pci_bar1_map, ++ bar1map_len); ++ if (!phba->sli4_hba.ctrl_regs_memmap_p) { ++ dev_err(&pdev->dev, ++ "ioremap failed for SLI4 HBA " ++ "control registers.\n"); ++ error = -ENOMEM; ++ goto out_iounmap_conf; ++ } ++ phba->pci_bar2_memmap_p = ++ phba->sli4_hba.ctrl_regs_memmap_p; ++ lpfc_sli4_bar1_register_memmap(phba); ++ } else { ++ error = -ENOMEM; + goto out_iounmap_conf; + } +- phba->pci_bar2_memmap_p = phba->sli4_hba.ctrl_regs_memmap_p; +- lpfc_sli4_bar1_register_memmap(phba); + } + +- if ((if_type == LPFC_SLI_INTF_IF_TYPE_0) && +- (pci_resource_start(pdev, PCI_64BIT_BAR4))) { +- /* +- * Map SLI4 if type 0 HBA Doorbell Register base to a kernel +- * virtual address and setup the registers. +- */ +- phba->pci_bar2_map = pci_resource_start(pdev, PCI_64BIT_BAR4); +- bar2map_len = pci_resource_len(pdev, PCI_64BIT_BAR4); +- phba->sli4_hba.drbl_regs_memmap_p = +- ioremap(phba->pci_bar2_map, bar2map_len); +- if (!phba->sli4_hba.drbl_regs_memmap_p) { +- dev_printk(KERN_ERR, &pdev->dev, +- "ioremap failed for SLI4 HBA doorbell registers.\n"); +- goto out_iounmap_ctrl; +- } +- phba->pci_bar4_memmap_p = phba->sli4_hba.drbl_regs_memmap_p; +- error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0); +- if (error) ++ if (if_type == LPFC_SLI_INTF_IF_TYPE_0) { ++ if (pci_resource_start(pdev, PCI_64BIT_BAR4)) { ++ /* ++ * Map SLI4 if type 0 HBA Doorbell Register base to ++ * a kernel virtual address and setup the registers. ++ */ ++ phba->pci_bar2_map = pci_resource_start(pdev, ++ PCI_64BIT_BAR4); ++ bar2map_len = pci_resource_len(pdev, PCI_64BIT_BAR4); ++ phba->sli4_hba.drbl_regs_memmap_p = ++ ioremap(phba->pci_bar2_map, ++ bar2map_len); ++ if (!phba->sli4_hba.drbl_regs_memmap_p) { ++ dev_err(&pdev->dev, ++ "ioremap failed for SLI4 HBA" ++ " doorbell registers.\n"); ++ error = -ENOMEM; ++ goto out_iounmap_ctrl; ++ } ++ phba->pci_bar4_memmap_p = ++ phba->sli4_hba.drbl_regs_memmap_p; ++ error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0); ++ if (error) ++ goto out_iounmap_all; ++ } else { ++ error = -ENOMEM; + goto out_iounmap_all; ++ } + } + + return 0; +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index 62b56de38ae8..3737c6d3b064 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -220,6 +220,17 @@ static void scsi_eh_reset(struct scsi_cmnd *scmd) + } + } + ++static void scsi_eh_inc_host_failed(struct rcu_head *head) ++{ ++ struct Scsi_Host *shost = container_of(head, typeof(*shost), rcu); ++ unsigned long flags; ++ ++ spin_lock_irqsave(shost->host_lock, flags); ++ shost->host_failed++; ++ scsi_eh_wakeup(shost); ++ spin_unlock_irqrestore(shost->host_lock, flags); ++} ++ + /** + * scsi_eh_scmd_add - add scsi cmd to error handling. + * @scmd: scmd to run eh on. +@@ -242,9 +253,12 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd) + + scsi_eh_reset(scmd); + list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); +- shost->host_failed++; +- scsi_eh_wakeup(shost); + spin_unlock_irqrestore(shost->host_lock, flags); ++ /* ++ * Ensure that all tasks observe the host state change before the ++ * host_failed change. ++ */ ++ call_rcu(&shost->rcu, scsi_eh_inc_host_failed); + } + + /** +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index d9ca1dfab154..83856ee14851 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -318,22 +318,39 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) + cmd->cmd_len = scsi_command_size(cmd->cmnd); + } + +-void scsi_device_unbusy(struct scsi_device *sdev) ++/* ++ * Decrement the host_busy counter and wake up the error handler if necessary. ++ * Avoid as follows that the error handler is not woken up if shost->host_busy ++ * == shost->host_failed: use call_rcu() in scsi_eh_scmd_add() in combination ++ * with an RCU read lock in this function to ensure that this function in its ++ * entirety either finishes before scsi_eh_scmd_add() increases the ++ * host_failed counter or that it notices the shost state change made by ++ * scsi_eh_scmd_add(). ++ */ ++static void scsi_dec_host_busy(struct Scsi_Host *shost) + { +- struct Scsi_Host *shost = sdev->host; +- struct scsi_target *starget = scsi_target(sdev); + unsigned long flags; + ++ rcu_read_lock(); + atomic_dec(&shost->host_busy); +- if (starget->can_queue > 0) +- atomic_dec(&starget->target_busy); +- +- if (unlikely(scsi_host_in_recovery(shost) && +- (shost->host_failed || shost->host_eh_scheduled))) { ++ if (unlikely(scsi_host_in_recovery(shost))) { + spin_lock_irqsave(shost->host_lock, flags); +- scsi_eh_wakeup(shost); ++ if (shost->host_failed || shost->host_eh_scheduled) ++ scsi_eh_wakeup(shost); + spin_unlock_irqrestore(shost->host_lock, flags); + } ++ rcu_read_unlock(); ++} ++ ++void scsi_device_unbusy(struct scsi_device *sdev) ++{ ++ struct Scsi_Host *shost = sdev->host; ++ struct scsi_target *starget = scsi_target(sdev); ++ ++ scsi_dec_host_busy(shost); ++ ++ if (starget->can_queue > 0) ++ atomic_dec(&starget->target_busy); + + atomic_dec(&sdev->device_busy); + } +@@ -1532,7 +1549,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + list_add_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); + out_dec: +- atomic_dec(&shost->host_busy); ++ scsi_dec_host_busy(shost); + return 0; + } + +@@ -2020,7 +2037,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, + return BLK_STS_OK; + + out_dec_host_busy: +- atomic_dec(&shost->host_busy); ++ scsi_dec_host_busy(shost); + out_dec_target_busy: + if (scsi_target(sdev)->can_queue > 0) + atomic_dec(&scsi_target(sdev)->target_busy); +diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig +index 71c73766ee22..65af12c3bdb2 100644 +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -32,7 +32,7 @@ config SSB_BLOCKIO + + config SSB_PCIHOST_POSSIBLE + bool +- depends on SSB && (PCI = y || PCI = SSB) && PCI_DRIVERS_LEGACY ++ depends on SSB && (PCI = y || PCI = SSB) && (PCI_DRIVERS_LEGACY || !MIPS) + default y + + config SSB_PCIHOST +diff --git a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto-adler.c b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto-adler.c +index 2e5d311d2438..db81ed527452 100644 +--- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto-adler.c ++++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto-adler.c +@@ -120,6 +120,7 @@ static struct shash_alg alg = { + .cra_name = "adler32", + .cra_driver_name = "adler32-zlib", + .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index ca200d1f310a..5a606a4aee6a 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1451,7 +1451,7 @@ config RC32434_WDT + + config INDYDOG + tristate "Indy/I2 Hardware Watchdog" +- depends on SGI_HAS_INDYDOG || (MIPS && COMPILE_TEST) ++ depends on SGI_HAS_INDYDOG + help + Hardware driver for the Indy's/I2's watchdog. This is a + watchdog timer that will reboot the machine after a 60 second +diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c +index cb66c2f99ff1..7a6279daa8b9 100644 +--- a/drivers/watchdog/gpio_wdt.c ++++ b/drivers/watchdog/gpio_wdt.c +@@ -80,7 +80,8 @@ static int gpio_wdt_stop(struct watchdog_device *wdd) + + if (!priv->always_running) { + gpio_wdt_disable(priv); +- clear_bit(WDOG_HW_RUNNING, &wdd->status); ++ } else { ++ set_bit(WDOG_HW_RUNNING, &wdd->status); + } + + return 0; +diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c +index 4874b0f18650..518dfa1047cb 100644 +--- a/drivers/watchdog/imx2_wdt.c ++++ b/drivers/watchdog/imx2_wdt.c +@@ -169,15 +169,21 @@ static int imx2_wdt_ping(struct watchdog_device *wdog) + return 0; + } + +-static int imx2_wdt_set_timeout(struct watchdog_device *wdog, +- unsigned int new_timeout) ++static void __imx2_wdt_set_timeout(struct watchdog_device *wdog, ++ unsigned int new_timeout) + { + struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); + +- wdog->timeout = new_timeout; +- + regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT, + WDOG_SEC_TO_COUNT(new_timeout)); ++} ++ ++static int imx2_wdt_set_timeout(struct watchdog_device *wdog, ++ unsigned int new_timeout) ++{ ++ __imx2_wdt_set_timeout(wdog, new_timeout); ++ ++ wdog->timeout = new_timeout; + return 0; + } + +@@ -371,7 +377,11 @@ static int imx2_wdt_suspend(struct device *dev) + + /* The watchdog IP block is running */ + if (imx2_wdt_is_running(wdev)) { +- imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); ++ /* ++ * Don't update wdog->timeout, we'll restore the current value ++ * during resume. ++ */ ++ __imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); + imx2_wdt_ping(wdog); + } + +diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c +index a537368ba0db..fd9f28b8a933 100644 +--- a/fs/afs/addr_list.c ++++ b/fs/afs/addr_list.c +@@ -332,11 +332,18 @@ bool afs_iterate_addresses(struct afs_addr_cursor *ac) + */ + int afs_end_cursor(struct afs_addr_cursor *ac) + { +- if (ac->responded && ac->index != ac->start) +- WRITE_ONCE(ac->alist->index, ac->index); ++ struct afs_addr_list *alist; ++ ++ alist = ac->alist; ++ if (alist) { ++ if (ac->responded && ac->index != ac->start) ++ WRITE_ONCE(alist->index, ac->index); ++ afs_put_addrlist(alist); ++ } + +- afs_put_addrlist(ac->alist); ++ ac->addr = NULL; + ac->alist = NULL; ++ ac->begun = false; + return ac->error; + } + +diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c +index d04511fb3879..892a4904fd77 100644 +--- a/fs/afs/rotate.c ++++ b/fs/afs/rotate.c +@@ -334,6 +334,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) + + next_server: + _debug("next"); ++ afs_end_cursor(&fc->ac); + afs_put_cb_interest(afs_v2net(vnode), fc->cbi); + fc->cbi = NULL; + fc->index++; +@@ -383,6 +384,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) + afs_get_addrlist(alist); + read_unlock(&server->fs_lock); + ++ memset(&fc->ac, 0, sizeof(fc->ac)); + + /* Probe the current fileserver if we haven't done so yet. */ + if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) { +@@ -397,11 +399,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) + else + afs_put_addrlist(alist); + +- fc->ac.addr = NULL; + fc->ac.start = READ_ONCE(alist->index); + fc->ac.index = fc->ac.start; +- fc->ac.error = 0; +- fc->ac.begun = false; + goto iterate_address; + + iterate_address: +@@ -410,16 +409,15 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) + /* Iterate over the current server's address list to try and find an + * address on which it will respond to us. + */ +- if (afs_iterate_addresses(&fc->ac)) { +- _leave(" = t"); +- return true; +- } ++ if (!afs_iterate_addresses(&fc->ac)) ++ goto next_server; + +- afs_end_cursor(&fc->ac); +- goto next_server; ++ _leave(" = t"); ++ return true; + + failed: + fc->flags |= AFS_FS_CURSOR_STOP; ++ afs_end_cursor(&fc->ac); + _leave(" = f [failed %d]", fc->ac.error); + return false; + } +@@ -458,12 +456,10 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) + return false; + } + ++ memset(&fc->ac, 0, sizeof(fc->ac)); + fc->ac.alist = alist; +- fc->ac.addr = NULL; + fc->ac.start = READ_ONCE(alist->index); + fc->ac.index = fc->ac.start; +- fc->ac.error = 0; +- fc->ac.begun = false; + goto iterate_address; + + case 0: +diff --git a/fs/afs/server_list.c b/fs/afs/server_list.c +index 0ab3f8457839..0f8dc4c8f07c 100644 +--- a/fs/afs/server_list.c ++++ b/fs/afs/server_list.c +@@ -58,7 +58,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, + server = afs_lookup_server(cell, key, &vldb->fs_server[i]); + if (IS_ERR(server)) { + ret = PTR_ERR(server); +- if (ret == -ENOENT) ++ if (ret == -ENOENT || ++ ret == -ENOMEDIUM) + continue; + goto error_2; + } +diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c +index e372f89fd36a..5d8562f1ad4a 100644 +--- a/fs/afs/vlclient.c ++++ b/fs/afs/vlclient.c +@@ -23,7 +23,7 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) + struct afs_uvldbentry__xdr *uvldb; + struct afs_vldb_entry *entry; + bool new_only = false; +- u32 tmp; ++ u32 tmp, nr_servers; + int i, ret; + + _enter(""); +@@ -36,6 +36,10 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) + uvldb = call->buffer; + entry = call->reply[0]; + ++ nr_servers = ntohl(uvldb->nServers); ++ if (nr_servers > AFS_NMAXNSERVERS) ++ nr_servers = AFS_NMAXNSERVERS; ++ + for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++) + entry->name[i] = (u8)ntohl(uvldb->name[i]); + entry->name[i] = 0; +@@ -44,14 +48,14 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) + /* If there is a new replication site that we can use, ignore all the + * sites that aren't marked as new. + */ +- for (i = 0; i < AFS_NMAXNSERVERS; i++) { ++ for (i = 0; i < nr_servers; i++) { + tmp = ntohl(uvldb->serverFlags[i]); + if (!(tmp & AFS_VLSF_DONTUSE) && + (tmp & AFS_VLSF_NEWREPSITE)) + new_only = true; + } + +- for (i = 0; i < AFS_NMAXNSERVERS; i++) { ++ for (i = 0; i < nr_servers; i++) { + struct afs_uuid__xdr *xdr; + struct afs_uuid *uuid; + int j; +diff --git a/fs/afs/volume.c b/fs/afs/volume.c +index 684c48293353..b517a588781f 100644 +--- a/fs/afs/volume.c ++++ b/fs/afs/volume.c +@@ -26,9 +26,8 @@ static struct afs_volume *afs_alloc_volume(struct afs_mount_params *params, + unsigned long type_mask) + { + struct afs_server_list *slist; +- struct afs_server *server; + struct afs_volume *volume; +- int ret = -ENOMEM, nr_servers = 0, i, j; ++ int ret = -ENOMEM, nr_servers = 0, i; + + for (i = 0; i < vldb->nr_servers; i++) + if (vldb->fs_mask[i] & type_mask) +@@ -58,50 +57,10 @@ static struct afs_volume *afs_alloc_volume(struct afs_mount_params *params, + + refcount_set(&slist->usage, 1); + volume->servers = slist; +- +- /* Make sure a records exists for each server this volume occupies. */ +- for (i = 0; i < nr_servers; i++) { +- if (!(vldb->fs_mask[i] & type_mask)) +- continue; +- +- server = afs_lookup_server(params->cell, params->key, +- &vldb->fs_server[i]); +- if (IS_ERR(server)) { +- ret = PTR_ERR(server); +- if (ret == -ENOENT) +- continue; +- goto error_2; +- } +- +- /* Insertion-sort by server pointer */ +- for (j = 0; j < slist->nr_servers; j++) +- if (slist->servers[j].server >= server) +- break; +- if (j < slist->nr_servers) { +- if (slist->servers[j].server == server) { +- afs_put_server(params->net, server); +- continue; +- } +- +- memmove(slist->servers + j + 1, +- slist->servers + j, +- (slist->nr_servers - j) * sizeof(struct afs_server_entry)); +- } +- +- slist->servers[j].server = server; +- slist->nr_servers++; +- } +- +- if (slist->nr_servers == 0) { +- ret = -EDESTADDRREQ; +- goto error_2; +- } +- + return volume; + +-error_2: +- afs_put_serverlist(params->net, slist); + error_1: ++ afs_put_cell(params->net, volume->cell); + kfree(volume); + error_0: + return ERR_PTR(ret); +@@ -327,7 +286,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key) + + /* See if the volume's server list got updated. */ + new = afs_alloc_server_list(volume->cell, key, +- vldb, (1 << volume->type)); ++ vldb, (1 << volume->type)); + if (IS_ERR(new)) { + ret = PTR_ERR(new); + goto error_vldb; +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index e1a7f3cb5be9..0f57602092cf 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -2098,8 +2098,15 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work) + goto out; + } + +- btrfs_set_extent_delalloc(inode, page_start, page_end, 0, &cached_state, +- 0); ++ ret = btrfs_set_extent_delalloc(inode, page_start, page_end, 0, ++ &cached_state, 0); ++ if (ret) { ++ mapping_set_error(page->mapping, ret); ++ end_extent_writepage(page, ret, page_start, page_end); ++ ClearPageChecked(page); ++ goto out; ++ } ++ + ClearPageChecked(page); + set_page_dirty(page); + btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE); +diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c +index a7f79254ecca..8903c4fbf7e6 100644 +--- a/fs/btrfs/raid56.c ++++ b/fs/btrfs/raid56.c +@@ -1435,14 +1435,13 @@ static int fail_bio_stripe(struct btrfs_raid_bio *rbio, + */ + static void set_bio_pages_uptodate(struct bio *bio) + { +- struct bio_vec bvec; +- struct bvec_iter iter; ++ struct bio_vec *bvec; ++ int i; + +- if (bio_flagged(bio, BIO_CLONED)) +- bio->bi_iter = btrfs_io_bio(bio)->iter; ++ ASSERT(!bio_flagged(bio, BIO_CLONED)); + +- bio_for_each_segment(bvec, bio, iter) +- SetPageUptodate(bvec.bv_page); ++ bio_for_each_segment_all(bvec, bio, i) ++ SetPageUptodate(bvec->bv_page); + } + + /* +diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c +index 68abbb0db608..f2b0a7f124da 100644 +--- a/fs/cifs/cifsencrypt.c ++++ b/fs/cifs/cifsencrypt.c +@@ -325,9 +325,8 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, + { + int i; + int rc; +- char password_with_pad[CIFS_ENCPWD_SIZE]; ++ char password_with_pad[CIFS_ENCPWD_SIZE] = {0}; + +- memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); + if (password) + strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); + +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 0bfc2280436d..f7db2fedfa8c 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -1707,7 +1707,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + tmp_end++; + if (!(tmp_end < end && tmp_end[1] == delim)) { + /* No it is not. Set the password to NULL */ +- kfree(vol->password); ++ kzfree(vol->password); + vol->password = NULL; + break; + } +@@ -1745,7 +1745,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, + options = end; + } + +- kfree(vol->password); ++ kzfree(vol->password); + /* Now build new password string */ + temp_len = strlen(value); + vol->password = kzalloc(temp_len+1, GFP_KERNEL); +@@ -4235,7 +4235,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) + reset_cifs_unix_caps(0, tcon, NULL, vol_info); + out: + kfree(vol_info->username); +- kfree(vol_info->password); ++ kzfree(vol_info->password); + kfree(vol_info); + + return tcon; +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index df9f682708c6..3a85df2a9baf 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -3471,20 +3471,18 @@ static const struct vm_operations_struct cifs_file_vm_ops = { + + int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) + { +- int rc, xid; ++ int xid, rc = 0; + struct inode *inode = file_inode(file); + + xid = get_xid(); + +- if (!CIFS_CACHE_READ(CIFS_I(inode))) { ++ if (!CIFS_CACHE_READ(CIFS_I(inode))) + rc = cifs_zap_mapping(inode); +- if (rc) +- return rc; +- } +- +- rc = generic_file_mmap(file, vma); +- if (rc == 0) ++ if (!rc) ++ rc = generic_file_mmap(file, vma); ++ if (!rc) + vma->vm_ops = &cifs_file_vm_ops; ++ + free_xid(xid); + return rc; + } +@@ -3494,16 +3492,16 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) + int rc, xid; + + xid = get_xid(); ++ + rc = cifs_revalidate_file(file); +- if (rc) { ++ if (rc) + cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n", + rc); +- free_xid(xid); +- return rc; +- } +- rc = generic_file_mmap(file, vma); +- if (rc == 0) ++ if (!rc) ++ rc = generic_file_mmap(file, vma); ++ if (!rc) + vma->vm_ops = &cifs_file_vm_ops; ++ + free_xid(xid); + return rc; + } +diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c +index eea93ac15ef0..a0dbced4a45c 100644 +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -98,14 +98,11 @@ sesInfoFree(struct cifs_ses *buf_to_free) + kfree(buf_to_free->serverOS); + kfree(buf_to_free->serverDomain); + kfree(buf_to_free->serverNOS); +- if (buf_to_free->password) { +- memset(buf_to_free->password, 0, strlen(buf_to_free->password)); +- kfree(buf_to_free->password); +- } ++ kzfree(buf_to_free->password); + kfree(buf_to_free->user_name); + kfree(buf_to_free->domainName); +- kfree(buf_to_free->auth_key.response); +- kfree(buf_to_free); ++ kzfree(buf_to_free->auth_key.response); ++ kzfree(buf_to_free); + } + + struct cifs_tcon * +@@ -136,10 +133,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free) + } + atomic_dec(&tconInfoAllocCount); + kfree(buf_to_free->nativeFileSystem); +- if (buf_to_free->password) { +- memset(buf_to_free->password, 0, strlen(buf_to_free->password)); +- kfree(buf_to_free->password); +- } ++ kzfree(buf_to_free->password); + kfree(buf_to_free); + } + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 01346b8b6edb..66af1f8a13cc 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -733,8 +733,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + } + + /* check validate negotiate info response matches what we got earlier */ +- if (pneg_rsp->Dialect != +- cpu_to_le16(tcon->ses->server->vals->protocol_id)) ++ if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect)) + goto vneg_out; + + if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode)) +diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c +index 7eae33ffa3fc..e31d6ed3ec32 100644 +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -168,11 +168,11 @@ struct vfsmount *devpts_mntget(struct file *filp, struct pts_fs_info *fsi) + dput(path.dentry); + if (err) { + mntput(path.mnt); +- path.mnt = ERR_PTR(err); ++ return ERR_PTR(err); + } + if (DEVPTS_SB(path.mnt->mnt_sb) != fsi) { + mntput(path.mnt); +- path.mnt = ERR_PTR(-ENODEV); ++ return ERR_PTR(-ENODEV); + } + return path.mnt; + } +diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c +index 9698e51656b1..d8f49c412f50 100644 +--- a/fs/kernfs/file.c ++++ b/fs/kernfs/file.c +@@ -275,7 +275,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, + { + struct kernfs_open_file *of = kernfs_of(file); + const struct kernfs_ops *ops; +- size_t len; ++ ssize_t len; + char *buf; + + if (of->atomic_write_len) { +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index d2972d537469..8c10b0562e75 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -775,10 +775,8 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) + + spin_lock(&dreq->lock); + +- if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) { +- dreq->flags = 0; ++ if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) + dreq->error = hdr->error; +- } + if (dreq->error == 0) { + nfs_direct_good_bytes(dreq, hdr); + if (nfs_write_need_commit(hdr)) { +diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c +index 4e54d8b5413a..d175724ff566 100644 +--- a/fs/nfs/filelayout/filelayout.c ++++ b/fs/nfs/filelayout/filelayout.c +@@ -895,9 +895,7 @@ fl_pnfs_update_layout(struct inode *ino, + + lseg = pnfs_update_layout(ino, ctx, pos, count, iomode, strict_iomode, + gfp_flags); +- if (!lseg) +- lseg = ERR_PTR(-ENOMEM); +- if (IS_ERR(lseg)) ++ if (IS_ERR_OR_NULL(lseg)) + goto out; + + lo = NFS_I(ino)->layout; +diff --git a/fs/nfs/io.c b/fs/nfs/io.c +index 20fef85d2bb1..9034b4926909 100644 +--- a/fs/nfs/io.c ++++ b/fs/nfs/io.c +@@ -99,7 +99,7 @@ static void nfs_block_buffered(struct nfs_inode *nfsi, struct inode *inode) + { + if (!test_bit(NFS_INO_ODIRECT, &nfsi->flags)) { + set_bit(NFS_INO_ODIRECT, &nfsi->flags); +- nfs_wb_all(inode); ++ nfs_sync_mapping(inode->i_mapping); + } + } + +diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c +index 30426c1a1bbd..22dc30a679a0 100644 +--- a/fs/nfs/nfs4idmap.c ++++ b/fs/nfs/nfs4idmap.c +@@ -568,9 +568,13 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, + struct idmap_msg *im; + struct idmap *idmap = (struct idmap *)aux; + struct key *key = cons->key; +- int ret = -ENOMEM; ++ int ret = -ENOKEY; ++ ++ if (!aux) ++ goto out1; + + /* msg and im are freed in idmap_pipe_destroy_msg */ ++ ret = -ENOMEM; + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + goto out1; +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 77c6729e57f0..65c9c4175145 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -7678,6 +7678,22 @@ nfs4_stat_to_errno(int stat) + .p_name = #proc, \ + } + ++#if defined(CONFIG_NFS_V4_1) ++#define PROC41(proc, argtype, restype) \ ++ PROC(proc, argtype, restype) ++#else ++#define PROC41(proc, argtype, restype) \ ++ STUB(proc) ++#endif ++ ++#if defined(CONFIG_NFS_V4_2) ++#define PROC42(proc, argtype, restype) \ ++ PROC(proc, argtype, restype) ++#else ++#define PROC42(proc, argtype, restype) \ ++ STUB(proc) ++#endif ++ + const struct rpc_procinfo nfs4_procedures[] = { + PROC(READ, enc_read, dec_read), + PROC(WRITE, enc_write, dec_write), +@@ -7698,7 +7714,6 @@ const struct rpc_procinfo nfs4_procedures[] = { + PROC(ACCESS, enc_access, dec_access), + PROC(GETATTR, enc_getattr, dec_getattr), + PROC(LOOKUP, enc_lookup, dec_lookup), +- PROC(LOOKUPP, enc_lookupp, dec_lookupp), + PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), + PROC(REMOVE, enc_remove, dec_remove), + PROC(RENAME, enc_rename, dec_rename), +@@ -7717,33 +7732,30 @@ const struct rpc_procinfo nfs4_procedures[] = { + PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), + PROC(SECINFO, enc_secinfo, dec_secinfo), + PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present), +-#if defined(CONFIG_NFS_V4_1) +- PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), +- PROC(CREATE_SESSION, enc_create_session, dec_create_session), +- PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), +- PROC(SEQUENCE, enc_sequence, dec_sequence), +- PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), +- PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), +- PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), +- PROC(LAYOUTGET, enc_layoutget, dec_layoutget), +- PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), +- PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), +- PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), +- PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), +- PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), ++ PROC41(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), ++ PROC41(CREATE_SESSION, enc_create_session, dec_create_session), ++ PROC41(DESTROY_SESSION, enc_destroy_session, dec_destroy_session), ++ PROC41(SEQUENCE, enc_sequence, dec_sequence), ++ PROC41(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time), ++ PROC41(RECLAIM_COMPLETE,enc_reclaim_complete, dec_reclaim_complete), ++ PROC41(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), ++ PROC41(LAYOUTGET, enc_layoutget, dec_layoutget), ++ PROC41(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), ++ PROC41(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn), ++ PROC41(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), ++ PROC41(TEST_STATEID, enc_test_stateid, dec_test_stateid), ++ PROC41(FREE_STATEID, enc_free_stateid, dec_free_stateid), + STUB(GETDEVICELIST), +- PROC(BIND_CONN_TO_SESSION, ++ PROC41(BIND_CONN_TO_SESSION, + enc_bind_conn_to_session, dec_bind_conn_to_session), +- PROC(DESTROY_CLIENTID, enc_destroy_clientid, dec_destroy_clientid), +-#endif /* CONFIG_NFS_V4_1 */ +-#ifdef CONFIG_NFS_V4_2 +- PROC(SEEK, enc_seek, dec_seek), +- PROC(ALLOCATE, enc_allocate, dec_allocate), +- PROC(DEALLOCATE, enc_deallocate, dec_deallocate), +- PROC(LAYOUTSTATS, enc_layoutstats, dec_layoutstats), +- PROC(CLONE, enc_clone, dec_clone), +- PROC(COPY, enc_copy, dec_copy), +-#endif /* CONFIG_NFS_V4_2 */ ++ PROC41(DESTROY_CLIENTID,enc_destroy_clientid, dec_destroy_clientid), ++ PROC42(SEEK, enc_seek, dec_seek), ++ PROC42(ALLOCATE, enc_allocate, dec_allocate), ++ PROC42(DEALLOCATE, enc_deallocate, dec_deallocate), ++ PROC42(LAYOUTSTATS, enc_layoutstats, dec_layoutstats), ++ PROC42(CLONE, enc_clone, dec_clone), ++ PROC42(COPY, enc_copy, dec_copy), ++ PROC(LOOKUPP, enc_lookupp, dec_lookupp), + }; + + static unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)]; +diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c +index d602fe9e1ac8..eb098ccfefd5 100644 +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -2255,7 +2255,7 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, + nfs_pageio_reset_write_mds(desc); + mirror->pg_recoalesce = 1; + } +- hdr->release(hdr); ++ hdr->completion_ops->completion(hdr); + } + + static enum pnfs_try_status +@@ -2378,7 +2378,7 @@ pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, + nfs_pageio_reset_read_mds(desc); + mirror->pg_recoalesce = 1; + } +- hdr->release(hdr); ++ hdr->completion_ops->completion(hdr); + } + + /* +diff --git a/fs/nfs/write.c b/fs/nfs/write.c +index 4a379d7918f2..cf61108f8f8d 100644 +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -1837,6 +1837,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data) + set_bit(NFS_CONTEXT_RESEND_WRITES, &req->wb_context->flags); + next: + nfs_unlock_and_release_request(req); ++ /* Latency breaker */ ++ cond_resched(); + } + nfss = NFS_SERVER(data->inode); + if (atomic_long_read(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index b29b5a185a2c..5a75135f5f53 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -3590,6 +3590,7 @@ nfsd4_verify_open_stid(struct nfs4_stid *s) + switch (s->sc_type) { + default: + break; ++ case 0: + case NFS4_CLOSED_STID: + case NFS4_CLOSED_DELEG_STID: + ret = nfserr_bad_stateid; +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +index 00b6b294272a..94d2f8a8b779 100644 +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -606,6 +606,16 @@ static int ovl_inode_set(struct inode *inode, void *data) + static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, + struct dentry *upperdentry) + { ++ if (S_ISDIR(inode->i_mode)) { ++ /* Real lower dir moved to upper layer under us? */ ++ if (!lowerdentry && ovl_inode_lower(inode)) ++ return false; ++ ++ /* Lookup of an uncovered redirect origin? */ ++ if (!upperdentry && ovl_inode_upper(inode)) ++ return false; ++ } ++ + /* + * Allow non-NULL lower inode in ovl_inode even if lowerdentry is NULL. + * This happens when finding a copied up overlay inode for a renamed +@@ -633,6 +643,8 @@ struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, + struct inode *inode; + /* Already indexed or could be indexed on copy up? */ + bool indexed = (index || (ovl_indexdir(dentry->d_sb) && !upperdentry)); ++ struct dentry *origin = indexed ? lowerdentry : NULL; ++ bool is_dir; + + if (WARN_ON(upperdentry && indexed && !lowerdentry)) + return ERR_PTR(-EIO); +@@ -641,15 +653,19 @@ struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, + realinode = d_inode(lowerdentry); + + /* +- * Copy up origin (lower) may exist for non-indexed upper, but we must +- * not use lower as hash key in that case. +- * Hash inodes that are or could be indexed by origin inode and +- * non-indexed upper inodes that could be hard linked by upper inode. ++ * Copy up origin (lower) may exist for non-indexed non-dir upper, but ++ * we must not use lower as hash key in that case. ++ * Hash non-dir that is or could be indexed by origin inode. ++ * Hash dir that is or could be merged by origin inode. ++ * Hash pure upper and non-indexed non-dir by upper inode. + */ +- if (!S_ISDIR(realinode->i_mode) && (upperdentry || indexed)) { +- struct inode *key = d_inode(indexed ? lowerdentry : +- upperdentry); +- unsigned int nlink; ++ is_dir = S_ISDIR(realinode->i_mode); ++ if (is_dir) ++ origin = lowerdentry; ++ ++ if (upperdentry || origin) { ++ struct inode *key = d_inode(origin ?: upperdentry); ++ unsigned int nlink = is_dir ? 1 : realinode->i_nlink; + + inode = iget5_locked(dentry->d_sb, (unsigned long) key, + ovl_inode_test, ovl_inode_set, key); +@@ -670,8 +686,9 @@ struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, + goto out; + } + +- nlink = ovl_get_nlink(lowerdentry, upperdentry, +- realinode->i_nlink); ++ /* Recalculate nlink for non-dir due to indexing */ ++ if (!is_dir) ++ nlink = ovl_get_nlink(lowerdentry, upperdentry, nlink); + set_nlink(inode, nlink); + } else { + inode = new_inode(dentry->d_sb); +@@ -685,7 +702,7 @@ struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, + ovl_set_flag(OVL_IMPURE, inode); + + /* Check for non-merge dir that may have whiteouts */ +- if (S_ISDIR(realinode->i_mode)) { ++ if (is_dir) { + struct ovl_entry *oe = dentry->d_fsdata; + + if (((upperdentry && lowerdentry) || oe->numlower > 1) || +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +index 8c98578d27a1..e258c234f357 100644 +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -593,8 +593,15 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path) + return ERR_PTR(res); + } + if (list_empty(&cache->entries)) { +- /* Good oportunity to get rid of an unnecessary "impure" flag */ +- ovl_do_removexattr(ovl_dentry_upper(dentry), OVL_XATTR_IMPURE); ++ /* ++ * A good opportunity to get rid of an unneeded "impure" flag. ++ * Removing the "impure" xattr is best effort. ++ */ ++ if (!ovl_want_write(dentry)) { ++ ovl_do_removexattr(ovl_dentry_upper(dentry), ++ OVL_XATTR_IMPURE); ++ ovl_drop_write(dentry); ++ } + ovl_clear_flag(OVL_IMPURE, d_inode(dentry)); + kfree(cache); + return NULL; +@@ -769,10 +776,14 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, + struct dentry *dentry = file->f_path.dentry; + struct file *realfile = od->realfile; + ++ /* Nothing to sync for lower */ ++ if (!OVL_TYPE_UPPER(ovl_path_type(dentry))) ++ return 0; ++ + /* + * Need to check if we started out being a lower dir, but got copied up + */ +- if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) { ++ if (!od->is_upper) { + struct inode *inode = file_inode(file); + + realfile = READ_ONCE(od->upperfile); +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 76440feb79f6..e3d5fb651f9a 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -211,6 +211,7 @@ static void ovl_destroy_inode(struct inode *inode) + struct ovl_inode *oi = OVL_I(inode); + + dput(oi->__upperdentry); ++ iput(oi->lower); + kfree(oi->redirect); + ovl_dir_cache_free(inode); + mutex_destroy(&oi->lock); +@@ -520,10 +521,6 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs, + bool retried = false; + bool locked = false; + +- err = mnt_want_write(mnt); +- if (err) +- goto out_err; +- + inode_lock_nested(dir, I_MUTEX_PARENT); + locked = true; + +@@ -588,7 +585,6 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs, + goto out_err; + } + out_unlock: +- mnt_drop_write(mnt); + if (locked) + inode_unlock(dir); + +@@ -703,7 +699,8 @@ static int ovl_lower_dir(const char *name, struct path *path, + * The inodes index feature needs to encode and decode file + * handles, so it requires that all layers support them. + */ +- if (ofs->config.index && !ovl_can_decode_fh(path->dentry->d_sb)) { ++ if (ofs->config.index && ofs->config.upperdir && ++ !ovl_can_decode_fh(path->dentry->d_sb)) { + ofs->config.index = false; + pr_warn("overlayfs: fs on '%s' does not support file handles, falling back to index=off.\n", name); + } +@@ -929,12 +926,17 @@ static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath) + + static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath) + { ++ struct vfsmount *mnt = ofs->upper_mnt; + struct dentry *temp; + int err; + ++ err = mnt_want_write(mnt); ++ if (err) ++ return err; ++ + ofs->workdir = ovl_workdir_create(ofs, OVL_WORKDIR_NAME, false); + if (!ofs->workdir) +- return 0; ++ goto out; + + /* + * Upper should support d_type, else whiteouts are visible. Given +@@ -944,7 +946,7 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath) + */ + err = ovl_check_d_type_supported(workpath); + if (err < 0) +- return err; ++ goto out; + + /* + * We allowed this configuration and don't want to break users over +@@ -968,6 +970,7 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath) + if (err) { + ofs->noxattr = true; + pr_warn("overlayfs: upper fs does not support xattr.\n"); ++ err = 0; + } else { + vfs_removexattr(ofs->workdir, OVL_XATTR_OPAQUE); + } +@@ -979,7 +982,9 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath) + pr_warn("overlayfs: upper fs does not support file handles, falling back to index=off.\n"); + } + +- return 0; ++out: ++ mnt_drop_write(mnt); ++ return err; + } + + static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath) +@@ -1026,8 +1031,13 @@ static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath) + static int ovl_get_indexdir(struct ovl_fs *ofs, struct ovl_entry *oe, + struct path *upperpath) + { ++ struct vfsmount *mnt = ofs->upper_mnt; + int err; + ++ err = mnt_want_write(mnt); ++ if (err) ++ return err; ++ + /* Verify lower root is upper root origin */ + err = ovl_verify_origin(upperpath->dentry, oe->lowerstack[0].dentry, + false, true); +@@ -1055,6 +1065,7 @@ static int ovl_get_indexdir(struct ovl_fs *ofs, struct ovl_entry *oe, + pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); + + out: ++ mnt_drop_write(mnt); + return err; + } + +@@ -1257,11 +1268,16 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) + if (err) + goto out_free_oe; + +- if (!ofs->indexdir) ++ /* Force r/o mount with no index dir */ ++ if (!ofs->indexdir) { ++ dput(ofs->workdir); ++ ofs->workdir = NULL; + sb->s_flags |= SB_RDONLY; ++ } ++ + } + +- /* Show index=off/on in /proc/mounts for any of the reasons above */ ++ /* Show index=off in /proc/mounts for forced r/o mount */ + if (!ofs->indexdir) + ofs->config.index = false; + +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index d6bb1c9f5e7a..06119f34a69d 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -257,7 +257,7 @@ void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, + if (upperdentry) + OVL_I(inode)->__upperdentry = upperdentry; + if (lowerdentry) +- OVL_I(inode)->lower = d_inode(lowerdentry); ++ OVL_I(inode)->lower = igrab(d_inode(lowerdentry)); + + ovl_copyattr(d_inode(upperdentry ?: lowerdentry), inode); + } +@@ -273,7 +273,7 @@ void ovl_inode_update(struct inode *inode, struct dentry *upperdentry) + */ + smp_wmb(); + OVL_I(inode)->__upperdentry = upperdentry; +- if (!S_ISDIR(upperinode->i_mode) && inode_unhashed(inode)) { ++ if (inode_unhashed(inode)) { + inode->i_private = upperinode; + __insert_inode_hash(inode, (unsigned long) upperinode); + } +diff --git a/fs/pipe.c b/fs/pipe.c +index 6d98566201ef..b37a59f84dd0 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -610,12 +610,17 @@ static unsigned long account_pipe_buffers(struct user_struct *user, + + static bool too_many_pipe_buffers_soft(unsigned long user_bufs) + { +- return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft; ++ return pipe_user_pages_soft && user_bufs > pipe_user_pages_soft; + } + + static bool too_many_pipe_buffers_hard(unsigned long user_bufs) + { +- return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard; ++ return pipe_user_pages_hard && user_bufs > pipe_user_pages_hard; ++} ++ ++static bool is_unprivileged_user(void) ++{ ++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); + } + + struct pipe_inode_info *alloc_pipe_info(void) +@@ -634,12 +639,12 @@ struct pipe_inode_info *alloc_pipe_info(void) + + user_bufs = account_pipe_buffers(user, 0, pipe_bufs); + +- if (too_many_pipe_buffers_soft(user_bufs)) { ++ if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) { + user_bufs = account_pipe_buffers(user, pipe_bufs, 1); + pipe_bufs = 1; + } + +- if (too_many_pipe_buffers_hard(user_bufs)) ++ if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user()) + goto out_revert_acct; + + pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer), +@@ -1069,7 +1074,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg) + if (nr_pages > pipe->buffers && + (too_many_pipe_buffers_hard(user_bufs) || + too_many_pipe_buffers_soft(user_bufs)) && +- !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { ++ is_unprivileged_user()) { + ret = -EPERM; + goto out_revert_acct; + } +diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c +index 4bc85cb8be6a..e8a93bc8285d 100644 +--- a/fs/proc/kcore.c ++++ b/fs/proc/kcore.c +@@ -512,23 +512,15 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) + return -EFAULT; + } else { + if (kern_addr_valid(start)) { +- unsigned long n; +- + /* + * Using bounce buffer to bypass the + * hardened user copy kernel text checks. + */ +- memcpy(buf, (char *) start, tsz); +- n = copy_to_user(buffer, buf, tsz); +- /* +- * We cannot distinguish between fault on source +- * and fault on destination. When this happens +- * we clear too and hope it will trigger the +- * EFAULT again. +- */ +- if (n) { +- if (clear_user(buffer + tsz - n, +- n)) ++ if (probe_kernel_read(buf, (void *) start, tsz)) { ++ if (clear_user(buffer, tsz)) ++ return -EFAULT; ++ } else { ++ if (copy_to_user(buffer, buf, tsz)) + return -EFAULT; + } + } else { +diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c +index 417fe0b29f23..ef820f803176 100644 +--- a/fs/ubifs/dir.c ++++ b/fs/ubifs/dir.c +@@ -1216,10 +1216,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, + ostr.len = disk_link.len; + + err = fscrypt_fname_usr_to_disk(inode, &istr, &ostr); +- if (err) { +- kfree(sd); ++ if (err) + goto out_inode; +- } + + sd->len = cpu_to_le16(ostr.len); + disk_link.name = (char *)sd; +@@ -1251,11 +1249,10 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, + goto out_cancel; + mutex_unlock(&dir_ui->ui_mutex); + +- ubifs_release_budget(c, &req); + insert_inode_hash(inode); + d_instantiate(dentry, inode); +- fscrypt_free_filename(&nm); +- return 0; ++ err = 0; ++ goto out_fname; + + out_cancel: + dir->i_size -= sz_change; +@@ -1268,6 +1265,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, + fscrypt_free_filename(&nm); + out_budg: + ubifs_release_budget(c, &req); ++ kfree(sd); + return err; + } + +diff --git a/include/crypto/hash.h b/include/crypto/hash.h +index 0ed31fd80242..3880793e280e 100644 +--- a/include/crypto/hash.h ++++ b/include/crypto/hash.h +@@ -210,7 +210,6 @@ struct crypto_ahash { + unsigned int keylen); + + unsigned int reqsize; +- bool has_setkey; + struct crypto_tfm base; + }; + +@@ -410,11 +409,6 @@ static inline void *ahash_request_ctx(struct ahash_request *req) + int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen); + +-static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm) +-{ +- return tfm->has_setkey; +-} +- + /** + * crypto_ahash_finup() - update and finalize message digest + * @req: reference to the ahash_request handle that holds all information +@@ -487,7 +481,12 @@ static inline int crypto_ahash_export(struct ahash_request *req, void *out) + */ + static inline int crypto_ahash_import(struct ahash_request *req, const void *in) + { +- return crypto_ahash_reqtfm(req)->import(req, in); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return tfm->import(req, in); + } + + /** +@@ -503,7 +502,12 @@ static inline int crypto_ahash_import(struct ahash_request *req, const void *in) + */ + static inline int crypto_ahash_init(struct ahash_request *req) + { +- return crypto_ahash_reqtfm(req)->init(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return tfm->init(req); + } + + /** +@@ -855,7 +859,12 @@ static inline int crypto_shash_export(struct shash_desc *desc, void *out) + */ + static inline int crypto_shash_import(struct shash_desc *desc, const void *in) + { +- return crypto_shash_alg(desc->tfm)->import(desc, in); ++ struct crypto_shash *tfm = desc->tfm; ++ ++ if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return crypto_shash_alg(tfm)->import(desc, in); + } + + /** +@@ -871,7 +880,12 @@ static inline int crypto_shash_import(struct shash_desc *desc, const void *in) + */ + static inline int crypto_shash_init(struct shash_desc *desc) + { +- return crypto_shash_alg(desc->tfm)->init(desc); ++ struct crypto_shash *tfm = desc->tfm; ++ ++ if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return crypto_shash_alg(tfm)->init(desc); + } + + /** +diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h +index c2bae8da642c..27040a46d50a 100644 +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -90,6 +90,8 @@ static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) + return alg->setkey != shash_no_setkey; + } + ++bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg); ++ + int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, + struct hash_alg_common *alg, + struct crypto_instance *inst); +diff --git a/include/crypto/poly1305.h b/include/crypto/poly1305.h +index c65567d01e8e..f718a19da82f 100644 +--- a/include/crypto/poly1305.h ++++ b/include/crypto/poly1305.h +@@ -31,8 +31,6 @@ struct poly1305_desc_ctx { + }; + + int crypto_poly1305_init(struct shash_desc *desc); +-int crypto_poly1305_setkey(struct crypto_shash *tfm, +- const u8 *key, unsigned int keylen); + unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, + const u8 *src, unsigned int srclen); + int crypto_poly1305_update(struct shash_desc *desc, +diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h +new file mode 100644 +index 000000000000..e518e4e3dfb5 +--- /dev/null ++++ b/include/kvm/arm_psci.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2012,2013 - ARM Ltd ++ * Author: Marc Zyngier ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef __KVM_ARM_PSCI_H__ ++#define __KVM_ARM_PSCI_H__ ++ ++#include ++#include ++ ++#define KVM_ARM_PSCI_0_1 PSCI_VERSION(0, 1) ++#define KVM_ARM_PSCI_0_2 PSCI_VERSION(0, 2) ++#define KVM_ARM_PSCI_1_0 PSCI_VERSION(1, 0) ++ ++#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_0 ++ ++/* ++ * We need the KVM pointer independently from the vcpu as we can call ++ * this from HYP, and need to apply kern_hyp_va on it... ++ */ ++static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm) ++{ ++ /* ++ * Our PSCI implementation stays the same across versions from ++ * v0.2 onward, only adding the few mandatory functions (such ++ * as FEATURES with 1.0) that are required by newer ++ * revisions. It is thus safe to return the latest. ++ */ ++ if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) ++ return KVM_ARM_PSCI_LATEST; ++ ++ return KVM_ARM_PSCI_0_1; ++} ++ ++ ++int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); ++ ++#endif /* __KVM_ARM_PSCI_H__ */ +diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h +index 4c5bca38c653..a031897fca76 100644 +--- a/include/linux/arm-smccc.h ++++ b/include/linux/arm-smccc.h +@@ -14,14 +14,16 @@ + #ifndef __LINUX_ARM_SMCCC_H + #define __LINUX_ARM_SMCCC_H + ++#include ++ + /* + * This file provides common defines for ARM SMC Calling Convention as + * specified in + * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + */ + +-#define ARM_SMCCC_STD_CALL 0 +-#define ARM_SMCCC_FAST_CALL 1 ++#define ARM_SMCCC_STD_CALL _AC(0,U) ++#define ARM_SMCCC_FAST_CALL _AC(1,U) + #define ARM_SMCCC_TYPE_SHIFT 31 + + #define ARM_SMCCC_SMC_32 0 +@@ -60,6 +62,24 @@ + #define ARM_SMCCC_QUIRK_NONE 0 + #define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */ + ++#define ARM_SMCCC_VERSION_1_0 0x10000 ++#define ARM_SMCCC_VERSION_1_1 0x10001 ++ ++#define ARM_SMCCC_VERSION_FUNC_ID \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_32, \ ++ 0, 0) ++ ++#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_32, \ ++ 0, 1) ++ ++#define ARM_SMCCC_ARCH_WORKAROUND_1 \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_32, \ ++ 0, 0x8000) ++ + #ifndef __ASSEMBLY__ + + #include +@@ -130,5 +150,146 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, + + #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__) + ++/* SMCCC v1.1 implementation madness follows */ ++#ifdef CONFIG_ARM64 ++ ++#define SMCCC_SMC_INST "smc #0" ++#define SMCCC_HVC_INST "hvc #0" ++ ++#elif defined(CONFIG_ARM) ++#include ++#include ++ ++#define SMCCC_SMC_INST __SMC(0) ++#define SMCCC_HVC_INST __HVC(0) ++ ++#endif ++ ++#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x ++ ++#define __count_args(...) \ ++ ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) ++ ++#define __constraint_write_0 \ ++ "+r" (r0), "=&r" (r1), "=&r" (r2), "=&r" (r3) ++#define __constraint_write_1 \ ++ "+r" (r0), "+r" (r1), "=&r" (r2), "=&r" (r3) ++#define __constraint_write_2 \ ++ "+r" (r0), "+r" (r1), "+r" (r2), "=&r" (r3) ++#define __constraint_write_3 \ ++ "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3) ++#define __constraint_write_4 __constraint_write_3 ++#define __constraint_write_5 __constraint_write_4 ++#define __constraint_write_6 __constraint_write_5 ++#define __constraint_write_7 __constraint_write_6 ++ ++#define __constraint_read_0 ++#define __constraint_read_1 ++#define __constraint_read_2 ++#define __constraint_read_3 ++#define __constraint_read_4 "r" (r4) ++#define __constraint_read_5 __constraint_read_4, "r" (r5) ++#define __constraint_read_6 __constraint_read_5, "r" (r6) ++#define __constraint_read_7 __constraint_read_6, "r" (r7) ++ ++#define __declare_arg_0(a0, res) \ ++ struct arm_smccc_res *___res = res; \ ++ register u32 r0 asm("r0") = a0; \ ++ register unsigned long r1 asm("r1"); \ ++ register unsigned long r2 asm("r2"); \ ++ register unsigned long r3 asm("r3") ++ ++#define __declare_arg_1(a0, a1, res) \ ++ struct arm_smccc_res *___res = res; \ ++ register u32 r0 asm("r0") = a0; \ ++ register typeof(a1) r1 asm("r1") = a1; \ ++ register unsigned long r2 asm("r2"); \ ++ register unsigned long r3 asm("r3") ++ ++#define __declare_arg_2(a0, a1, a2, res) \ ++ struct arm_smccc_res *___res = res; \ ++ register u32 r0 asm("r0") = a0; \ ++ register typeof(a1) r1 asm("r1") = a1; \ ++ register typeof(a2) r2 asm("r2") = a2; \ ++ register unsigned long r3 asm("r3") ++ ++#define __declare_arg_3(a0, a1, a2, a3, res) \ ++ struct arm_smccc_res *___res = res; \ ++ register u32 r0 asm("r0") = a0; \ ++ register typeof(a1) r1 asm("r1") = a1; \ ++ register typeof(a2) r2 asm("r2") = a2; \ ++ register typeof(a3) r3 asm("r3") = a3 ++ ++#define __declare_arg_4(a0, a1, a2, a3, a4, res) \ ++ __declare_arg_3(a0, a1, a2, a3, res); \ ++ register typeof(a4) r4 asm("r4") = a4 ++ ++#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \ ++ __declare_arg_4(a0, a1, a2, a3, a4, res); \ ++ register typeof(a5) r5 asm("r5") = a5 ++ ++#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \ ++ __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \ ++ register typeof(a6) r6 asm("r6") = a6 ++ ++#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \ ++ __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \ ++ register typeof(a7) r7 asm("r7") = a7 ++ ++#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__) ++#define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__) ++ ++#define ___constraints(count) \ ++ : __constraint_write_ ## count \ ++ : __constraint_read_ ## count \ ++ : "memory" ++#define __constraints(count) ___constraints(count) ++ ++/* ++ * We have an output list that is not necessarily used, and GCC feels ++ * entitled to optimise the whole sequence away. "volatile" is what ++ * makes it stick. ++ */ ++#define __arm_smccc_1_1(inst, ...) \ ++ do { \ ++ __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ ++ asm volatile(inst "\n" \ ++ __constraints(__count_args(__VA_ARGS__))); \ ++ if (___res) \ ++ *___res = (typeof(*___res)){r0, r1, r2, r3}; \ ++ } while (0) ++ ++/* ++ * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call ++ * ++ * This is a variadic macro taking one to eight source arguments, and ++ * an optional return structure. ++ * ++ * @a0-a7: arguments passed in registers 0 to 7 ++ * @res: result values from registers 0 to 3 ++ * ++ * This macro is used to make SMC calls following SMC Calling Convention v1.1. ++ * The content of the supplied param are copied to registers 0 to 7 prior ++ * to the SMC instruction. The return values are updated with the content ++ * from register 0 to 3 on return from the SMC instruction if not NULL. ++ */ ++#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__) ++ ++/* ++ * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call ++ * ++ * This is a variadic macro taking one to eight source arguments, and ++ * an optional return structure. ++ * ++ * @a0-a7: arguments passed in registers 0 to 7 ++ * @res: result values from registers 0 to 3 ++ * ++ * This macro is used to make HVC calls following SMC Calling Convention v1.1. ++ * The content of the supplied param are copied to registers 0 to 7 prior ++ * to the HVC instruction. The return values are updated with the content ++ * from register 0 to 3 on return from the HVC instruction if not NULL. ++ */ ++#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) ++ + #endif /*__ASSEMBLY__*/ + #endif /*__LINUX_ARM_SMCCC_H*/ +diff --git a/include/linux/crypto.h b/include/linux/crypto.h +index 78508ca4b108..29c4257f9c5b 100644 +--- a/include/linux/crypto.h ++++ b/include/linux/crypto.h +@@ -106,9 +106,17 @@ + */ + #define CRYPTO_ALG_INTERNAL 0x00002000 + ++/* ++ * Set if the algorithm has a ->setkey() method but can be used without ++ * calling it first, i.e. there is a default key. ++ */ ++#define CRYPTO_ALG_OPTIONAL_KEY 0x00004000 ++ + /* + * Transform masks and values (for crt_flags). + */ ++#define CRYPTO_TFM_NEED_KEY 0x00000001 ++ + #define CRYPTO_TFM_REQ_MASK 0x000fff00 + #define CRYPTO_TFM_RES_MASK 0xfff00000 + +diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h +index 3aa56e3104bb..b5b43f94f311 100644 +--- a/include/linux/mtd/map.h ++++ b/include/linux/mtd/map.h +@@ -270,75 +270,67 @@ void map_destroy(struct mtd_info *mtd); + #define INVALIDATE_CACHED_RANGE(map, from, size) \ + do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0) + +- +-static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2) +-{ +- int i; +- +- for (i = 0; i < map_words(map); i++) { +- if (val1.x[i] != val2.x[i]) +- return 0; +- } +- +- return 1; +-} +- +-static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2) +-{ +- map_word r; +- int i; +- +- for (i = 0; i < map_words(map); i++) +- r.x[i] = val1.x[i] & val2.x[i]; +- +- return r; +-} +- +-static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2) +-{ +- map_word r; +- int i; +- +- for (i = 0; i < map_words(map); i++) +- r.x[i] = val1.x[i] & ~val2.x[i]; +- +- return r; +-} +- +-static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2) +-{ +- map_word r; +- int i; +- +- for (i = 0; i < map_words(map); i++) +- r.x[i] = val1.x[i] | val2.x[i]; +- +- return r; +-} +- +-static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3) +-{ +- int i; +- +- for (i = 0; i < map_words(map); i++) { +- if ((val1.x[i] & val2.x[i]) != val3.x[i]) +- return 0; +- } +- +- return 1; +-} +- +-static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2) +-{ +- int i; +- +- for (i = 0; i < map_words(map); i++) { +- if (val1.x[i] & val2.x[i]) +- return 1; +- } +- +- return 0; +-} ++#define map_word_equal(map, val1, val2) \ ++({ \ ++ int i, ret = 1; \ ++ for (i = 0; i < map_words(map); i++) \ ++ if ((val1).x[i] != (val2).x[i]) { \ ++ ret = 0; \ ++ break; \ ++ } \ ++ ret; \ ++}) ++ ++#define map_word_and(map, val1, val2) \ ++({ \ ++ map_word r; \ ++ int i; \ ++ for (i = 0; i < map_words(map); i++) \ ++ r.x[i] = (val1).x[i] & (val2).x[i]; \ ++ r; \ ++}) ++ ++#define map_word_clr(map, val1, val2) \ ++({ \ ++ map_word r; \ ++ int i; \ ++ for (i = 0; i < map_words(map); i++) \ ++ r.x[i] = (val1).x[i] & ~(val2).x[i]; \ ++ r; \ ++}) ++ ++#define map_word_or(map, val1, val2) \ ++({ \ ++ map_word r; \ ++ int i; \ ++ for (i = 0; i < map_words(map); i++) \ ++ r.x[i] = (val1).x[i] | (val2).x[i]; \ ++ r; \ ++}) ++ ++#define map_word_andequal(map, val1, val2, val3) \ ++({ \ ++ int i, ret = 1; \ ++ for (i = 0; i < map_words(map); i++) { \ ++ if (((val1).x[i] & (val2).x[i]) != (val2).x[i]) { \ ++ ret = 0; \ ++ break; \ ++ } \ ++ } \ ++ ret; \ ++}) ++ ++#define map_word_bitsset(map, val1, val2) \ ++({ \ ++ int i, ret = 0; \ ++ for (i = 0; i < map_words(map); i++) { \ ++ if ((val1).x[i] & (val2).x[i]) { \ ++ ret = 1; \ ++ break; \ ++ } \ ++ } \ ++ ret; \ ++}) + + static inline map_word map_word_load(struct map_info *map, const void *ptr) + { +diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h +index 47adac640191..57ffaa20d564 100644 +--- a/include/linux/nfs4.h ++++ b/include/linux/nfs4.h +@@ -457,7 +457,12 @@ enum lock_type4 { + + #define NFS4_DEBUG 1 + +-/* Index of predefined Linux client operations */ ++/* ++ * Index of predefined Linux client operations ++ * ++ * To ensure that /proc/net/rpc/nfs remains correctly ordered, please ++ * append only to this enum when adding new client operations. ++ */ + + enum { + NFSPROC4_CLNT_NULL = 0, /* Unused */ +@@ -480,7 +485,6 @@ enum { + NFSPROC4_CLNT_ACCESS, + NFSPROC4_CLNT_GETATTR, + NFSPROC4_CLNT_LOOKUP, +- NFSPROC4_CLNT_LOOKUPP, + NFSPROC4_CLNT_LOOKUP_ROOT, + NFSPROC4_CLNT_REMOVE, + NFSPROC4_CLNT_RENAME, +@@ -500,7 +504,6 @@ enum { + NFSPROC4_CLNT_SECINFO, + NFSPROC4_CLNT_FSID_PRESENT, + +- /* nfs41 */ + NFSPROC4_CLNT_EXCHANGE_ID, + NFSPROC4_CLNT_CREATE_SESSION, + NFSPROC4_CLNT_DESTROY_SESSION, +@@ -518,13 +521,14 @@ enum { + NFSPROC4_CLNT_BIND_CONN_TO_SESSION, + NFSPROC4_CLNT_DESTROY_CLIENTID, + +- /* nfs42 */ + NFSPROC4_CLNT_SEEK, + NFSPROC4_CLNT_ALLOCATE, + NFSPROC4_CLNT_DEALLOCATE, + NFSPROC4_CLNT_LAYOUTSTATS, + NFSPROC4_CLNT_CLONE, + NFSPROC4_CLNT_COPY, ++ ++ NFSPROC4_CLNT_LOOKUPP, + }; + + /* nfs41 types */ +diff --git a/include/linux/psci.h b/include/linux/psci.h +index bdea1cb5e1db..347077cf19c6 100644 +--- a/include/linux/psci.h ++++ b/include/linux/psci.h +@@ -25,7 +25,19 @@ bool psci_tos_resident_on(int cpu); + int psci_cpu_init_idle(unsigned int cpu); + int psci_cpu_suspend_enter(unsigned long index); + ++enum psci_conduit { ++ PSCI_CONDUIT_NONE, ++ PSCI_CONDUIT_SMC, ++ PSCI_CONDUIT_HVC, ++}; ++ ++enum smccc_version { ++ SMCCC_VERSION_1_0, ++ SMCCC_VERSION_1_1, ++}; ++ + struct psci_operations { ++ u32 (*get_version)(void); + int (*cpu_suspend)(u32 state, unsigned long entry_point); + int (*cpu_off)(u32 state); + int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); +@@ -33,6 +45,8 @@ struct psci_operations { + int (*affinity_info)(unsigned long target_affinity, + unsigned long lowest_affinity_level); + int (*migrate_info_type)(void); ++ enum psci_conduit conduit; ++ enum smccc_version smccc_version; + }; + + extern struct psci_operations psci_ops; +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index a8b7bf879ced..1a1df0d21ee3 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -571,6 +571,8 @@ struct Scsi_Host { + struct blk_mq_tag_set tag_set; + }; + ++ struct rcu_head rcu; ++ + atomic_t host_busy; /* commands actually active on low-level */ + atomic_t host_blocked; + +diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h +index 760e52a9640f..b3bcabe380da 100644 +--- a/include/uapi/linux/psci.h ++++ b/include/uapi/linux/psci.h +@@ -88,6 +88,9 @@ + (((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT) + #define PSCI_VERSION_MINOR(ver) \ + ((ver) & PSCI_VERSION_MINOR_MASK) ++#define PSCI_VERSION(maj, min) \ ++ ((((maj) << PSCI_VERSION_MAJOR_SHIFT) & PSCI_VERSION_MAJOR_MASK) | \ ++ ((min) & PSCI_VERSION_MINOR_MASK)) + + /* PSCI features decoding (>=1.0) */ + #define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1 +diff --git a/kernel/async.c b/kernel/async.c +index 2cbd3dd5940d..a893d6170944 100644 +--- a/kernel/async.c ++++ b/kernel/async.c +@@ -84,20 +84,24 @@ static atomic_t entry_count; + + static async_cookie_t lowest_in_progress(struct async_domain *domain) + { +- struct list_head *pending; ++ struct async_entry *first = NULL; + async_cookie_t ret = ASYNC_COOKIE_MAX; + unsigned long flags; + + spin_lock_irqsave(&async_lock, flags); + +- if (domain) +- pending = &domain->pending; +- else +- pending = &async_global_pending; ++ if (domain) { ++ if (!list_empty(&domain->pending)) ++ first = list_first_entry(&domain->pending, ++ struct async_entry, domain_list); ++ } else { ++ if (!list_empty(&async_global_pending)) ++ first = list_first_entry(&async_global_pending, ++ struct async_entry, global_list); ++ } + +- if (!list_empty(pending)) +- ret = list_first_entry(pending, struct async_entry, +- domain_list)->cookie; ++ if (first) ++ ret = first->cookie; + + spin_unlock_irqrestore(&async_lock, flags); + return ret; +diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c +index 4e8089b319ae..8c82ea26e837 100644 +--- a/kernel/irq/autoprobe.c ++++ b/kernel/irq/autoprobe.c +@@ -71,7 +71,7 @@ unsigned long probe_irq_on(void) + raw_spin_lock_irq(&desc->lock); + if (!desc->action && irq_settings_can_probe(desc)) { + desc->istate |= IRQS_AUTODETECT | IRQS_WAITING; +- if (irq_startup(desc, IRQ_NORESEND, IRQ_START_FORCE)) ++ if (irq_activate_and_startup(desc, IRQ_NORESEND)) + desc->istate |= IRQS_PENDING; + } + raw_spin_unlock_irq(&desc->lock); +diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c +index 043bfc35b353..c69357a43849 100644 +--- a/kernel/irq/chip.c ++++ b/kernel/irq/chip.c +@@ -294,11 +294,11 @@ int irq_activate(struct irq_desc *desc) + return 0; + } + +-void irq_activate_and_startup(struct irq_desc *desc, bool resend) ++int irq_activate_and_startup(struct irq_desc *desc, bool resend) + { + if (WARN_ON(irq_activate(desc))) +- return; +- irq_startup(desc, resend, IRQ_START_FORCE); ++ return 0; ++ return irq_startup(desc, resend, IRQ_START_FORCE); + } + + static void __irq_disable(struct irq_desc *desc, bool mask); +diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h +index ab19371eab9b..ca6afa267070 100644 +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -76,7 +76,7 @@ extern void __enable_irq(struct irq_desc *desc); + #define IRQ_START_COND false + + extern int irq_activate(struct irq_desc *desc); +-extern void irq_activate_and_startup(struct irq_desc *desc, bool resend); ++extern int irq_activate_and_startup(struct irq_desc *desc, bool resend); + extern int irq_startup(struct irq_desc *desc, bool resend, bool force); + + extern void irq_shutdown(struct irq_desc *desc); +diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c +index fbd56d6e575b..68fa19a5e7bd 100644 +--- a/kernel/rcu/update.c ++++ b/kernel/rcu/update.c +@@ -422,11 +422,13 @@ void init_rcu_head(struct rcu_head *head) + { + debug_object_init(head, &rcuhead_debug_descr); + } ++EXPORT_SYMBOL_GPL(init_rcu_head); + + void destroy_rcu_head(struct rcu_head *head) + { + debug_object_free(head, &rcuhead_debug_descr); + } ++EXPORT_SYMBOL_GPL(destroy_rcu_head); + + static bool rcuhead_is_static_object(void *addr) + { +diff --git a/kernel/relay.c b/kernel/relay.c +index 39a9dfc69486..55da824f4adc 100644 +--- a/kernel/relay.c ++++ b/kernel/relay.c +@@ -611,7 +611,6 @@ struct rchan *relay_open(const char *base_filename, + + kref_put(&chan->kref, relay_destroy_channel); + mutex_unlock(&relay_channels_mutex); +- kfree(chan); + return NULL; + } + EXPORT_SYMBOL_GPL(relay_open); +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 665ace2fc558..3401f588c916 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -1907,9 +1907,8 @@ static void push_rt_tasks(struct rq *rq) + * the rt_loop_next will cause the iterator to perform another scan. + * + */ +-static int rto_next_cpu(struct rq *rq) ++static int rto_next_cpu(struct root_domain *rd) + { +- struct root_domain *rd = rq->rd; + int next; + int cpu; + +@@ -1985,19 +1984,24 @@ static void tell_cpu_to_push(struct rq *rq) + * Otherwise it is finishing up and an ipi needs to be sent. + */ + if (rq->rd->rto_cpu < 0) +- cpu = rto_next_cpu(rq); ++ cpu = rto_next_cpu(rq->rd); + + raw_spin_unlock(&rq->rd->rto_lock); + + rto_start_unlock(&rq->rd->rto_loop_start); + +- if (cpu >= 0) ++ if (cpu >= 0) { ++ /* Make sure the rd does not get freed while pushing */ ++ sched_get_rd(rq->rd); + irq_work_queue_on(&rq->rd->rto_push_work, cpu); ++ } + } + + /* Called from hardirq context */ + void rto_push_irq_work_func(struct irq_work *work) + { ++ struct root_domain *rd = ++ container_of(work, struct root_domain, rto_push_work); + struct rq *rq; + int cpu; + +@@ -2013,18 +2017,20 @@ void rto_push_irq_work_func(struct irq_work *work) + raw_spin_unlock(&rq->lock); + } + +- raw_spin_lock(&rq->rd->rto_lock); ++ raw_spin_lock(&rd->rto_lock); + + /* Pass the IPI to the next rt overloaded queue */ +- cpu = rto_next_cpu(rq); ++ cpu = rto_next_cpu(rd); + +- raw_spin_unlock(&rq->rd->rto_lock); ++ raw_spin_unlock(&rd->rto_lock); + +- if (cpu < 0) ++ if (cpu < 0) { ++ sched_put_rd(rd); + return; ++ } + + /* Try the next RT overloaded CPU */ +- irq_work_queue_on(&rq->rd->rto_push_work, cpu); ++ irq_work_queue_on(&rd->rto_push_work, cpu); + } + #endif /* HAVE_RT_PUSH_IPI */ + +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index b19552a212de..74b57279e3ff 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -665,6 +665,8 @@ extern struct mutex sched_domains_mutex; + extern void init_defrootdomain(void); + extern int sched_init_domains(const struct cpumask *cpu_map); + extern void rq_attach_root(struct rq *rq, struct root_domain *rd); ++extern void sched_get_rd(struct root_domain *rd); ++extern void sched_put_rd(struct root_domain *rd); + + #ifdef HAVE_RT_PUSH_IPI + extern void rto_push_irq_work_func(struct irq_work *work); +diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c +index 034cbed7f88b..519b024f4e94 100644 +--- a/kernel/sched/topology.c ++++ b/kernel/sched/topology.c +@@ -259,6 +259,19 @@ void rq_attach_root(struct rq *rq, struct root_domain *rd) + call_rcu_sched(&old_rd->rcu, free_rootdomain); + } + ++void sched_get_rd(struct root_domain *rd) ++{ ++ atomic_inc(&rd->refcount); ++} ++ ++void sched_put_rd(struct root_domain *rd) ++{ ++ if (!atomic_dec_and_test(&rd->refcount)) ++ return; ++ ++ call_rcu_sched(&rd->rcu, free_rootdomain); ++} ++ + static int init_rootdomain(struct root_domain *rd) + { + if (!zalloc_cpumask_var(&rd->span, GFP_KERNEL)) +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index 554b517c61a0..a7741d14f51b 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -4456,7 +4456,6 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, + func_g.type = filter_parse_regex(glob, strlen(glob), + &func_g.search, ¬); + func_g.len = strlen(func_g.search); +- func_g.search = glob; + + /* we do not support '!' for function probes */ + if (WARN_ON(not)) +diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug +index 9d5b78aad4c5..f55c15ab6f93 100644 +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -217,7 +217,7 @@ config ENABLE_MUST_CHECK + config FRAME_WARN + int "Warn for stack frames larger than (needs gcc 4.4)" + range 0 8192 +- default 0 if KASAN ++ default 3072 if KASAN_EXTRA + default 2048 if GCC_PLUGIN_LATENT_ENTROPY + default 1280 if (!64BIT && PARISC) + default 1024 if (!64BIT && !PARISC) +diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan +index bd38aab05929..3d35d062970d 100644 +--- a/lib/Kconfig.kasan ++++ b/lib/Kconfig.kasan +@@ -20,6 +20,17 @@ config KASAN + Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB + (the resulting kernel does not boot). + ++config KASAN_EXTRA ++ bool "KAsan: extra checks" ++ depends on KASAN && DEBUG_KERNEL && !COMPILE_TEST ++ help ++ This enables further checks in the kernel address sanitizer, for now ++ it only includes the address-use-after-scope check that can lead ++ to excessive kernel stack usage, frame size warnings and longer ++ compile time. ++ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 has more ++ ++ + choice + prompt "Instrumentation type" + depends on KASAN +diff --git a/lib/ubsan.c b/lib/ubsan.c +index fb0409df1bcf..50d1d5c25deb 100644 +--- a/lib/ubsan.c ++++ b/lib/ubsan.c +@@ -265,14 +265,14 @@ void __ubsan_handle_divrem_overflow(struct overflow_data *data, + } + EXPORT_SYMBOL(__ubsan_handle_divrem_overflow); + +-static void handle_null_ptr_deref(struct type_mismatch_data *data) ++static void handle_null_ptr_deref(struct type_mismatch_data_common *data) + { + unsigned long flags; + +- if (suppress_report(&data->location)) ++ if (suppress_report(data->location)) + return; + +- ubsan_prologue(&data->location, &flags); ++ ubsan_prologue(data->location, &flags); + + pr_err("%s null pointer of type %s\n", + type_check_kinds[data->type_check_kind], +@@ -281,15 +281,15 @@ static void handle_null_ptr_deref(struct type_mismatch_data *data) + ubsan_epilogue(&flags); + } + +-static void handle_missaligned_access(struct type_mismatch_data *data, ++static void handle_misaligned_access(struct type_mismatch_data_common *data, + unsigned long ptr) + { + unsigned long flags; + +- if (suppress_report(&data->location)) ++ if (suppress_report(data->location)) + return; + +- ubsan_prologue(&data->location, &flags); ++ ubsan_prologue(data->location, &flags); + + pr_err("%s misaligned address %p for type %s\n", + type_check_kinds[data->type_check_kind], +@@ -299,15 +299,15 @@ static void handle_missaligned_access(struct type_mismatch_data *data, + ubsan_epilogue(&flags); + } + +-static void handle_object_size_mismatch(struct type_mismatch_data *data, ++static void handle_object_size_mismatch(struct type_mismatch_data_common *data, + unsigned long ptr) + { + unsigned long flags; + +- if (suppress_report(&data->location)) ++ if (suppress_report(data->location)) + return; + +- ubsan_prologue(&data->location, &flags); ++ ubsan_prologue(data->location, &flags); + pr_err("%s address %p with insufficient space\n", + type_check_kinds[data->type_check_kind], + (void *) ptr); +@@ -315,19 +315,47 @@ static void handle_object_size_mismatch(struct type_mismatch_data *data, + ubsan_epilogue(&flags); + } + +-void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, ++static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data, + unsigned long ptr) + { + + if (!ptr) + handle_null_ptr_deref(data); + else if (data->alignment && !IS_ALIGNED(ptr, data->alignment)) +- handle_missaligned_access(data, ptr); ++ handle_misaligned_access(data, ptr); + else + handle_object_size_mismatch(data, ptr); + } ++ ++void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, ++ unsigned long ptr) ++{ ++ struct type_mismatch_data_common common_data = { ++ .location = &data->location, ++ .type = data->type, ++ .alignment = data->alignment, ++ .type_check_kind = data->type_check_kind ++ }; ++ ++ ubsan_type_mismatch_common(&common_data, ptr); ++} + EXPORT_SYMBOL(__ubsan_handle_type_mismatch); + ++void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data, ++ unsigned long ptr) ++{ ++ ++ struct type_mismatch_data_common common_data = { ++ .location = &data->location, ++ .type = data->type, ++ .alignment = 1UL << data->log_alignment, ++ .type_check_kind = data->type_check_kind ++ }; ++ ++ ubsan_type_mismatch_common(&common_data, ptr); ++} ++EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1); ++ + void __ubsan_handle_nonnull_return(struct nonnull_return_data *data) + { + unsigned long flags; +diff --git a/lib/ubsan.h b/lib/ubsan.h +index 88f23557edbe..7e30b26497e0 100644 +--- a/lib/ubsan.h ++++ b/lib/ubsan.h +@@ -37,6 +37,20 @@ struct type_mismatch_data { + unsigned char type_check_kind; + }; + ++struct type_mismatch_data_v1 { ++ struct source_location location; ++ struct type_descriptor *type; ++ unsigned char log_alignment; ++ unsigned char type_check_kind; ++}; ++ ++struct type_mismatch_data_common { ++ struct source_location *location; ++ struct type_descriptor *type; ++ unsigned long alignment; ++ unsigned char type_check_kind; ++}; ++ + struct nonnull_arg_data { + struct source_location location; + struct source_location attr_location; +diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan +index 1ce7115aa499..97a56c0b565a 100644 +--- a/scripts/Makefile.kasan ++++ b/scripts/Makefile.kasan +@@ -30,5 +30,10 @@ else + endif + endif + ++ifdef CONFIG_KASAN_EXTRA + CFLAGS_KASAN += $(call cc-option, -fsanitize-address-use-after-scope) + endif ++ ++CFLAGS_KASAN_NOSANITIZE := -fno-builtin ++ ++endif +diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib +index 1ca4dcd2d500..015aa9dbad86 100644 +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -121,7 +121,7 @@ endif + ifeq ($(CONFIG_KASAN),y) + _c_flags += $(if $(patsubst n%,, \ + $(KASAN_SANITIZE_$(basetarget).o)$(KASAN_SANITIZE)y), \ +- $(CFLAGS_KASAN)) ++ $(CFLAGS_KASAN), $(CFLAGS_KASAN_NOSANITIZE)) + endif + + ifeq ($(CONFIG_UBSAN),y) +diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c +index 3eaac41090ca..26b0a5caea5a 100644 +--- a/sound/soc/intel/skylake/skl-nhlt.c ++++ b/sound/soc/intel/skylake/skl-nhlt.c +@@ -43,7 +43,8 @@ struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) + obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); + if (obj && obj->type == ACPI_TYPE_BUFFER) { + nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; +- nhlt_table = (struct nhlt_acpi_table *) ++ if (nhlt_ptr->length) ++ nhlt_table = (struct nhlt_acpi_table *) + memremap(nhlt_ptr->min_addr, nhlt_ptr->length, + MEMREMAP_WB); + ACPI_FREE(obj); +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 908211e1d6fc..eb27f6c24bf7 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -504,6 +504,7 @@ static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg) + case I2S_INTCR: + case I2S_XFER: + case I2S_CLR: ++ case I2S_TXDR: + case I2S_RXDR: + case I2S_FIFOLR: + case I2S_INTSR: +@@ -518,6 +519,9 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + switch (reg) { + case I2S_INTSR: + case I2S_CLR: ++ case I2S_FIFOLR: ++ case I2S_TXDR: ++ case I2S_RXDR: + return true; + default: + return false; +@@ -527,6 +531,8 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg) + { + switch (reg) { ++ case I2S_RXDR: ++ return true; + default: + return false; + } +diff --git a/sound/soc/soc-acpi.c b/sound/soc/soc-acpi.c +index f21df28bc28e..d4dd2efea45e 100644 +--- a/sound/soc/soc-acpi.c ++++ b/sound/soc/soc-acpi.c +@@ -84,11 +84,9 @@ snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines) + + for (mach = machines; mach->id[0]; mach++) { + if (snd_soc_acpi_check_hid(mach->id) == true) { +- if (mach->machine_quirk == NULL) +- return mach; +- +- if (mach->machine_quirk(mach) != NULL) +- return mach; ++ if (mach->machine_quirk) ++ mach = mach->machine_quirk(mach); ++ return mach; + } + } + return NULL; +diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c +index d9b1e6417fb9..1507117d1185 100644 +--- a/sound/soc/soc-compress.c ++++ b/sound/soc/soc-compress.c +@@ -944,7 +944,7 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, + struct snd_soc_platform *platform = rtd->platform; + struct snd_soc_component *component; + struct snd_soc_rtdcom_list *rtdcom; +- int ret = 0, __ret; ++ int ret = 0; + + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + +@@ -965,10 +965,10 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, + !component->driver->compr_ops->copy) + continue; + +- __ret = component->driver->compr_ops->copy(cstream, buf, count); +- if (__ret < 0) +- ret = __ret; ++ ret = component->driver->compr_ops->copy(cstream, buf, count); ++ break; + } ++ + err: + mutex_unlock(&rtd->pcm_mutex); + return ret; +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 9cd028aa1509..2e458eb45586 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -851,8 +851,14 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func, + * This is a fairly uncommon pattern which is new for GCC 6. As of this + * writing, there are 11 occurrences of it in the allmodconfig kernel. + * ++ * As of GCC 7 there are quite a few more of these and the 'in between' code ++ * is significant. Esp. with KASAN enabled some of the code between the mov ++ * and jmpq uses .rodata itself, which can confuse things. ++ * + * TODO: Once we have DWARF CFI and smarter instruction decoding logic, + * ensure the same register is used in the mov and jump instructions. ++ * ++ * NOTE: RETPOLINE made it harder still to decode dynamic jumps. + */ + static struct rela *find_switch_table(struct objtool_file *file, + struct symbol *func, +@@ -874,12 +880,25 @@ static struct rela *find_switch_table(struct objtool_file *file, + text_rela->addend + 4); + if (!rodata_rela) + return NULL; ++ + file->ignore_unreachables = true; + return rodata_rela; + } + + /* case 3 */ +- func_for_each_insn_continue_reverse(file, func, insn) { ++ /* ++ * Backward search using the @first_jump_src links, these help avoid ++ * much of the 'in between' code. Which avoids us getting confused by ++ * it. ++ */ ++ for (insn = list_prev_entry(insn, list); ++ ++ &insn->list != &file->insn_list && ++ insn->sec == func->sec && ++ insn->offset >= func->offset; ++ ++ insn = insn->first_jump_src ?: list_prev_entry(insn, list)) { ++ + if (insn->type == INSN_JUMP_DYNAMIC) + break; + +@@ -909,14 +928,32 @@ static struct rela *find_switch_table(struct objtool_file *file, + return NULL; + } + ++ + static int add_func_switch_tables(struct objtool_file *file, + struct symbol *func) + { +- struct instruction *insn, *prev_jump = NULL; ++ struct instruction *insn, *last = NULL, *prev_jump = NULL; + struct rela *rela, *prev_rela = NULL; + int ret; + + func_for_each_insn(file, func, insn) { ++ if (!last) ++ last = insn; ++ ++ /* ++ * Store back-pointers for unconditional forward jumps such ++ * that find_switch_table() can back-track using those and ++ * avoid some potentially confusing code. ++ */ ++ if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && ++ insn->offset > last->offset && ++ insn->jump_dest->offset > insn->offset && ++ !insn->jump_dest->first_jump_src) { ++ ++ insn->jump_dest->first_jump_src = insn; ++ last = insn->jump_dest; ++ } ++ + if (insn->type != INSN_JUMP_DYNAMIC) + continue; + +diff --git a/tools/objtool/check.h b/tools/objtool/check.h +index dbadb304a410..23a1d065cae1 100644 +--- a/tools/objtool/check.h ++++ b/tools/objtool/check.h +@@ -47,6 +47,7 @@ struct instruction { + bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts; + struct symbol *call_dest; + struct instruction *jump_dest; ++ struct instruction *first_jump_src; + struct list_head alts; + struct symbol *func; + struct stack_op stack_op; +diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c +index 2e43f9d42bd5..9a866459bff4 100644 +--- a/virt/kvm/arm/arm.c ++++ b/virt/kvm/arm/arm.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #define CREATE_TRACE_POINTS + #include "trace.h" +@@ -46,7 +47,6 @@ + #include + #include + #include +-#include + #include + + #ifdef REQUIRES_VIRT +@@ -1158,7 +1158,7 @@ static void cpu_init_hyp_mode(void *dummy) + pgd_ptr = kvm_mmu_get_httbr(); + stack_page = __this_cpu_read(kvm_arm_hyp_stack_page); + hyp_stack_ptr = stack_page + PAGE_SIZE; +- vector_ptr = (unsigned long)kvm_ksym_ref(__kvm_hyp_vector); ++ vector_ptr = (unsigned long)kvm_get_hyp_vector(); + + __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr); + __cpu_init_stage2(); +@@ -1239,6 +1239,7 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, + cpu_hyp_reset(); + + return NOTIFY_OK; ++ case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + if (__this_cpu_read(kvm_arm_hardware_enabled)) + /* The hardware was enabled before suspend. */ +@@ -1403,6 +1404,12 @@ static int init_hyp_mode(void) + goto out_err; + } + ++ err = kvm_map_vectors(); ++ if (err) { ++ kvm_err("Cannot map vectors\n"); ++ goto out_err; ++ } ++ + /* + * Map the Hyp stack pages + */ +diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c +index f1e363bab5e8..6919352cbf15 100644 +--- a/virt/kvm/arm/psci.c ++++ b/virt/kvm/arm/psci.c +@@ -15,16 +15,16 @@ + * along with this program. If not, see . + */ + ++#include + #include + #include + #include + + #include + #include +-#include + #include + +-#include ++#include + + /* + * This is an implementation of the Power State Coordination Interface +@@ -33,6 +33,38 @@ + + #define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) + ++static u32 smccc_get_function(struct kvm_vcpu *vcpu) ++{ ++ return vcpu_get_reg(vcpu, 0); ++} ++ ++static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu) ++{ ++ return vcpu_get_reg(vcpu, 1); ++} ++ ++static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu) ++{ ++ return vcpu_get_reg(vcpu, 2); ++} ++ ++static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu) ++{ ++ return vcpu_get_reg(vcpu, 3); ++} ++ ++static void smccc_set_retval(struct kvm_vcpu *vcpu, ++ unsigned long a0, ++ unsigned long a1, ++ unsigned long a2, ++ unsigned long a3) ++{ ++ vcpu_set_reg(vcpu, 0, a0); ++ vcpu_set_reg(vcpu, 1, a1); ++ vcpu_set_reg(vcpu, 2, a2); ++ vcpu_set_reg(vcpu, 3, a3); ++} ++ + static unsigned long psci_affinity_mask(unsigned long affinity_level) + { + if (affinity_level <= 3) +@@ -78,7 +110,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) + unsigned long context_id; + phys_addr_t target_pc; + +- cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK; ++ cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK; + if (vcpu_mode_is_32bit(source_vcpu)) + cpu_id &= ~((u32) 0); + +@@ -91,14 +123,14 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) + if (!vcpu) + return PSCI_RET_INVALID_PARAMS; + if (!vcpu->arch.power_off) { +- if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1) ++ if (kvm_psci_version(source_vcpu, kvm) != KVM_ARM_PSCI_0_1) + return PSCI_RET_ALREADY_ON; + else + return PSCI_RET_INVALID_PARAMS; + } + +- target_pc = vcpu_get_reg(source_vcpu, 2); +- context_id = vcpu_get_reg(source_vcpu, 3); ++ target_pc = smccc_get_arg2(source_vcpu); ++ context_id = smccc_get_arg3(source_vcpu); + + kvm_reset_vcpu(vcpu); + +@@ -117,7 +149,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) + * NOTE: We always update r0 (or x0) because for PSCI v0.1 + * the general puspose registers are undefined upon CPU_ON. + */ +- vcpu_set_reg(vcpu, 0, context_id); ++ smccc_set_retval(vcpu, context_id, 0, 0, 0); + vcpu->arch.power_off = false; + smp_mb(); /* Make sure the above is visible */ + +@@ -137,8 +169,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) + struct kvm *kvm = vcpu->kvm; + struct kvm_vcpu *tmp; + +- target_affinity = vcpu_get_reg(vcpu, 1); +- lowest_affinity_level = vcpu_get_reg(vcpu, 2); ++ target_affinity = smccc_get_arg1(vcpu); ++ lowest_affinity_level = smccc_get_arg2(vcpu); + + /* Determine target affinity mask */ + target_affinity_mask = psci_affinity_mask(lowest_affinity_level); +@@ -200,18 +232,10 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) + kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET); + } + +-int kvm_psci_version(struct kvm_vcpu *vcpu) +-{ +- if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) +- return KVM_ARM_PSCI_0_2; +- +- return KVM_ARM_PSCI_0_1; +-} +- + static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) + { + struct kvm *kvm = vcpu->kvm; +- unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); ++ u32 psci_fn = smccc_get_function(vcpu); + unsigned long val; + int ret = 1; + +@@ -221,7 +245,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) + * Bits[31:16] = Major Version = 0 + * Bits[15:0] = Minor Version = 2 + */ +- val = 2; ++ val = KVM_ARM_PSCI_0_2; + break; + case PSCI_0_2_FN_CPU_SUSPEND: + case PSCI_0_2_FN64_CPU_SUSPEND: +@@ -278,14 +302,56 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) + break; + } + +- vcpu_set_reg(vcpu, 0, val); ++ smccc_set_retval(vcpu, val, 0, 0, 0); ++ return ret; ++} ++ ++static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu) ++{ ++ u32 psci_fn = smccc_get_function(vcpu); ++ u32 feature; ++ unsigned long val; ++ int ret = 1; ++ ++ switch(psci_fn) { ++ case PSCI_0_2_FN_PSCI_VERSION: ++ val = KVM_ARM_PSCI_1_0; ++ break; ++ case PSCI_1_0_FN_PSCI_FEATURES: ++ feature = smccc_get_arg1(vcpu); ++ switch(feature) { ++ case PSCI_0_2_FN_PSCI_VERSION: ++ case PSCI_0_2_FN_CPU_SUSPEND: ++ case PSCI_0_2_FN64_CPU_SUSPEND: ++ case PSCI_0_2_FN_CPU_OFF: ++ case PSCI_0_2_FN_CPU_ON: ++ case PSCI_0_2_FN64_CPU_ON: ++ case PSCI_0_2_FN_AFFINITY_INFO: ++ case PSCI_0_2_FN64_AFFINITY_INFO: ++ case PSCI_0_2_FN_MIGRATE_INFO_TYPE: ++ case PSCI_0_2_FN_SYSTEM_OFF: ++ case PSCI_0_2_FN_SYSTEM_RESET: ++ case PSCI_1_0_FN_PSCI_FEATURES: ++ case ARM_SMCCC_VERSION_FUNC_ID: ++ val = 0; ++ break; ++ default: ++ val = PSCI_RET_NOT_SUPPORTED; ++ break; ++ } ++ break; ++ default: ++ return kvm_psci_0_2_call(vcpu); ++ } ++ ++ smccc_set_retval(vcpu, val, 0, 0, 0); + return ret; + } + + static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) + { + struct kvm *kvm = vcpu->kvm; +- unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); ++ u32 psci_fn = smccc_get_function(vcpu); + unsigned long val; + + switch (psci_fn) { +@@ -303,7 +369,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) + break; + } + +- vcpu_set_reg(vcpu, 0, val); ++ smccc_set_retval(vcpu, val, 0, 0, 0); + return 1; + } + +@@ -321,9 +387,11 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) + * Errors: + * -EINVAL: Unrecognized PSCI function + */ +-int kvm_psci_call(struct kvm_vcpu *vcpu) ++static int kvm_psci_call(struct kvm_vcpu *vcpu) + { +- switch (kvm_psci_version(vcpu)) { ++ switch (kvm_psci_version(vcpu, vcpu->kvm)) { ++ case KVM_ARM_PSCI_1_0: ++ return kvm_psci_1_0_call(vcpu); + case KVM_ARM_PSCI_0_2: + return kvm_psci_0_2_call(vcpu); + case KVM_ARM_PSCI_0_1: +@@ -332,3 +400,30 @@ int kvm_psci_call(struct kvm_vcpu *vcpu) + return -EINVAL; + }; + } ++ ++int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) ++{ ++ u32 func_id = smccc_get_function(vcpu); ++ u32 val = PSCI_RET_NOT_SUPPORTED; ++ u32 feature; ++ ++ switch (func_id) { ++ case ARM_SMCCC_VERSION_FUNC_ID: ++ val = ARM_SMCCC_VERSION_1_1; ++ break; ++ case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: ++ feature = smccc_get_arg1(vcpu); ++ switch(feature) { ++ case ARM_SMCCC_ARCH_WORKAROUND_1: ++ if (kvm_arm_harden_branch_predictor()) ++ val = 0; ++ break; ++ } ++ break; ++ default: ++ return kvm_psci_call(vcpu); ++ } ++ ++ smccc_set_retval(vcpu, val, 0, 0, 0); ++ return 1; ++}