diff options
130 files changed, 1462 insertions, 634 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-cxl b/Documentation/ABI/testing/sysfs-class-cxl index 640f65e79ef1..8e69345c37cc 100644 --- a/Documentation/ABI/testing/sysfs-class-cxl +++ b/Documentation/ABI/testing/sysfs-class-cxl | |||
| @@ -244,3 +244,11 @@ Description: read only | |||
| 244 | Returns 1 if the psl timebase register is synchronized | 244 | Returns 1 if the psl timebase register is synchronized |
| 245 | with the core timebase register, 0 otherwise. | 245 | with the core timebase register, 0 otherwise. |
| 246 | Users: https://github.com/ibm-capi/libcxl | 246 | Users: https://github.com/ibm-capi/libcxl |
| 247 | |||
| 248 | What: /sys/class/cxl/<card>/tunneled_ops_supported | ||
| 249 | Date: May 2018 | ||
| 250 | Contact: linuxppc-dev@lists.ozlabs.org | ||
| 251 | Description: read only | ||
| 252 | Returns 1 if tunneled operations are supported in capi mode, | ||
| 253 | 0 otherwise. | ||
| 254 | Users: https://github.com/ibm-capi/libcxl | ||
diff --git a/Documentation/virtual/kvm/cpuid.txt b/Documentation/virtual/kvm/cpuid.txt index d4f33eb805dd..ab022dcd0911 100644 --- a/Documentation/virtual/kvm/cpuid.txt +++ b/Documentation/virtual/kvm/cpuid.txt | |||
| @@ -72,8 +72,8 @@ KVM_FEATURE_CLOCKSOURCE_STABLE_BIT || 24 || host will warn if no guest-side | |||
| 72 | 72 | ||
| 73 | flag || value || meaning | 73 | flag || value || meaning |
| 74 | ================================================================================== | 74 | ================================================================================== |
| 75 | KVM_HINTS_DEDICATED || 0 || guest checks this feature bit to | 75 | KVM_HINTS_REALTIME || 0 || guest checks this feature bit to |
| 76 | || || determine if there is vCPU pinning | 76 | || || determine that vCPUs are never |
| 77 | || || and there is no vCPU over-commitment, | 77 | || || preempted for an unlimited time, |
| 78 | || || allowing optimizations | 78 | || || allowing optimizations |
| 79 | ---------------------------------------------------------------------------------- | 79 | ---------------------------------------------------------------------------------- |
diff --git a/MAINTAINERS b/MAINTAINERS index 58b9861ccf99..078fd80f664f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -4309,7 +4309,7 @@ F: Documentation/driver-api/dma-buf.rst | |||
| 4309 | T: git git://anongit.freedesktop.org/drm/drm-misc | 4309 | T: git git://anongit.freedesktop.org/drm/drm-misc |
| 4310 | 4310 | ||
| 4311 | DMA GENERIC OFFLOAD ENGINE SUBSYSTEM | 4311 | DMA GENERIC OFFLOAD ENGINE SUBSYSTEM |
| 4312 | M: Vinod Koul <vinod.koul@intel.com> | 4312 | M: Vinod Koul <vkoul@kernel.org> |
| 4313 | L: dmaengine@vger.kernel.org | 4313 | L: dmaengine@vger.kernel.org |
| 4314 | Q: https://patchwork.kernel.org/project/linux-dmaengine/list/ | 4314 | Q: https://patchwork.kernel.org/project/linux-dmaengine/list/ |
| 4315 | S: Maintained | 4315 | S: Maintained |
| @@ -7698,6 +7698,7 @@ KERNEL SELFTEST FRAMEWORK | |||
| 7698 | M: Shuah Khan <shuah@kernel.org> | 7698 | M: Shuah Khan <shuah@kernel.org> |
| 7699 | L: linux-kselftest@vger.kernel.org | 7699 | L: linux-kselftest@vger.kernel.org |
| 7700 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git | 7700 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git |
| 7701 | Q: https://patchwork.kernel.org/project/linux-kselftest/list/ | ||
| 7701 | S: Maintained | 7702 | S: Maintained |
| 7702 | F: tools/testing/selftests/ | 7703 | F: tools/testing/selftests/ |
| 7703 | F: Documentation/dev-tools/kselftest* | 7704 | F: Documentation/dev-tools/kselftest* |
| @@ -12220,7 +12221,7 @@ F: Documentation/s390/vfio-ccw.txt | |||
| 12220 | F: include/uapi/linux/vfio_ccw.h | 12221 | F: include/uapi/linux/vfio_ccw.h |
| 12221 | 12222 | ||
| 12222 | S390 ZCRYPT DRIVER | 12223 | S390 ZCRYPT DRIVER |
| 12223 | M: Harald Freudenberger <freude@de.ibm.com> | 12224 | M: Harald Freudenberger <freude@linux.ibm.com> |
| 12224 | L: linux-s390@vger.kernel.org | 12225 | L: linux-s390@vger.kernel.org |
| 12225 | W: http://www.ibm.com/developerworks/linux/linux390/ | 12226 | W: http://www.ibm.com/developerworks/linux/linux390/ |
| 12226 | S: Supported | 12227 | S: Supported |
| @@ -13264,6 +13265,12 @@ M: Jan-Benedict Glaw <jbglaw@lug-owl.de> | |||
| 13264 | S: Maintained | 13265 | S: Maintained |
| 13265 | F: arch/alpha/kernel/srm_env.c | 13266 | F: arch/alpha/kernel/srm_env.c |
| 13266 | 13267 | ||
| 13268 | ST STM32 I2C/SMBUS DRIVER | ||
| 13269 | M: Pierre-Yves MORDRET <pierre-yves.mordret@st.com> | ||
| 13270 | L: linux-i2c@vger.kernel.org | ||
| 13271 | S: Maintained | ||
| 13272 | F: drivers/i2c/busses/i2c-stm32* | ||
| 13273 | |||
| 13267 | STABLE BRANCH | 13274 | STABLE BRANCH |
| 13268 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 13275 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| 13269 | L: stable@vger.kernel.org | 13276 | L: stable@vger.kernel.org |
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 707a1f06dc5d..f675162663f0 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h | |||
| @@ -309,6 +309,22 @@ static inline unsigned int kvm_get_vmid_bits(void) | |||
| 309 | return 8; | 309 | return 8; |
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | /* | ||
| 313 | * We are not in the kvm->srcu critical section most of the time, so we take | ||
| 314 | * the SRCU read lock here. Since we copy the data from the user page, we | ||
| 315 | * can immediately drop the lock again. | ||
| 316 | */ | ||
| 317 | static inline int kvm_read_guest_lock(struct kvm *kvm, | ||
| 318 | gpa_t gpa, void *data, unsigned long len) | ||
| 319 | { | ||
| 320 | int srcu_idx = srcu_read_lock(&kvm->srcu); | ||
| 321 | int ret = kvm_read_guest(kvm, gpa, data, len); | ||
| 322 | |||
| 323 | srcu_read_unlock(&kvm->srcu, srcu_idx); | ||
| 324 | |||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 312 | static inline void *kvm_get_hyp_vector(void) | 328 | static inline void *kvm_get_hyp_vector(void) |
| 313 | { | 329 | { |
| 314 | return kvm_ksym_ref(__kvm_hyp_vector); | 330 | return kvm_ksym_ref(__kvm_hyp_vector); |
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 082110993647..6128992c2ded 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h | |||
| @@ -360,6 +360,22 @@ static inline unsigned int kvm_get_vmid_bits(void) | |||
| 360 | return (cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR1_VMIDBITS_SHIFT) == 2) ? 16 : 8; | 360 | return (cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR1_VMIDBITS_SHIFT) == 2) ? 16 : 8; |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | /* | ||
| 364 | * We are not in the kvm->srcu critical section most of the time, so we take | ||
| 365 | * the SRCU read lock here. Since we copy the data from the user page, we | ||
| 366 | * can immediately drop the lock again. | ||
| 367 | */ | ||
| 368 | static inline int kvm_read_guest_lock(struct kvm *kvm, | ||
| 369 | gpa_t gpa, void *data, unsigned long len) | ||
| 370 | { | ||
| 371 | int srcu_idx = srcu_read_lock(&kvm->srcu); | ||
| 372 | int ret = kvm_read_guest(kvm, gpa, data, len); | ||
| 373 | |||
| 374 | srcu_read_unlock(&kvm->srcu, srcu_idx); | ||
| 375 | |||
| 376 | return ret; | ||
| 377 | } | ||
| 378 | |||
| 363 | #ifdef CONFIG_KVM_INDIRECT_VECTORS | 379 | #ifdef CONFIG_KVM_INDIRECT_VECTORS |
| 364 | /* | 380 | /* |
| 365 | * EL2 vectors can be mapped and rerouted in a number of ways, | 381 | * EL2 vectors can be mapped and rerouted in a number of ways, |
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c index 1bceb95f422d..5584247f5029 100644 --- a/arch/powerpc/platforms/powernv/opal-nvram.c +++ b/arch/powerpc/platforms/powernv/opal-nvram.c | |||
| @@ -44,6 +44,10 @@ static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index) | |||
| 44 | return count; | 44 | return count; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | /* | ||
| 48 | * This can be called in the panic path with interrupts off, so use | ||
| 49 | * mdelay in that case. | ||
| 50 | */ | ||
| 47 | static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index) | 51 | static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index) |
| 48 | { | 52 | { |
| 49 | s64 rc = OPAL_BUSY; | 53 | s64 rc = OPAL_BUSY; |
| @@ -58,10 +62,16 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index) | |||
| 58 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | 62 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { |
| 59 | rc = opal_write_nvram(__pa(buf), count, off); | 63 | rc = opal_write_nvram(__pa(buf), count, off); |
| 60 | if (rc == OPAL_BUSY_EVENT) { | 64 | if (rc == OPAL_BUSY_EVENT) { |
| 61 | msleep(OPAL_BUSY_DELAY_MS); | 65 | if (in_interrupt() || irqs_disabled()) |
| 66 | mdelay(OPAL_BUSY_DELAY_MS); | ||
| 67 | else | ||
| 68 | msleep(OPAL_BUSY_DELAY_MS); | ||
| 62 | opal_poll_events(NULL); | 69 | opal_poll_events(NULL); |
| 63 | } else if (rc == OPAL_BUSY) { | 70 | } else if (rc == OPAL_BUSY) { |
| 64 | msleep(OPAL_BUSY_DELAY_MS); | 71 | if (in_interrupt() || irqs_disabled()) |
| 72 | mdelay(OPAL_BUSY_DELAY_MS); | ||
| 73 | else | ||
| 74 | msleep(OPAL_BUSY_DELAY_MS); | ||
| 65 | } | 75 | } |
| 66 | } | 76 | } |
| 67 | 77 | ||
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 6176fe9795ca..941d8cc6c9f5 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig | |||
| @@ -261,9 +261,9 @@ CONFIG_IP_VS_NQ=m | |||
| 261 | CONFIG_IP_VS_FTP=m | 261 | CONFIG_IP_VS_FTP=m |
| 262 | CONFIG_IP_VS_PE_SIP=m | 262 | CONFIG_IP_VS_PE_SIP=m |
| 263 | CONFIG_NF_CONNTRACK_IPV4=m | 263 | CONFIG_NF_CONNTRACK_IPV4=m |
| 264 | CONFIG_NF_TABLES_IPV4=m | 264 | CONFIG_NF_TABLES_IPV4=y |
| 265 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | 265 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m |
| 266 | CONFIG_NF_TABLES_ARP=m | 266 | CONFIG_NF_TABLES_ARP=y |
| 267 | CONFIG_NFT_CHAIN_NAT_IPV4=m | 267 | CONFIG_NFT_CHAIN_NAT_IPV4=m |
| 268 | CONFIG_IP_NF_IPTABLES=m | 268 | CONFIG_IP_NF_IPTABLES=m |
| 269 | CONFIG_IP_NF_MATCH_AH=m | 269 | CONFIG_IP_NF_MATCH_AH=m |
| @@ -284,7 +284,7 @@ CONFIG_IP_NF_ARPTABLES=m | |||
| 284 | CONFIG_IP_NF_ARPFILTER=m | 284 | CONFIG_IP_NF_ARPFILTER=m |
| 285 | CONFIG_IP_NF_ARP_MANGLE=m | 285 | CONFIG_IP_NF_ARP_MANGLE=m |
| 286 | CONFIG_NF_CONNTRACK_IPV6=m | 286 | CONFIG_NF_CONNTRACK_IPV6=m |
| 287 | CONFIG_NF_TABLES_IPV6=m | 287 | CONFIG_NF_TABLES_IPV6=y |
| 288 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | 288 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m |
| 289 | CONFIG_NFT_CHAIN_NAT_IPV6=m | 289 | CONFIG_NFT_CHAIN_NAT_IPV6=m |
| 290 | CONFIG_IP6_NF_IPTABLES=m | 290 | CONFIG_IP6_NF_IPTABLES=m |
| @@ -305,7 +305,7 @@ CONFIG_IP6_NF_RAW=m | |||
| 305 | CONFIG_IP6_NF_SECURITY=m | 305 | CONFIG_IP6_NF_SECURITY=m |
| 306 | CONFIG_IP6_NF_NAT=m | 306 | CONFIG_IP6_NF_NAT=m |
| 307 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 307 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
| 308 | CONFIG_NF_TABLES_BRIDGE=m | 308 | CONFIG_NF_TABLES_BRIDGE=y |
| 309 | CONFIG_RDS=m | 309 | CONFIG_RDS=m |
| 310 | CONFIG_RDS_RDMA=m | 310 | CONFIG_RDS_RDMA=m |
| 311 | CONFIG_RDS_TCP=m | 311 | CONFIG_RDS_TCP=m |
| @@ -604,7 +604,6 @@ CONFIG_DETECT_HUNG_TASK=y | |||
| 604 | CONFIG_WQ_WATCHDOG=y | 604 | CONFIG_WQ_WATCHDOG=y |
| 605 | CONFIG_PANIC_ON_OOPS=y | 605 | CONFIG_PANIC_ON_OOPS=y |
| 606 | CONFIG_DEBUG_TIMEKEEPING=y | 606 | CONFIG_DEBUG_TIMEKEEPING=y |
| 607 | CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y | ||
| 608 | CONFIG_PROVE_LOCKING=y | 607 | CONFIG_PROVE_LOCKING=y |
| 609 | CONFIG_LOCK_STAT=y | 608 | CONFIG_LOCK_STAT=y |
| 610 | CONFIG_DEBUG_LOCKDEP=y | 609 | CONFIG_DEBUG_LOCKDEP=y |
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig index c105bcc6d7a6..eb6f75f24208 100644 --- a/arch/s390/configs/performance_defconfig +++ b/arch/s390/configs/performance_defconfig | |||
| @@ -259,9 +259,9 @@ CONFIG_IP_VS_NQ=m | |||
| 259 | CONFIG_IP_VS_FTP=m | 259 | CONFIG_IP_VS_FTP=m |
| 260 | CONFIG_IP_VS_PE_SIP=m | 260 | CONFIG_IP_VS_PE_SIP=m |
| 261 | CONFIG_NF_CONNTRACK_IPV4=m | 261 | CONFIG_NF_CONNTRACK_IPV4=m |
| 262 | CONFIG_NF_TABLES_IPV4=m | 262 | CONFIG_NF_TABLES_IPV4=y |
| 263 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m | 263 | CONFIG_NFT_CHAIN_ROUTE_IPV4=m |
| 264 | CONFIG_NF_TABLES_ARP=m | 264 | CONFIG_NF_TABLES_ARP=y |
| 265 | CONFIG_NFT_CHAIN_NAT_IPV4=m | 265 | CONFIG_NFT_CHAIN_NAT_IPV4=m |
| 266 | CONFIG_IP_NF_IPTABLES=m | 266 | CONFIG_IP_NF_IPTABLES=m |
| 267 | CONFIG_IP_NF_MATCH_AH=m | 267 | CONFIG_IP_NF_MATCH_AH=m |
| @@ -282,7 +282,7 @@ CONFIG_IP_NF_ARPTABLES=m | |||
| 282 | CONFIG_IP_NF_ARPFILTER=m | 282 | CONFIG_IP_NF_ARPFILTER=m |
| 283 | CONFIG_IP_NF_ARP_MANGLE=m | 283 | CONFIG_IP_NF_ARP_MANGLE=m |
| 284 | CONFIG_NF_CONNTRACK_IPV6=m | 284 | CONFIG_NF_CONNTRACK_IPV6=m |
| 285 | CONFIG_NF_TABLES_IPV6=m | 285 | CONFIG_NF_TABLES_IPV6=y |
| 286 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m | 286 | CONFIG_NFT_CHAIN_ROUTE_IPV6=m |
| 287 | CONFIG_NFT_CHAIN_NAT_IPV6=m | 287 | CONFIG_NFT_CHAIN_NAT_IPV6=m |
| 288 | CONFIG_IP6_NF_IPTABLES=m | 288 | CONFIG_IP6_NF_IPTABLES=m |
| @@ -303,7 +303,7 @@ CONFIG_IP6_NF_RAW=m | |||
| 303 | CONFIG_IP6_NF_SECURITY=m | 303 | CONFIG_IP6_NF_SECURITY=m |
| 304 | CONFIG_IP6_NF_NAT=m | 304 | CONFIG_IP6_NF_NAT=m |
| 305 | CONFIG_IP6_NF_TARGET_MASQUERADE=m | 305 | CONFIG_IP6_NF_TARGET_MASQUERADE=m |
| 306 | CONFIG_NF_TABLES_BRIDGE=m | 306 | CONFIG_NF_TABLES_BRIDGE=y |
| 307 | CONFIG_RDS=m | 307 | CONFIG_RDS=m |
| 308 | CONFIG_RDS_RDMA=m | 308 | CONFIG_RDS_RDMA=m |
| 309 | CONFIG_RDS_TCP=m | 309 | CONFIG_RDS_TCP=m |
diff --git a/arch/s390/crypto/crc32be-vx.S b/arch/s390/crypto/crc32be-vx.S index e8077f0971f8..2bf01ba44107 100644 --- a/arch/s390/crypto/crc32be-vx.S +++ b/arch/s390/crypto/crc32be-vx.S | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
| 16 | #include <asm/nospec-insn.h> | ||
| 16 | #include <asm/vx-insn.h> | 17 | #include <asm/vx-insn.h> |
| 17 | 18 | ||
| 18 | /* Vector register range containing CRC-32 constants */ | 19 | /* Vector register range containing CRC-32 constants */ |
| @@ -67,6 +68,8 @@ | |||
| 67 | 68 | ||
| 68 | .previous | 69 | .previous |
| 69 | 70 | ||
| 71 | GEN_BR_THUNK %r14 | ||
| 72 | |||
| 70 | .text | 73 | .text |
| 71 | /* | 74 | /* |
| 72 | * The CRC-32 function(s) use these calling conventions: | 75 | * The CRC-32 function(s) use these calling conventions: |
| @@ -203,6 +206,6 @@ ENTRY(crc32_be_vgfm_16) | |||
| 203 | 206 | ||
| 204 | .Ldone: | 207 | .Ldone: |
| 205 | VLGVF %r2,%v2,3 | 208 | VLGVF %r2,%v2,3 |
| 206 | br %r14 | 209 | BR_EX %r14 |
| 207 | 210 | ||
| 208 | .previous | 211 | .previous |
diff --git a/arch/s390/crypto/crc32le-vx.S b/arch/s390/crypto/crc32le-vx.S index d8c67a58c0c5..7d6f568bd3ad 100644 --- a/arch/s390/crypto/crc32le-vx.S +++ b/arch/s390/crypto/crc32le-vx.S | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
| 17 | #include <asm/nospec-insn.h> | ||
| 17 | #include <asm/vx-insn.h> | 18 | #include <asm/vx-insn.h> |
| 18 | 19 | ||
| 19 | /* Vector register range containing CRC-32 constants */ | 20 | /* Vector register range containing CRC-32 constants */ |
| @@ -76,6 +77,7 @@ | |||
| 76 | 77 | ||
| 77 | .previous | 78 | .previous |
| 78 | 79 | ||
| 80 | GEN_BR_THUNK %r14 | ||
| 79 | 81 | ||
| 80 | .text | 82 | .text |
| 81 | 83 | ||
| @@ -264,6 +266,6 @@ crc32_le_vgfm_generic: | |||
| 264 | 266 | ||
| 265 | .Ldone: | 267 | .Ldone: |
| 266 | VLGVF %r2,%v2,2 | 268 | VLGVF %r2,%v2,2 |
| 267 | br %r14 | 269 | BR_EX %r14 |
| 268 | 270 | ||
| 269 | .previous | 271 | .previous |
diff --git a/arch/s390/include/asm/nospec-insn.h b/arch/s390/include/asm/nospec-insn.h new file mode 100644 index 000000000000..a01f81186e86 --- /dev/null +++ b/arch/s390/include/asm/nospec-insn.h | |||
| @@ -0,0 +1,196 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _ASM_S390_NOSPEC_ASM_H | ||
| 3 | #define _ASM_S390_NOSPEC_ASM_H | ||
| 4 | |||
| 5 | #include <asm/alternative-asm.h> | ||
| 6 | #include <asm/asm-offsets.h> | ||
| 7 | #include <asm/dwarf.h> | ||
| 8 | |||
| 9 | #ifdef __ASSEMBLY__ | ||
| 10 | |||
| 11 | #ifdef CONFIG_EXPOLINE | ||
| 12 | |||
| 13 | _LC_BR_R1 = __LC_BR_R1 | ||
| 14 | |||
| 15 | /* | ||
| 16 | * The expoline macros are used to create thunks in the same format | ||
| 17 | * as gcc generates them. The 'comdat' section flag makes sure that | ||
| 18 | * the various thunks are merged into a single copy. | ||
| 19 | */ | ||
| 20 | .macro __THUNK_PROLOG_NAME name | ||
| 21 | .pushsection .text.\name,"axG",@progbits,\name,comdat | ||
| 22 | .globl \name | ||
| 23 | .hidden \name | ||
| 24 | .type \name,@function | ||
| 25 | \name: | ||
| 26 | CFI_STARTPROC | ||
| 27 | .endm | ||
| 28 | |||
| 29 | .macro __THUNK_EPILOG | ||
| 30 | CFI_ENDPROC | ||
| 31 | .popsection | ||
| 32 | .endm | ||
| 33 | |||
| 34 | .macro __THUNK_PROLOG_BR r1,r2 | ||
| 35 | __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1 | ||
| 36 | .endm | ||
| 37 | |||
| 38 | .macro __THUNK_PROLOG_BC d0,r1,r2 | ||
| 39 | __THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1 | ||
| 40 | .endm | ||
| 41 | |||
| 42 | .macro __THUNK_BR r1,r2 | ||
| 43 | jg __s390x_indirect_jump_r\r2\()use_r\r1 | ||
| 44 | .endm | ||
| 45 | |||
| 46 | .macro __THUNK_BC d0,r1,r2 | ||
| 47 | jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1 | ||
| 48 | .endm | ||
| 49 | |||
| 50 | .macro __THUNK_BRASL r1,r2,r3 | ||
| 51 | brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2 | ||
| 52 | .endm | ||
| 53 | |||
| 54 | .macro __DECODE_RR expand,reg,ruse | ||
| 55 | .set __decode_fail,1 | ||
| 56 | .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | ||
| 57 | .ifc \reg,%r\r1 | ||
| 58 | .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | ||
| 59 | .ifc \ruse,%r\r2 | ||
| 60 | \expand \r1,\r2 | ||
| 61 | .set __decode_fail,0 | ||
| 62 | .endif | ||
| 63 | .endr | ||
| 64 | .endif | ||
| 65 | .endr | ||
| 66 | .if __decode_fail == 1 | ||
| 67 | .error "__DECODE_RR failed" | ||
| 68 | .endif | ||
| 69 | .endm | ||
| 70 | |||
| 71 | .macro __DECODE_RRR expand,rsave,rtarget,ruse | ||
| 72 | .set __decode_fail,1 | ||
| 73 | .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | ||
| 74 | .ifc \rsave,%r\r1 | ||
| 75 | .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | ||
| 76 | .ifc \rtarget,%r\r2 | ||
| 77 | .irp r3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | ||
| 78 | .ifc \ruse,%r\r3 | ||
| 79 | \expand \r1,\r2,\r3 | ||
| 80 | .set __decode_fail,0 | ||
| 81 | .endif | ||
| 82 | .endr | ||
| 83 | .endif | ||
| 84 | .endr | ||
| 85 | .endif | ||
| 86 | .endr | ||
| 87 | .if __decode_fail == 1 | ||
| 88 | .error "__DECODE_RRR failed" | ||
| 89 | .endif | ||
| 90 | .endm | ||
| 91 | |||
| 92 | .macro __DECODE_DRR expand,disp,reg,ruse | ||
| 93 | .set __decode_fail,1 | ||
| 94 | .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | ||
| 95 | .ifc \reg,%r\r1 | ||
| 96 | .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | ||
| 97 | .ifc \ruse,%r\r2 | ||
| 98 | \expand \disp,\r1,\r2 | ||
| 99 | .set __decode_fail,0 | ||
| 100 | .endif | ||
| 101 | .endr | ||
| 102 | .endif | ||
| 103 | .endr | ||
| 104 | .if __decode_fail == 1 | ||
| 105 | .error "__DECODE_DRR failed" | ||
| 106 | .endif | ||
| 107 | .endm | ||
| 108 | |||
| 109 | .macro __THUNK_EX_BR reg,ruse | ||
| 110 | # Be very careful when adding instructions to this macro! | ||
| 111 | # The ALTERNATIVE replacement code has a .+10 which targets | ||
| 112 | # the "br \reg" after the code has been patched. | ||
| 113 | #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES | ||
| 114 | exrl 0,555f | ||
| 115 | j . | ||
| 116 | #else | ||
| 117 | .ifc \reg,%r1 | ||
| 118 | ALTERNATIVE "ex %r0,_LC_BR_R1", ".insn ril,0xc60000000000,0,.+10", 35 | ||
| 119 | j . | ||
| 120 | .else | ||
| 121 | larl \ruse,555f | ||
| 122 | ex 0,0(\ruse) | ||
| 123 | j . | ||
| 124 | .endif | ||
| 125 | #endif | ||
| 126 | 555: br \reg | ||
| 127 | .endm | ||
| 128 | |||
| 129 | .macro __THUNK_EX_BC disp,reg,ruse | ||
| 130 | #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES | ||
| 131 | exrl 0,556f | ||
| 132 | j . | ||
| 133 | #else | ||
| 134 | larl \ruse,556f | ||
| 135 | ex 0,0(\ruse) | ||
| 136 | j . | ||
| 137 | #endif | ||
| 138 | 556: b \disp(\reg) | ||
| 139 | .endm | ||
| 140 | |||
| 141 | .macro GEN_BR_THUNK reg,ruse=%r1 | ||
| 142 | __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse | ||
| 143 | __THUNK_EX_BR \reg,\ruse | ||
| 144 | __THUNK_EPILOG | ||
| 145 | .endm | ||
| 146 | |||
| 147 | .macro GEN_B_THUNK disp,reg,ruse=%r1 | ||
| 148 | __DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse | ||
| 149 | __THUNK_EX_BC \disp,\reg,\ruse | ||
| 150 | __THUNK_EPILOG | ||
| 151 | .endm | ||
| 152 | |||
| 153 | .macro BR_EX reg,ruse=%r1 | ||
| 154 | 557: __DECODE_RR __THUNK_BR,\reg,\ruse | ||
| 155 | .pushsection .s390_indirect_branches,"a",@progbits | ||
| 156 | .long 557b-. | ||
| 157 | .popsection | ||
| 158 | .endm | ||
| 159 | |||
| 160 | .macro B_EX disp,reg,ruse=%r1 | ||
| 161 | 558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse | ||
| 162 | .pushsection .s390_indirect_branches,"a",@progbits | ||
| 163 | .long 558b-. | ||
| 164 | .popsection | ||
| 165 | .endm | ||
| 166 | |||
| 167 | .macro BASR_EX rsave,rtarget,ruse=%r1 | ||
| 168 | 559: __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse | ||
| 169 | .pushsection .s390_indirect_branches,"a",@progbits | ||
| 170 | .long 559b-. | ||
| 171 | .popsection | ||
| 172 | .endm | ||
| 173 | |||
| 174 | #else | ||
| 175 | .macro GEN_BR_THUNK reg,ruse=%r1 | ||
| 176 | .endm | ||
| 177 | |||
| 178 | .macro GEN_B_THUNK disp,reg,ruse=%r1 | ||
| 179 | .endm | ||
| 180 | |||
| 181 | .macro BR_EX reg,ruse=%r1 | ||
| 182 | br \reg | ||
| 183 | .endm | ||
| 184 | |||
| 185 | .macro B_EX disp,reg,ruse=%r1 | ||
| 186 | b \disp(\reg) | ||
| 187 | .endm | ||
| 188 | |||
| 189 | .macro BASR_EX rsave,rtarget,ruse=%r1 | ||
| 190 | basr \rsave,\rtarget | ||
| 191 | .endm | ||
| 192 | #endif | ||
| 193 | |||
| 194 | #endif /* __ASSEMBLY__ */ | ||
| 195 | |||
| 196 | #endif /* _ASM_S390_NOSPEC_ASM_H */ | ||
diff --git a/arch/s390/include/asm/purgatory.h b/arch/s390/include/asm/purgatory.h index e297bcfc476f..6090670df51f 100644 --- a/arch/s390/include/asm/purgatory.h +++ b/arch/s390/include/asm/purgatory.h | |||
| @@ -13,5 +13,11 @@ | |||
| 13 | 13 | ||
| 14 | int verify_sha256_digest(void); | 14 | int verify_sha256_digest(void); |
| 15 | 15 | ||
| 16 | extern u64 kernel_entry; | ||
| 17 | extern u64 kernel_type; | ||
| 18 | |||
| 19 | extern u64 crash_start; | ||
| 20 | extern u64 crash_size; | ||
| 21 | |||
| 16 | #endif /* __ASSEMBLY__ */ | 22 | #endif /* __ASSEMBLY__ */ |
| 17 | #endif /* _S390_PURGATORY_H_ */ | 23 | #endif /* _S390_PURGATORY_H_ */ |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 84ea6225efb4..f92dd8ed3884 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
| @@ -65,6 +65,7 @@ obj-y += nospec-branch.o | |||
| 65 | 65 | ||
| 66 | extra-y += head.o head64.o vmlinux.lds | 66 | extra-y += head.o head64.o vmlinux.lds |
| 67 | 67 | ||
| 68 | obj-$(CONFIG_SYSFS) += nospec-sysfs.o | ||
| 68 | CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE) | 69 | CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE) |
| 69 | 70 | ||
| 70 | obj-$(CONFIG_MODULES) += module.o | 71 | obj-$(CONFIG_MODULES) += module.o |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index eb2a5c0443cd..11aea745a2a6 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
| @@ -181,6 +181,7 @@ int main(void) | |||
| 181 | OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags); | 181 | OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags); |
| 182 | OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count); | 182 | OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count); |
| 183 | OFFSET(__LC_GMAP, lowcore, gmap); | 183 | OFFSET(__LC_GMAP, lowcore, gmap); |
| 184 | OFFSET(__LC_BR_R1, lowcore, br_r1_trampoline); | ||
| 184 | /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ | 185 | /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ |
| 185 | OFFSET(__LC_DUMP_REIPL, lowcore, ipib); | 186 | OFFSET(__LC_DUMP_REIPL, lowcore, ipib); |
| 186 | /* hardware defined lowcore locations 0x1000 - 0x18ff */ | 187 | /* hardware defined lowcore locations 0x1000 - 0x18ff */ |
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S index f6c56009e822..b65874b0b412 100644 --- a/arch/s390/kernel/base.S +++ b/arch/s390/kernel/base.S | |||
| @@ -9,18 +9,22 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/linkage.h> | 10 | #include <linux/linkage.h> |
| 11 | #include <asm/asm-offsets.h> | 11 | #include <asm/asm-offsets.h> |
| 12 | #include <asm/nospec-insn.h> | ||
| 12 | #include <asm/ptrace.h> | 13 | #include <asm/ptrace.h> |
| 13 | #include <asm/sigp.h> | 14 | #include <asm/sigp.h> |
| 14 | 15 | ||
| 16 | GEN_BR_THUNK %r9 | ||
| 17 | GEN_BR_THUNK %r14 | ||
| 18 | |||
| 15 | ENTRY(s390_base_mcck_handler) | 19 | ENTRY(s390_base_mcck_handler) |
| 16 | basr %r13,0 | 20 | basr %r13,0 |
| 17 | 0: lg %r15,__LC_PANIC_STACK # load panic stack | 21 | 0: lg %r15,__LC_PANIC_STACK # load panic stack |
| 18 | aghi %r15,-STACK_FRAME_OVERHEAD | 22 | aghi %r15,-STACK_FRAME_OVERHEAD |
| 19 | larl %r1,s390_base_mcck_handler_fn | 23 | larl %r1,s390_base_mcck_handler_fn |
| 20 | lg %r1,0(%r1) | 24 | lg %r9,0(%r1) |
| 21 | ltgr %r1,%r1 | 25 | ltgr %r9,%r9 |
| 22 | jz 1f | 26 | jz 1f |
| 23 | basr %r14,%r1 | 27 | BASR_EX %r14,%r9 |
| 24 | 1: la %r1,4095 | 28 | 1: la %r1,4095 |
| 25 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) | 29 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) |
| 26 | lpswe __LC_MCK_OLD_PSW | 30 | lpswe __LC_MCK_OLD_PSW |
| @@ -37,10 +41,10 @@ ENTRY(s390_base_ext_handler) | |||
| 37 | basr %r13,0 | 41 | basr %r13,0 |
| 38 | 0: aghi %r15,-STACK_FRAME_OVERHEAD | 42 | 0: aghi %r15,-STACK_FRAME_OVERHEAD |
| 39 | larl %r1,s390_base_ext_handler_fn | 43 | larl %r1,s390_base_ext_handler_fn |
| 40 | lg %r1,0(%r1) | 44 | lg %r9,0(%r1) |
| 41 | ltgr %r1,%r1 | 45 | ltgr %r9,%r9 |
| 42 | jz 1f | 46 | jz 1f |
| 43 | basr %r14,%r1 | 47 | BASR_EX %r14,%r9 |
| 44 | 1: lmg %r0,%r15,__LC_SAVE_AREA_ASYNC | 48 | 1: lmg %r0,%r15,__LC_SAVE_AREA_ASYNC |
| 45 | ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit | 49 | ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit |
| 46 | lpswe __LC_EXT_OLD_PSW | 50 | lpswe __LC_EXT_OLD_PSW |
| @@ -57,10 +61,10 @@ ENTRY(s390_base_pgm_handler) | |||
| 57 | basr %r13,0 | 61 | basr %r13,0 |
| 58 | 0: aghi %r15,-STACK_FRAME_OVERHEAD | 62 | 0: aghi %r15,-STACK_FRAME_OVERHEAD |
| 59 | larl %r1,s390_base_pgm_handler_fn | 63 | larl %r1,s390_base_pgm_handler_fn |
| 60 | lg %r1,0(%r1) | 64 | lg %r9,0(%r1) |
| 61 | ltgr %r1,%r1 | 65 | ltgr %r9,%r9 |
| 62 | jz 1f | 66 | jz 1f |
| 63 | basr %r14,%r1 | 67 | BASR_EX %r14,%r9 |
| 64 | lmg %r0,%r15,__LC_SAVE_AREA_SYNC | 68 | lmg %r0,%r15,__LC_SAVE_AREA_SYNC |
| 65 | lpswe __LC_PGM_OLD_PSW | 69 | lpswe __LC_PGM_OLD_PSW |
| 66 | 1: lpswe disabled_wait_psw-0b(%r13) | 70 | 1: lpswe disabled_wait_psw-0b(%r13) |
| @@ -117,7 +121,7 @@ ENTRY(diag308_reset) | |||
| 117 | larl %r4,.Lcontinue_psw # Restore PSW flags | 121 | larl %r4,.Lcontinue_psw # Restore PSW flags |
| 118 | lpswe 0(%r4) | 122 | lpswe 0(%r4) |
| 119 | .Lcontinue: | 123 | .Lcontinue: |
| 120 | br %r14 | 124 | BR_EX %r14 |
| 121 | .align 16 | 125 | .align 16 |
| 122 | .Lrestart_psw: | 126 | .Lrestart_psw: |
| 123 | .long 0x00080000,0x80000000 + .Lrestart_part2 | 127 | .long 0x00080000,0x80000000 + .Lrestart_part2 |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 3f22f139a041..f03402efab4b 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <asm/setup.h> | 28 | #include <asm/setup.h> |
| 29 | #include <asm/nmi.h> | 29 | #include <asm/nmi.h> |
| 30 | #include <asm/export.h> | 30 | #include <asm/export.h> |
| 31 | #include <asm/nospec-insn.h> | ||
| 31 | 32 | ||
| 32 | __PT_R0 = __PT_GPRS | 33 | __PT_R0 = __PT_GPRS |
| 33 | __PT_R1 = __PT_GPRS + 8 | 34 | __PT_R1 = __PT_GPRS + 8 |
| @@ -183,67 +184,9 @@ _LPP_OFFSET = __LC_LPP | |||
| 183 | "jnz .+8; .long 0xb2e8d000", 82 | 184 | "jnz .+8; .long 0xb2e8d000", 82 |
| 184 | .endm | 185 | .endm |
| 185 | 186 | ||
| 186 | #ifdef CONFIG_EXPOLINE | 187 | GEN_BR_THUNK %r9 |
| 187 | 188 | GEN_BR_THUNK %r14 | |
| 188 | .macro GEN_BR_THUNK name,reg,tmp | 189 | GEN_BR_THUNK %r14,%r11 |
| 189 | .section .text.\name,"axG",@progbits,\name,comdat | ||
| 190 | .globl \name | ||
| 191 | .hidden \name | ||
| 192 | .type \name,@function | ||
| 193 | \name: | ||
| 194 | CFI_STARTPROC | ||
| 195 | #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES | ||
| 196 | exrl 0,0f | ||
| 197 | #else | ||
| 198 | larl \tmp,0f | ||
| 199 | ex 0,0(\tmp) | ||
| 200 | #endif | ||
| 201 | j . | ||
| 202 | 0: br \reg | ||
| 203 | CFI_ENDPROC | ||
| 204 | .endm | ||
| 205 | |||
| 206 | GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1 | ||
| 207 | GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1 | ||
| 208 | GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11 | ||
| 209 | |||
| 210 | .macro BASR_R14_R9 | ||
| 211 | 0: brasl %r14,__s390x_indirect_jump_r1use_r9 | ||
| 212 | .pushsection .s390_indirect_branches,"a",@progbits | ||
| 213 | .long 0b-. | ||
| 214 | .popsection | ||
| 215 | .endm | ||
| 216 | |||
| 217 | .macro BR_R1USE_R14 | ||
| 218 | 0: jg __s390x_indirect_jump_r1use_r14 | ||
| 219 | .pushsection .s390_indirect_branches,"a",@progbits | ||
| 220 | .long 0b-. | ||
| 221 | .popsection | ||
| 222 | .endm | ||
| 223 | |||
| 224 | .macro BR_R11USE_R14 | ||
| 225 | 0: jg __s390x_indirect_jump_r11use_r14 | ||
| 226 | .pushsection .s390_indirect_branches,"a",@progbits | ||
| 227 | .long 0b-. | ||
| 228 | .popsection | ||
| 229 | .endm | ||
| 230 | |||
| 231 | #else /* CONFIG_EXPOLINE */ | ||
| 232 | |||
| 233 | .macro BASR_R14_R9 | ||
| 234 | basr %r14,%r9 | ||
| 235 | .endm | ||
| 236 | |||
| 237 | .macro BR_R1USE_R14 | ||
| 238 | br %r14 | ||
| 239 | .endm | ||
| 240 | |||
| 241 | .macro BR_R11USE_R14 | ||
| 242 | br %r14 | ||
| 243 | .endm | ||
| 244 | |||
| 245 | #endif /* CONFIG_EXPOLINE */ | ||
| 246 | |||
| 247 | 190 | ||
| 248 | .section .kprobes.text, "ax" | 191 | .section .kprobes.text, "ax" |
| 249 | .Ldummy: | 192 | .Ldummy: |
| @@ -260,7 +203,7 @@ _LPP_OFFSET = __LC_LPP | |||
| 260 | ENTRY(__bpon) | 203 | ENTRY(__bpon) |
| 261 | .globl __bpon | 204 | .globl __bpon |
| 262 | BPON | 205 | BPON |
| 263 | BR_R1USE_R14 | 206 | BR_EX %r14 |
| 264 | 207 | ||
| 265 | /* | 208 | /* |
| 266 | * Scheduler resume function, called by switch_to | 209 | * Scheduler resume function, called by switch_to |
| @@ -284,7 +227,7 @@ ENTRY(__switch_to) | |||
| 284 | mvc __LC_CURRENT_PID(4,%r0),0(%r3) # store pid of next | 227 | mvc __LC_CURRENT_PID(4,%r0),0(%r3) # store pid of next |
| 285 | lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task | 228 | lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task |
| 286 | ALTERNATIVE "", ".insn s,0xb2800000,_LPP_OFFSET", 40 | 229 | ALTERNATIVE "", ".insn s,0xb2800000,_LPP_OFFSET", 40 |
| 287 | BR_R1USE_R14 | 230 | BR_EX %r14 |
| 288 | 231 | ||
| 289 | .L__critical_start: | 232 | .L__critical_start: |
| 290 | 233 | ||
| @@ -351,7 +294,7 @@ sie_exit: | |||
| 351 | xgr %r5,%r5 | 294 | xgr %r5,%r5 |
| 352 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers | 295 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers |
| 353 | lg %r2,__SF_SIE_REASON(%r15) # return exit reason code | 296 | lg %r2,__SF_SIE_REASON(%r15) # return exit reason code |
| 354 | BR_R1USE_R14 | 297 | BR_EX %r14 |
| 355 | .Lsie_fault: | 298 | .Lsie_fault: |
| 356 | lghi %r14,-EFAULT | 299 | lghi %r14,-EFAULT |
| 357 | stg %r14,__SF_SIE_REASON(%r15) # set exit reason code | 300 | stg %r14,__SF_SIE_REASON(%r15) # set exit reason code |
| @@ -410,7 +353,7 @@ ENTRY(system_call) | |||
| 410 | lgf %r9,0(%r8,%r10) # get system call add. | 353 | lgf %r9,0(%r8,%r10) # get system call add. |
| 411 | TSTMSK __TI_flags(%r12),_TIF_TRACE | 354 | TSTMSK __TI_flags(%r12),_TIF_TRACE |
| 412 | jnz .Lsysc_tracesys | 355 | jnz .Lsysc_tracesys |
| 413 | BASR_R14_R9 # call sys_xxxx | 356 | BASR_EX %r14,%r9 # call sys_xxxx |
| 414 | stg %r2,__PT_R2(%r11) # store return value | 357 | stg %r2,__PT_R2(%r11) # store return value |
| 415 | 358 | ||
| 416 | .Lsysc_return: | 359 | .Lsysc_return: |
| @@ -595,7 +538,7 @@ ENTRY(system_call) | |||
| 595 | lmg %r3,%r7,__PT_R3(%r11) | 538 | lmg %r3,%r7,__PT_R3(%r11) |
| 596 | stg %r7,STACK_FRAME_OVERHEAD(%r15) | 539 | stg %r7,STACK_FRAME_OVERHEAD(%r15) |
| 597 | lg %r2,__PT_ORIG_GPR2(%r11) | 540 | lg %r2,__PT_ORIG_GPR2(%r11) |
| 598 | BASR_R14_R9 # call sys_xxx | 541 | BASR_EX %r14,%r9 # call sys_xxx |
| 599 | stg %r2,__PT_R2(%r11) # store return value | 542 | stg %r2,__PT_R2(%r11) # store return value |
| 600 | .Lsysc_tracenogo: | 543 | .Lsysc_tracenogo: |
| 601 | TSTMSK __TI_flags(%r12),_TIF_TRACE | 544 | TSTMSK __TI_flags(%r12),_TIF_TRACE |
| @@ -619,7 +562,7 @@ ENTRY(ret_from_fork) | |||
| 619 | lmg %r9,%r10,__PT_R9(%r11) # load gprs | 562 | lmg %r9,%r10,__PT_R9(%r11) # load gprs |
| 620 | ENTRY(kernel_thread_starter) | 563 | ENTRY(kernel_thread_starter) |
| 621 | la %r2,0(%r10) | 564 | la %r2,0(%r10) |
| 622 | BASR_R14_R9 | 565 | BASR_EX %r14,%r9 |
| 623 | j .Lsysc_tracenogo | 566 | j .Lsysc_tracenogo |
| 624 | 567 | ||
| 625 | /* | 568 | /* |
| @@ -701,7 +644,7 @@ ENTRY(pgm_check_handler) | |||
| 701 | je .Lpgm_return | 644 | je .Lpgm_return |
| 702 | lgf %r9,0(%r10,%r1) # load address of handler routine | 645 | lgf %r9,0(%r10,%r1) # load address of handler routine |
| 703 | lgr %r2,%r11 # pass pointer to pt_regs | 646 | lgr %r2,%r11 # pass pointer to pt_regs |
| 704 | BASR_R14_R9 # branch to interrupt-handler | 647 | BASR_EX %r14,%r9 # branch to interrupt-handler |
| 705 | .Lpgm_return: | 648 | .Lpgm_return: |
| 706 | LOCKDEP_SYS_EXIT | 649 | LOCKDEP_SYS_EXIT |
| 707 | tm __PT_PSW+1(%r11),0x01 # returning to user ? | 650 | tm __PT_PSW+1(%r11),0x01 # returning to user ? |
| @@ -1019,7 +962,7 @@ ENTRY(psw_idle) | |||
| 1019 | stpt __TIMER_IDLE_ENTER(%r2) | 962 | stpt __TIMER_IDLE_ENTER(%r2) |
| 1020 | .Lpsw_idle_lpsw: | 963 | .Lpsw_idle_lpsw: |
| 1021 | lpswe __SF_EMPTY(%r15) | 964 | lpswe __SF_EMPTY(%r15) |
| 1022 | BR_R1USE_R14 | 965 | BR_EX %r14 |
| 1023 | .Lpsw_idle_end: | 966 | .Lpsw_idle_end: |
| 1024 | 967 | ||
| 1025 | /* | 968 | /* |
| @@ -1061,7 +1004,7 @@ ENTRY(save_fpu_regs) | |||
| 1061 | .Lsave_fpu_regs_done: | 1004 | .Lsave_fpu_regs_done: |
| 1062 | oi __LC_CPU_FLAGS+7,_CIF_FPU | 1005 | oi __LC_CPU_FLAGS+7,_CIF_FPU |
| 1063 | .Lsave_fpu_regs_exit: | 1006 | .Lsave_fpu_regs_exit: |
| 1064 | BR_R1USE_R14 | 1007 | BR_EX %r14 |
| 1065 | .Lsave_fpu_regs_end: | 1008 | .Lsave_fpu_regs_end: |
| 1066 | EXPORT_SYMBOL(save_fpu_regs) | 1009 | EXPORT_SYMBOL(save_fpu_regs) |
| 1067 | 1010 | ||
| @@ -1107,7 +1050,7 @@ load_fpu_regs: | |||
| 1107 | .Lload_fpu_regs_done: | 1050 | .Lload_fpu_regs_done: |
| 1108 | ni __LC_CPU_FLAGS+7,255-_CIF_FPU | 1051 | ni __LC_CPU_FLAGS+7,255-_CIF_FPU |
| 1109 | .Lload_fpu_regs_exit: | 1052 | .Lload_fpu_regs_exit: |
| 1110 | BR_R1USE_R14 | 1053 | BR_EX %r14 |
| 1111 | .Lload_fpu_regs_end: | 1054 | .Lload_fpu_regs_end: |
| 1112 | 1055 | ||
| 1113 | .L__critical_end: | 1056 | .L__critical_end: |
| @@ -1322,7 +1265,7 @@ cleanup_critical: | |||
| 1322 | jl 0f | 1265 | jl 0f |
| 1323 | clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end | 1266 | clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end |
| 1324 | jl .Lcleanup_load_fpu_regs | 1267 | jl .Lcleanup_load_fpu_regs |
| 1325 | 0: BR_R11USE_R14 | 1268 | 0: BR_EX %r14 |
| 1326 | 1269 | ||
| 1327 | .align 8 | 1270 | .align 8 |
| 1328 | .Lcleanup_table: | 1271 | .Lcleanup_table: |
| @@ -1358,7 +1301,7 @@ cleanup_critical: | |||
| 1358 | ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE | 1301 | ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE |
| 1359 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 1302 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
| 1360 | larl %r9,sie_exit # skip forward to sie_exit | 1303 | larl %r9,sie_exit # skip forward to sie_exit |
| 1361 | BR_R11USE_R14 | 1304 | BR_EX %r14 |
| 1362 | #endif | 1305 | #endif |
| 1363 | 1306 | ||
| 1364 | .Lcleanup_system_call: | 1307 | .Lcleanup_system_call: |
| @@ -1412,7 +1355,7 @@ cleanup_critical: | |||
| 1412 | stg %r15,56(%r11) # r15 stack pointer | 1355 | stg %r15,56(%r11) # r15 stack pointer |
| 1413 | # set new psw address and exit | 1356 | # set new psw address and exit |
| 1414 | larl %r9,.Lsysc_do_svc | 1357 | larl %r9,.Lsysc_do_svc |
| 1415 | BR_R11USE_R14 | 1358 | BR_EX %r14,%r11 |
| 1416 | .Lcleanup_system_call_insn: | 1359 | .Lcleanup_system_call_insn: |
| 1417 | .quad system_call | 1360 | .quad system_call |
| 1418 | .quad .Lsysc_stmg | 1361 | .quad .Lsysc_stmg |
| @@ -1424,7 +1367,7 @@ cleanup_critical: | |||
| 1424 | 1367 | ||
| 1425 | .Lcleanup_sysc_tif: | 1368 | .Lcleanup_sysc_tif: |
| 1426 | larl %r9,.Lsysc_tif | 1369 | larl %r9,.Lsysc_tif |
| 1427 | BR_R11USE_R14 | 1370 | BR_EX %r14,%r11 |
| 1428 | 1371 | ||
| 1429 | .Lcleanup_sysc_restore: | 1372 | .Lcleanup_sysc_restore: |
| 1430 | # check if stpt has been executed | 1373 | # check if stpt has been executed |
| @@ -1441,14 +1384,14 @@ cleanup_critical: | |||
| 1441 | mvc 0(64,%r11),__PT_R8(%r9) | 1384 | mvc 0(64,%r11),__PT_R8(%r9) |
| 1442 | lmg %r0,%r7,__PT_R0(%r9) | 1385 | lmg %r0,%r7,__PT_R0(%r9) |
| 1443 | 1: lmg %r8,%r9,__LC_RETURN_PSW | 1386 | 1: lmg %r8,%r9,__LC_RETURN_PSW |
| 1444 | BR_R11USE_R14 | 1387 | BR_EX %r14,%r11 |
| 1445 | .Lcleanup_sysc_restore_insn: | 1388 | .Lcleanup_sysc_restore_insn: |
| 1446 | .quad .Lsysc_exit_timer | 1389 | .quad .Lsysc_exit_timer |
| 1447 | .quad .Lsysc_done - 4 | 1390 | .quad .Lsysc_done - 4 |
| 1448 | 1391 | ||
| 1449 | .Lcleanup_io_tif: | 1392 | .Lcleanup_io_tif: |
| 1450 | larl %r9,.Lio_tif | 1393 | larl %r9,.Lio_tif |
| 1451 | BR_R11USE_R14 | 1394 | BR_EX %r14,%r11 |
| 1452 | 1395 | ||
| 1453 | .Lcleanup_io_restore: | 1396 | .Lcleanup_io_restore: |
| 1454 | # check if stpt has been executed | 1397 | # check if stpt has been executed |
| @@ -1462,7 +1405,7 @@ cleanup_critical: | |||
| 1462 | mvc 0(64,%r11),__PT_R8(%r9) | 1405 | mvc 0(64,%r11),__PT_R8(%r9) |
| 1463 | lmg %r0,%r7,__PT_R0(%r9) | 1406 | lmg %r0,%r7,__PT_R0(%r9) |
| 1464 | 1: lmg %r8,%r9,__LC_RETURN_PSW | 1407 | 1: lmg %r8,%r9,__LC_RETURN_PSW |
| 1465 | BR_R11USE_R14 | 1408 | BR_EX %r14,%r11 |
| 1466 | .Lcleanup_io_restore_insn: | 1409 | .Lcleanup_io_restore_insn: |
| 1467 | .quad .Lio_exit_timer | 1410 | .quad .Lio_exit_timer |
| 1468 | .quad .Lio_done - 4 | 1411 | .quad .Lio_done - 4 |
| @@ -1515,17 +1458,17 @@ cleanup_critical: | |||
| 1515 | # prepare return psw | 1458 | # prepare return psw |
| 1516 | nihh %r8,0xfcfd # clear irq & wait state bits | 1459 | nihh %r8,0xfcfd # clear irq & wait state bits |
| 1517 | lg %r9,48(%r11) # return from psw_idle | 1460 | lg %r9,48(%r11) # return from psw_idle |
| 1518 | BR_R11USE_R14 | 1461 | BR_EX %r14,%r11 |
| 1519 | .Lcleanup_idle_insn: | 1462 | .Lcleanup_idle_insn: |
| 1520 | .quad .Lpsw_idle_lpsw | 1463 | .quad .Lpsw_idle_lpsw |
| 1521 | 1464 | ||
| 1522 | .Lcleanup_save_fpu_regs: | 1465 | .Lcleanup_save_fpu_regs: |
| 1523 | larl %r9,save_fpu_regs | 1466 | larl %r9,save_fpu_regs |
| 1524 | BR_R11USE_R14 | 1467 | BR_EX %r14,%r11 |
| 1525 | 1468 | ||
| 1526 | .Lcleanup_load_fpu_regs: | 1469 | .Lcleanup_load_fpu_regs: |
| 1527 | larl %r9,load_fpu_regs | 1470 | larl %r9,load_fpu_regs |
| 1528 | BR_R11USE_R14 | 1471 | BR_EX %r14,%r11 |
| 1529 | 1472 | ||
| 1530 | /* | 1473 | /* |
| 1531 | * Integer constants | 1474 | * Integer constants |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 94f2099bceb0..3d17c41074ca 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
| @@ -176,10 +176,9 @@ void do_softirq_own_stack(void) | |||
| 176 | new -= STACK_FRAME_OVERHEAD; | 176 | new -= STACK_FRAME_OVERHEAD; |
| 177 | ((struct stack_frame *) new)->back_chain = old; | 177 | ((struct stack_frame *) new)->back_chain = old; |
| 178 | asm volatile(" la 15,0(%0)\n" | 178 | asm volatile(" la 15,0(%0)\n" |
| 179 | " basr 14,%2\n" | 179 | " brasl 14,__do_softirq\n" |
| 180 | " la 15,0(%1)\n" | 180 | " la 15,0(%1)\n" |
| 181 | : : "a" (new), "a" (old), | 181 | : : "a" (new), "a" (old) |
| 182 | "a" (__do_softirq) | ||
| 183 | : "0", "1", "2", "3", "4", "5", "14", | 182 | : "0", "1", "2", "3", "4", "5", "14", |
| 184 | "cc", "memory" ); | 183 | "cc", "memory" ); |
| 185 | } else { | 184 | } else { |
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index 82df7d80fab2..27110f3294ed 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S | |||
| @@ -9,13 +9,17 @@ | |||
| 9 | #include <linux/linkage.h> | 9 | #include <linux/linkage.h> |
| 10 | #include <asm/asm-offsets.h> | 10 | #include <asm/asm-offsets.h> |
| 11 | #include <asm/ftrace.h> | 11 | #include <asm/ftrace.h> |
| 12 | #include <asm/nospec-insn.h> | ||
| 12 | #include <asm/ptrace.h> | 13 | #include <asm/ptrace.h> |
| 13 | #include <asm/export.h> | 14 | #include <asm/export.h> |
| 14 | 15 | ||
| 16 | GEN_BR_THUNK %r1 | ||
| 17 | GEN_BR_THUNK %r14 | ||
| 18 | |||
| 15 | .section .kprobes.text, "ax" | 19 | .section .kprobes.text, "ax" |
| 16 | 20 | ||
| 17 | ENTRY(ftrace_stub) | 21 | ENTRY(ftrace_stub) |
| 18 | br %r14 | 22 | BR_EX %r14 |
| 19 | 23 | ||
| 20 | #define STACK_FRAME_SIZE (STACK_FRAME_OVERHEAD + __PT_SIZE) | 24 | #define STACK_FRAME_SIZE (STACK_FRAME_OVERHEAD + __PT_SIZE) |
| 21 | #define STACK_PTREGS (STACK_FRAME_OVERHEAD) | 25 | #define STACK_PTREGS (STACK_FRAME_OVERHEAD) |
| @@ -23,7 +27,7 @@ ENTRY(ftrace_stub) | |||
| 23 | #define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW) | 27 | #define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW) |
| 24 | 28 | ||
| 25 | ENTRY(_mcount) | 29 | ENTRY(_mcount) |
| 26 | br %r14 | 30 | BR_EX %r14 |
| 27 | 31 | ||
| 28 | EXPORT_SYMBOL(_mcount) | 32 | EXPORT_SYMBOL(_mcount) |
| 29 | 33 | ||
| @@ -53,7 +57,7 @@ ENTRY(ftrace_caller) | |||
| 53 | #endif | 57 | #endif |
| 54 | lgr %r3,%r14 | 58 | lgr %r3,%r14 |
| 55 | la %r5,STACK_PTREGS(%r15) | 59 | la %r5,STACK_PTREGS(%r15) |
| 56 | basr %r14,%r1 | 60 | BASR_EX %r14,%r1 |
| 57 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 61 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 58 | # The j instruction gets runtime patched to a nop instruction. | 62 | # The j instruction gets runtime patched to a nop instruction. |
| 59 | # See ftrace_enable_ftrace_graph_caller. | 63 | # See ftrace_enable_ftrace_graph_caller. |
| @@ -68,7 +72,7 @@ ftrace_graph_caller_end: | |||
| 68 | #endif | 72 | #endif |
| 69 | lg %r1,(STACK_PTREGS_PSW+8)(%r15) | 73 | lg %r1,(STACK_PTREGS_PSW+8)(%r15) |
| 70 | lmg %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15) | 74 | lmg %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15) |
| 71 | br %r1 | 75 | BR_EX %r1 |
| 72 | 76 | ||
| 73 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 77 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 74 | 78 | ||
| @@ -81,6 +85,6 @@ ENTRY(return_to_handler) | |||
| 81 | aghi %r15,STACK_FRAME_OVERHEAD | 85 | aghi %r15,STACK_FRAME_OVERHEAD |
| 82 | lgr %r14,%r2 | 86 | lgr %r14,%r2 |
| 83 | lmg %r2,%r5,32(%r15) | 87 | lmg %r2,%r5,32(%r15) |
| 84 | br %r14 | 88 | BR_EX %r14 |
| 85 | 89 | ||
| 86 | #endif | 90 | #endif |
diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c index 46d49a11663f..8ad6a7128b3a 100644 --- a/arch/s390/kernel/nospec-branch.c +++ b/arch/s390/kernel/nospec-branch.c | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/device.h> | 3 | #include <linux/device.h> |
| 4 | #include <linux/cpu.h> | ||
| 5 | #include <asm/nospec-branch.h> | 4 | #include <asm/nospec-branch.h> |
| 6 | 5 | ||
| 7 | static int __init nobp_setup_early(char *str) | 6 | static int __init nobp_setup_early(char *str) |
| @@ -44,24 +43,6 @@ static int __init nospec_report(void) | |||
| 44 | } | 43 | } |
| 45 | arch_initcall(nospec_report); | 44 | arch_initcall(nospec_report); |
| 46 | 45 | ||
| 47 | #ifdef CONFIG_SYSFS | ||
| 48 | ssize_t cpu_show_spectre_v1(struct device *dev, | ||
| 49 | struct device_attribute *attr, char *buf) | ||
| 50 | { | ||
| 51 | return sprintf(buf, "Mitigation: __user pointer sanitization\n"); | ||
| 52 | } | ||
| 53 | |||
| 54 | ssize_t cpu_show_spectre_v2(struct device *dev, | ||
| 55 | struct device_attribute *attr, char *buf) | ||
| 56 | { | ||
| 57 | if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) | ||
| 58 | return sprintf(buf, "Mitigation: execute trampolines\n"); | ||
| 59 | if (__test_facility(82, S390_lowcore.alt_stfle_fac_list)) | ||
| 60 | return sprintf(buf, "Mitigation: limited branch prediction.\n"); | ||
| 61 | return sprintf(buf, "Vulnerable\n"); | ||
| 62 | } | ||
| 63 | #endif | ||
| 64 | |||
| 65 | #ifdef CONFIG_EXPOLINE | 46 | #ifdef CONFIG_EXPOLINE |
| 66 | 47 | ||
| 67 | int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF); | 48 | int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF); |
| @@ -112,7 +93,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end) | |||
| 112 | s32 *epo; | 93 | s32 *epo; |
| 113 | 94 | ||
| 114 | /* Second part of the instruction replace is always a nop */ | 95 | /* Second part of the instruction replace is always a nop */ |
| 115 | memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4); | ||
| 116 | for (epo = start; epo < end; epo++) { | 96 | for (epo = start; epo < end; epo++) { |
| 117 | instr = (u8 *) epo + *epo; | 97 | instr = (u8 *) epo + *epo; |
| 118 | if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04) | 98 | if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04) |
| @@ -133,18 +113,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end) | |||
| 133 | br = thunk + (*(int *)(thunk + 2)) * 2; | 113 | br = thunk + (*(int *)(thunk + 2)) * 2; |
| 134 | else | 114 | else |
| 135 | continue; | 115 | continue; |
| 136 | if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0) | 116 | /* Check for unconditional branch 0x07f? or 0x47f???? */ |
| 117 | if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0) | ||
| 137 | continue; | 118 | continue; |
| 119 | |||
| 120 | memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4); | ||
| 138 | switch (type) { | 121 | switch (type) { |
| 139 | case BRCL_EXPOLINE: | 122 | case BRCL_EXPOLINE: |
| 140 | /* brcl to thunk, replace with br + nop */ | ||
| 141 | insnbuf[0] = br[0]; | 123 | insnbuf[0] = br[0]; |
| 142 | insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); | 124 | insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); |
| 125 | if (br[0] == 0x47) { | ||
| 126 | /* brcl to b, replace with bc + nopr */ | ||
| 127 | insnbuf[2] = br[2]; | ||
| 128 | insnbuf[3] = br[3]; | ||
| 129 | } else { | ||
| 130 | /* brcl to br, replace with bcr + nop */ | ||
| 131 | } | ||
| 143 | break; | 132 | break; |
| 144 | case BRASL_EXPOLINE: | 133 | case BRASL_EXPOLINE: |
| 145 | /* brasl to thunk, replace with basr + nop */ | ||
| 146 | insnbuf[0] = 0x0d; | ||
| 147 | insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); | 134 | insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); |
| 135 | if (br[0] == 0x47) { | ||
| 136 | /* brasl to b, replace with bas + nopr */ | ||
| 137 | insnbuf[0] = 0x4d; | ||
| 138 | insnbuf[2] = br[2]; | ||
| 139 | insnbuf[3] = br[3]; | ||
| 140 | } else { | ||
| 141 | /* brasl to br, replace with basr + nop */ | ||
| 142 | insnbuf[0] = 0x0d; | ||
| 143 | } | ||
| 148 | break; | 144 | break; |
| 149 | } | 145 | } |
| 150 | 146 | ||
diff --git a/arch/s390/kernel/nospec-sysfs.c b/arch/s390/kernel/nospec-sysfs.c new file mode 100644 index 000000000000..8affad5f18cb --- /dev/null +++ b/arch/s390/kernel/nospec-sysfs.c | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | #include <linux/device.h> | ||
| 3 | #include <linux/cpu.h> | ||
| 4 | #include <asm/facility.h> | ||
| 5 | #include <asm/nospec-branch.h> | ||
| 6 | |||
| 7 | ssize_t cpu_show_spectre_v1(struct device *dev, | ||
| 8 | struct device_attribute *attr, char *buf) | ||
| 9 | { | ||
| 10 | return sprintf(buf, "Mitigation: __user pointer sanitization\n"); | ||
| 11 | } | ||
| 12 | |||
| 13 | ssize_t cpu_show_spectre_v2(struct device *dev, | ||
| 14 | struct device_attribute *attr, char *buf) | ||
| 15 | { | ||
| 16 | if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) | ||
| 17 | return sprintf(buf, "Mitigation: execute trampolines\n"); | ||
| 18 | if (__test_facility(82, S390_lowcore.alt_stfle_fac_list)) | ||
| 19 | return sprintf(buf, "Mitigation: limited branch prediction\n"); | ||
| 20 | return sprintf(buf, "Vulnerable\n"); | ||
| 21 | } | ||
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index 1c9ddd7aa5ec..0292d68e7dde 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c | |||
| @@ -753,6 +753,10 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
| 753 | */ | 753 | */ |
| 754 | rate = 0; | 754 | rate = 0; |
| 755 | if (attr->freq) { | 755 | if (attr->freq) { |
| 756 | if (!attr->sample_freq) { | ||
| 757 | err = -EINVAL; | ||
| 758 | goto out; | ||
| 759 | } | ||
| 756 | rate = freq_to_sample_rate(&si, attr->sample_freq); | 760 | rate = freq_to_sample_rate(&si, attr->sample_freq); |
| 757 | rate = hw_limit_rate(&si, rate); | 761 | rate = hw_limit_rate(&si, rate); |
| 758 | attr->freq = 0; | 762 | attr->freq = 0; |
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S index 73cc3750f0d3..7f14adf512c6 100644 --- a/arch/s390/kernel/reipl.S +++ b/arch/s390/kernel/reipl.S | |||
| @@ -7,8 +7,11 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/linkage.h> | 8 | #include <linux/linkage.h> |
| 9 | #include <asm/asm-offsets.h> | 9 | #include <asm/asm-offsets.h> |
| 10 | #include <asm/nospec-insn.h> | ||
| 10 | #include <asm/sigp.h> | 11 | #include <asm/sigp.h> |
| 11 | 12 | ||
| 13 | GEN_BR_THUNK %r9 | ||
| 14 | |||
| 12 | # | 15 | # |
| 13 | # Issue "store status" for the current CPU to its prefix page | 16 | # Issue "store status" for the current CPU to its prefix page |
| 14 | # and call passed function afterwards | 17 | # and call passed function afterwards |
| @@ -67,9 +70,9 @@ ENTRY(store_status) | |||
| 67 | st %r4,0(%r1) | 70 | st %r4,0(%r1) |
| 68 | st %r5,4(%r1) | 71 | st %r5,4(%r1) |
| 69 | stg %r2,8(%r1) | 72 | stg %r2,8(%r1) |
| 70 | lgr %r1,%r2 | 73 | lgr %r9,%r2 |
| 71 | lgr %r2,%r3 | 74 | lgr %r2,%r3 |
| 72 | br %r1 | 75 | BR_EX %r9 |
| 73 | 76 | ||
| 74 | .section .bss | 77 | .section .bss |
| 75 | .align 8 | 78 | .align 8 |
diff --git a/arch/s390/kernel/swsusp.S b/arch/s390/kernel/swsusp.S index e99187149f17..a049a7b9d6e8 100644 --- a/arch/s390/kernel/swsusp.S +++ b/arch/s390/kernel/swsusp.S | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <asm/ptrace.h> | 13 | #include <asm/ptrace.h> |
| 14 | #include <asm/thread_info.h> | 14 | #include <asm/thread_info.h> |
| 15 | #include <asm/asm-offsets.h> | 15 | #include <asm/asm-offsets.h> |
| 16 | #include <asm/nospec-insn.h> | ||
| 16 | #include <asm/sigp.h> | 17 | #include <asm/sigp.h> |
| 17 | 18 | ||
| 18 | /* | 19 | /* |
| @@ -24,6 +25,8 @@ | |||
| 24 | * (see below) in the resume process. | 25 | * (see below) in the resume process. |
| 25 | * This function runs with disabled interrupts. | 26 | * This function runs with disabled interrupts. |
| 26 | */ | 27 | */ |
| 28 | GEN_BR_THUNK %r14 | ||
| 29 | |||
| 27 | .section .text | 30 | .section .text |
| 28 | ENTRY(swsusp_arch_suspend) | 31 | ENTRY(swsusp_arch_suspend) |
| 29 | stmg %r6,%r15,__SF_GPRS(%r15) | 32 | stmg %r6,%r15,__SF_GPRS(%r15) |
| @@ -103,7 +106,7 @@ ENTRY(swsusp_arch_suspend) | |||
| 103 | spx 0x318(%r1) | 106 | spx 0x318(%r1) |
| 104 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) | 107 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) |
| 105 | lghi %r2,0 | 108 | lghi %r2,0 |
| 106 | br %r14 | 109 | BR_EX %r14 |
| 107 | 110 | ||
| 108 | /* | 111 | /* |
| 109 | * Restore saved memory image to correct place and restore register context. | 112 | * Restore saved memory image to correct place and restore register context. |
| @@ -197,11 +200,10 @@ pgm_check_entry: | |||
| 197 | larl %r15,init_thread_union | 200 | larl %r15,init_thread_union |
| 198 | ahi %r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER) | 201 | ahi %r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER) |
| 199 | larl %r2,.Lpanic_string | 202 | larl %r2,.Lpanic_string |
| 200 | larl %r3,sclp_early_printk | ||
| 201 | lghi %r1,0 | 203 | lghi %r1,0 |
| 202 | sam31 | 204 | sam31 |
| 203 | sigp %r1,%r0,SIGP_SET_ARCHITECTURE | 205 | sigp %r1,%r0,SIGP_SET_ARCHITECTURE |
| 204 | basr %r14,%r3 | 206 | brasl %r14,sclp_early_printk |
| 205 | larl %r3,.Ldisabled_wait_31 | 207 | larl %r3,.Ldisabled_wait_31 |
| 206 | lpsw 0(%r3) | 208 | lpsw 0(%r3) |
| 207 | 4: | 209 | 4: |
| @@ -267,7 +269,7 @@ restore_registers: | |||
| 267 | /* Return 0 */ | 269 | /* Return 0 */ |
| 268 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) | 270 | lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) |
| 269 | lghi %r2,0 | 271 | lghi %r2,0 |
| 270 | br %r14 | 272 | BR_EX %r14 |
| 271 | 273 | ||
| 272 | .section .data..nosave,"aw",@progbits | 274 | .section .data..nosave,"aw",@progbits |
| 273 | .align 8 | 275 | .align 8 |
diff --git a/arch/s390/lib/mem.S b/arch/s390/lib/mem.S index 495c9c4bacc7..2311f15be9cf 100644 --- a/arch/s390/lib/mem.S +++ b/arch/s390/lib/mem.S | |||
| @@ -7,6 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/linkage.h> | 8 | #include <linux/linkage.h> |
| 9 | #include <asm/export.h> | 9 | #include <asm/export.h> |
| 10 | #include <asm/nospec-insn.h> | ||
| 11 | |||
| 12 | GEN_BR_THUNK %r14 | ||
| 10 | 13 | ||
| 11 | /* | 14 | /* |
| 12 | * void *memmove(void *dest, const void *src, size_t n) | 15 | * void *memmove(void *dest, const void *src, size_t n) |
| @@ -33,14 +36,14 @@ ENTRY(memmove) | |||
| 33 | .Lmemmove_forward_remainder: | 36 | .Lmemmove_forward_remainder: |
| 34 | larl %r5,.Lmemmove_mvc | 37 | larl %r5,.Lmemmove_mvc |
| 35 | ex %r4,0(%r5) | 38 | ex %r4,0(%r5) |
| 36 | br %r14 | 39 | BR_EX %r14 |
| 37 | .Lmemmove_reverse: | 40 | .Lmemmove_reverse: |
| 38 | ic %r0,0(%r4,%r3) | 41 | ic %r0,0(%r4,%r3) |
| 39 | stc %r0,0(%r4,%r1) | 42 | stc %r0,0(%r4,%r1) |
| 40 | brctg %r4,.Lmemmove_reverse | 43 | brctg %r4,.Lmemmove_reverse |
| 41 | ic %r0,0(%r4,%r3) | 44 | ic %r0,0(%r4,%r3) |
| 42 | stc %r0,0(%r4,%r1) | 45 | stc %r0,0(%r4,%r1) |
| 43 | br %r14 | 46 | BR_EX %r14 |
| 44 | .Lmemmove_mvc: | 47 | .Lmemmove_mvc: |
| 45 | mvc 0(1,%r1),0(%r3) | 48 | mvc 0(1,%r1),0(%r3) |
| 46 | EXPORT_SYMBOL(memmove) | 49 | EXPORT_SYMBOL(memmove) |
| @@ -77,7 +80,7 @@ ENTRY(memset) | |||
| 77 | .Lmemset_clear_remainder: | 80 | .Lmemset_clear_remainder: |
| 78 | larl %r3,.Lmemset_xc | 81 | larl %r3,.Lmemset_xc |
| 79 | ex %r4,0(%r3) | 82 | ex %r4,0(%r3) |
| 80 | br %r14 | 83 | BR_EX %r14 |
| 81 | .Lmemset_fill: | 84 | .Lmemset_fill: |
| 82 | cghi %r4,1 | 85 | cghi %r4,1 |
| 83 | lgr %r1,%r2 | 86 | lgr %r1,%r2 |
| @@ -95,10 +98,10 @@ ENTRY(memset) | |||
| 95 | stc %r3,0(%r1) | 98 | stc %r3,0(%r1) |
| 96 | larl %r5,.Lmemset_mvc | 99 | larl %r5,.Lmemset_mvc |
| 97 | ex %r4,0(%r5) | 100 | ex %r4,0(%r5) |
| 98 | br %r14 | 101 | BR_EX %r14 |
| 99 | .Lmemset_fill_exit: | 102 | .Lmemset_fill_exit: |
| 100 | stc %r3,0(%r1) | 103 | stc %r3,0(%r1) |
| 101 | br %r14 | 104 | BR_EX %r14 |
| 102 | .Lmemset_xc: | 105 | .Lmemset_xc: |
| 103 | xc 0(1,%r1),0(%r1) | 106 | xc 0(1,%r1),0(%r1) |
| 104 | .Lmemset_mvc: | 107 | .Lmemset_mvc: |
| @@ -121,7 +124,7 @@ ENTRY(memcpy) | |||
| 121 | .Lmemcpy_remainder: | 124 | .Lmemcpy_remainder: |
| 122 | larl %r5,.Lmemcpy_mvc | 125 | larl %r5,.Lmemcpy_mvc |
| 123 | ex %r4,0(%r5) | 126 | ex %r4,0(%r5) |
| 124 | br %r14 | 127 | BR_EX %r14 |
| 125 | .Lmemcpy_loop: | 128 | .Lmemcpy_loop: |
| 126 | mvc 0(256,%r1),0(%r3) | 129 | mvc 0(256,%r1),0(%r3) |
| 127 | la %r1,256(%r1) | 130 | la %r1,256(%r1) |
| @@ -159,10 +162,10 @@ ENTRY(__memset\bits) | |||
| 159 | \insn %r3,0(%r1) | 162 | \insn %r3,0(%r1) |
| 160 | larl %r5,.L__memset_mvc\bits | 163 | larl %r5,.L__memset_mvc\bits |
| 161 | ex %r4,0(%r5) | 164 | ex %r4,0(%r5) |
| 162 | br %r14 | 165 | BR_EX %r14 |
| 163 | .L__memset_exit\bits: | 166 | .L__memset_exit\bits: |
| 164 | \insn %r3,0(%r2) | 167 | \insn %r3,0(%r2) |
| 165 | br %r14 | 168 | BR_EX %r14 |
| 166 | .L__memset_mvc\bits: | 169 | .L__memset_mvc\bits: |
| 167 | mvc \bytes(1,%r1),0(%r1) | 170 | mvc \bytes(1,%r1),0(%r1) |
| 168 | .endm | 171 | .endm |
diff --git a/arch/s390/net/bpf_jit.S b/arch/s390/net/bpf_jit.S index 25bb4643c4f4..9f794869c1b0 100644 --- a/arch/s390/net/bpf_jit.S +++ b/arch/s390/net/bpf_jit.S | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/linkage.h> | 11 | #include <linux/linkage.h> |
| 12 | #include <asm/nospec-insn.h> | ||
| 12 | #include "bpf_jit.h" | 13 | #include "bpf_jit.h" |
| 13 | 14 | ||
| 14 | /* | 15 | /* |
| @@ -54,7 +55,7 @@ ENTRY(sk_load_##NAME##_pos); \ | |||
| 54 | clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \ | 55 | clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \ |
| 55 | jh sk_load_##NAME##_slow; \ | 56 | jh sk_load_##NAME##_slow; \ |
| 56 | LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \ | 57 | LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \ |
| 57 | b OFF_OK(%r6); /* Return */ \ | 58 | B_EX OFF_OK,%r6; /* Return */ \ |
| 58 | \ | 59 | \ |
| 59 | sk_load_##NAME##_slow:; \ | 60 | sk_load_##NAME##_slow:; \ |
| 60 | lgr %r2,%r7; /* Arg1 = skb pointer */ \ | 61 | lgr %r2,%r7; /* Arg1 = skb pointer */ \ |
| @@ -64,11 +65,14 @@ sk_load_##NAME##_slow:; \ | |||
| 64 | brasl %r14,skb_copy_bits; /* Get data from skb */ \ | 65 | brasl %r14,skb_copy_bits; /* Get data from skb */ \ |
| 65 | LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \ | 66 | LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \ |
| 66 | ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \ | 67 | ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \ |
| 67 | br %r6; /* Return */ | 68 | BR_EX %r6; /* Return */ |
| 68 | 69 | ||
| 69 | sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */ | 70 | sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */ |
| 70 | sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */ | 71 | sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */ |
| 71 | 72 | ||
| 73 | GEN_BR_THUNK %r6 | ||
| 74 | GEN_B_THUNK OFF_OK,%r6 | ||
| 75 | |||
| 72 | /* | 76 | /* |
| 73 | * Load 1 byte from SKB (optimized version) | 77 | * Load 1 byte from SKB (optimized version) |
| 74 | */ | 78 | */ |
| @@ -80,7 +84,7 @@ ENTRY(sk_load_byte_pos) | |||
| 80 | clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen? | 84 | clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen? |
| 81 | jnl sk_load_byte_slow | 85 | jnl sk_load_byte_slow |
| 82 | llgc %r14,0(%r3,%r12) # Get byte from skb | 86 | llgc %r14,0(%r3,%r12) # Get byte from skb |
| 83 | b OFF_OK(%r6) # Return OK | 87 | B_EX OFF_OK,%r6 # Return OK |
| 84 | 88 | ||
| 85 | sk_load_byte_slow: | 89 | sk_load_byte_slow: |
| 86 | lgr %r2,%r7 # Arg1 = skb pointer | 90 | lgr %r2,%r7 # Arg1 = skb pointer |
| @@ -90,7 +94,7 @@ sk_load_byte_slow: | |||
| 90 | brasl %r14,skb_copy_bits # Get data from skb | 94 | brasl %r14,skb_copy_bits # Get data from skb |
| 91 | llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer | 95 | llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer |
| 92 | ltgr %r2,%r2 # Set cc to (%r2 != 0) | 96 | ltgr %r2,%r2 # Set cc to (%r2 != 0) |
| 93 | br %r6 # Return cc | 97 | BR_EX %r6 # Return cc |
| 94 | 98 | ||
| 95 | #define sk_negative_common(NAME, SIZE, LOAD) \ | 99 | #define sk_negative_common(NAME, SIZE, LOAD) \ |
| 96 | sk_load_##NAME##_slow_neg:; \ | 100 | sk_load_##NAME##_slow_neg:; \ |
| @@ -104,7 +108,7 @@ sk_load_##NAME##_slow_neg:; \ | |||
| 104 | jz bpf_error; \ | 108 | jz bpf_error; \ |
| 105 | LOAD %r14,0(%r2); /* Get data from pointer */ \ | 109 | LOAD %r14,0(%r2); /* Get data from pointer */ \ |
| 106 | xr %r3,%r3; /* Set cc to zero */ \ | 110 | xr %r3,%r3; /* Set cc to zero */ \ |
| 107 | br %r6; /* Return cc */ | 111 | BR_EX %r6; /* Return cc */ |
| 108 | 112 | ||
| 109 | sk_negative_common(word, 4, llgf) | 113 | sk_negative_common(word, 4, llgf) |
| 110 | sk_negative_common(half, 2, llgh) | 114 | sk_negative_common(half, 2, llgh) |
| @@ -113,4 +117,4 @@ sk_negative_common(byte, 1, llgc) | |||
| 113 | bpf_error: | 117 | bpf_error: |
| 114 | # force a return 0 from jit handler | 118 | # force a return 0 from jit handler |
| 115 | ltgr %r15,%r15 # Set condition code | 119 | ltgr %r15,%r15 # Set condition code |
| 116 | br %r6 | 120 | BR_EX %r6 |
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 78a19c93b380..dd2bcf0e7d00 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include <linux/bpf.h> | 25 | #include <linux/bpf.h> |
| 26 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
| 27 | #include <asm/dis.h> | 27 | #include <asm/dis.h> |
| 28 | #include <asm/facility.h> | ||
| 29 | #include <asm/nospec-branch.h> | ||
| 28 | #include <asm/set_memory.h> | 30 | #include <asm/set_memory.h> |
| 29 | #include "bpf_jit.h" | 31 | #include "bpf_jit.h" |
| 30 | 32 | ||
| @@ -41,6 +43,8 @@ struct bpf_jit { | |||
| 41 | int base_ip; /* Base address for literal pool */ | 43 | int base_ip; /* Base address for literal pool */ |
| 42 | int ret0_ip; /* Address of return 0 */ | 44 | int ret0_ip; /* Address of return 0 */ |
| 43 | int exit_ip; /* Address of exit */ | 45 | int exit_ip; /* Address of exit */ |
| 46 | int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */ | ||
| 47 | int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */ | ||
| 44 | int tail_call_start; /* Tail call start offset */ | 48 | int tail_call_start; /* Tail call start offset */ |
| 45 | int labels[1]; /* Labels for local jumps */ | 49 | int labels[1]; /* Labels for local jumps */ |
| 46 | }; | 50 | }; |
| @@ -250,6 +254,19 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1) | |||
| 250 | REG_SET_SEEN(b2); \ | 254 | REG_SET_SEEN(b2); \ |
| 251 | }) | 255 | }) |
| 252 | 256 | ||
| 257 | #define EMIT6_PCREL_RILB(op, b, target) \ | ||
| 258 | ({ \ | ||
| 259 | int rel = (target - jit->prg) / 2; \ | ||
| 260 | _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \ | ||
| 261 | REG_SET_SEEN(b); \ | ||
| 262 | }) | ||
| 263 | |||
| 264 | #define EMIT6_PCREL_RIL(op, target) \ | ||
| 265 | ({ \ | ||
| 266 | int rel = (target - jit->prg) / 2; \ | ||
| 267 | _EMIT6(op | rel >> 16, rel & 0xffff); \ | ||
| 268 | }) | ||
| 269 | |||
| 253 | #define _EMIT6_IMM(op, imm) \ | 270 | #define _EMIT6_IMM(op, imm) \ |
| 254 | ({ \ | 271 | ({ \ |
| 255 | unsigned int __imm = (imm); \ | 272 | unsigned int __imm = (imm); \ |
| @@ -469,8 +486,45 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth) | |||
| 469 | EMIT4(0xb9040000, REG_2, BPF_REG_0); | 486 | EMIT4(0xb9040000, REG_2, BPF_REG_0); |
| 470 | /* Restore registers */ | 487 | /* Restore registers */ |
| 471 | save_restore_regs(jit, REGS_RESTORE, stack_depth); | 488 | save_restore_regs(jit, REGS_RESTORE, stack_depth); |
| 489 | if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) { | ||
| 490 | jit->r14_thunk_ip = jit->prg; | ||
| 491 | /* Generate __s390_indirect_jump_r14 thunk */ | ||
| 492 | if (test_facility(35)) { | ||
| 493 | /* exrl %r0,.+10 */ | ||
| 494 | EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10); | ||
| 495 | } else { | ||
| 496 | /* larl %r1,.+14 */ | ||
| 497 | EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14); | ||
| 498 | /* ex 0,0(%r1) */ | ||
| 499 | EMIT4_DISP(0x44000000, REG_0, REG_1, 0); | ||
| 500 | } | ||
| 501 | /* j . */ | ||
| 502 | EMIT4_PCREL(0xa7f40000, 0); | ||
| 503 | } | ||
| 472 | /* br %r14 */ | 504 | /* br %r14 */ |
| 473 | _EMIT2(0x07fe); | 505 | _EMIT2(0x07fe); |
| 506 | |||
| 507 | if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable && | ||
| 508 | (jit->seen & SEEN_FUNC)) { | ||
| 509 | jit->r1_thunk_ip = jit->prg; | ||
| 510 | /* Generate __s390_indirect_jump_r1 thunk */ | ||
| 511 | if (test_facility(35)) { | ||
| 512 | /* exrl %r0,.+10 */ | ||
| 513 | EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10); | ||
| 514 | /* j . */ | ||
| 515 | EMIT4_PCREL(0xa7f40000, 0); | ||
| 516 | /* br %r1 */ | ||
| 517 | _EMIT2(0x07f1); | ||
| 518 | } else { | ||
| 519 | /* larl %r1,.+14 */ | ||
| 520 | EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14); | ||
| 521 | /* ex 0,S390_lowcore.br_r1_tampoline */ | ||
| 522 | EMIT4_DISP(0x44000000, REG_0, REG_0, | ||
| 523 | offsetof(struct lowcore, br_r1_trampoline)); | ||
| 524 | /* j . */ | ||
| 525 | EMIT4_PCREL(0xa7f40000, 0); | ||
| 526 | } | ||
| 527 | } | ||
| 474 | } | 528 | } |
| 475 | 529 | ||
| 476 | /* | 530 | /* |
| @@ -966,8 +1020,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i | |||
| 966 | /* lg %w1,<d(imm)>(%l) */ | 1020 | /* lg %w1,<d(imm)>(%l) */ |
| 967 | EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L, | 1021 | EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L, |
| 968 | EMIT_CONST_U64(func)); | 1022 | EMIT_CONST_U64(func)); |
| 969 | /* basr %r14,%w1 */ | 1023 | if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) { |
| 970 | EMIT2(0x0d00, REG_14, REG_W1); | 1024 | /* brasl %r14,__s390_indirect_jump_r1 */ |
| 1025 | EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip); | ||
| 1026 | } else { | ||
| 1027 | /* basr %r14,%w1 */ | ||
| 1028 | EMIT2(0x0d00, REG_14, REG_W1); | ||
| 1029 | } | ||
| 971 | /* lgr %b0,%r2: load return value into %b0 */ | 1030 | /* lgr %b0,%r2: load return value into %b0 */ |
| 972 | EMIT4(0xb9040000, BPF_REG_0, REG_2); | 1031 | EMIT4(0xb9040000, BPF_REG_0, REG_2); |
| 973 | if ((jit->seen & SEEN_SKB) && | 1032 | if ((jit->seen & SEEN_SKB) && |
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h index 4c851ebb3ceb..0ede697c3961 100644 --- a/arch/x86/include/uapi/asm/kvm_para.h +++ b/arch/x86/include/uapi/asm/kvm_para.h | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | #define KVM_FEATURE_PV_TLB_FLUSH 9 | 29 | #define KVM_FEATURE_PV_TLB_FLUSH 9 |
| 30 | #define KVM_FEATURE_ASYNC_PF_VMEXIT 10 | 30 | #define KVM_FEATURE_ASYNC_PF_VMEXIT 10 |
| 31 | 31 | ||
| 32 | #define KVM_HINTS_DEDICATED 0 | 32 | #define KVM_HINTS_REALTIME 0 |
| 33 | 33 | ||
| 34 | /* The last 8 bits are used to indicate how to interpret the flags field | 34 | /* The last 8 bits are used to indicate how to interpret the flags field |
| 35 | * in pvclock structure. If no bits are set, all flags are ignored. | 35 | * in pvclock structure. If no bits are set, all flags are ignored. |
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index c88e0b127810..b481b95bd8f6 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c | |||
| @@ -14,8 +14,11 @@ | |||
| 14 | #include <asm/amd_nb.h> | 14 | #include <asm/amd_nb.h> |
| 15 | 15 | ||
| 16 | #define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450 | 16 | #define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450 |
| 17 | #define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0 | ||
| 17 | #define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 | 18 | #define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 |
| 18 | #define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464 | 19 | #define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464 |
| 20 | #define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 0x15eb | ||
| 21 | #define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec | ||
| 19 | 22 | ||
| 20 | /* Protect the PCI config register pairs used for SMN and DF indirect access. */ | 23 | /* Protect the PCI config register pairs used for SMN and DF indirect access. */ |
| 21 | static DEFINE_MUTEX(smn_mutex); | 24 | static DEFINE_MUTEX(smn_mutex); |
| @@ -24,6 +27,7 @@ static u32 *flush_words; | |||
| 24 | 27 | ||
| 25 | static const struct pci_device_id amd_root_ids[] = { | 28 | static const struct pci_device_id amd_root_ids[] = { |
| 26 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) }, | 29 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) }, |
| 30 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT) }, | ||
| 27 | {} | 31 | {} |
| 28 | }; | 32 | }; |
| 29 | 33 | ||
| @@ -39,6 +43,7 @@ const struct pci_device_id amd_nb_misc_ids[] = { | |||
| 39 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, | 43 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, |
| 40 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, | 44 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, |
| 41 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, | 45 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, |
| 46 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) }, | ||
| 42 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, | 47 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, |
| 43 | {} | 48 | {} |
| 44 | }; | 49 | }; |
| @@ -51,6 +56,7 @@ static const struct pci_device_id amd_nb_link_ids[] = { | |||
| 51 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, | 56 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, |
| 52 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) }, | 57 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) }, |
| 53 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) }, | 58 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) }, |
| 59 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F4) }, | ||
| 54 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) }, | 60 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) }, |
| 55 | {} | 61 | {} |
| 56 | }; | 62 | }; |
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 7867417cfaff..5b2300b818af 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c | |||
| @@ -457,7 +457,7 @@ static void __init sev_map_percpu_data(void) | |||
| 457 | static void __init kvm_smp_prepare_cpus(unsigned int max_cpus) | 457 | static void __init kvm_smp_prepare_cpus(unsigned int max_cpus) |
| 458 | { | 458 | { |
| 459 | native_smp_prepare_cpus(max_cpus); | 459 | native_smp_prepare_cpus(max_cpus); |
| 460 | if (kvm_para_has_hint(KVM_HINTS_DEDICATED)) | 460 | if (kvm_para_has_hint(KVM_HINTS_REALTIME)) |
| 461 | static_branch_disable(&virt_spin_lock_key); | 461 | static_branch_disable(&virt_spin_lock_key); |
| 462 | } | 462 | } |
| 463 | 463 | ||
| @@ -553,7 +553,7 @@ static void __init kvm_guest_init(void) | |||
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) && | 555 | if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) && |
| 556 | !kvm_para_has_hint(KVM_HINTS_DEDICATED) && | 556 | !kvm_para_has_hint(KVM_HINTS_REALTIME) && |
| 557 | kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) | 557 | kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) |
| 558 | pv_mmu_ops.flush_tlb_others = kvm_flush_tlb_others; | 558 | pv_mmu_ops.flush_tlb_others = kvm_flush_tlb_others; |
| 559 | 559 | ||
| @@ -649,7 +649,7 @@ static __init int kvm_setup_pv_tlb_flush(void) | |||
| 649 | int cpu; | 649 | int cpu; |
| 650 | 650 | ||
| 651 | if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) && | 651 | if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) && |
| 652 | !kvm_para_has_hint(KVM_HINTS_DEDICATED) && | 652 | !kvm_para_has_hint(KVM_HINTS_REALTIME) && |
| 653 | kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) { | 653 | kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) { |
| 654 | for_each_possible_cpu(cpu) { | 654 | for_each_possible_cpu(cpu) { |
| 655 | zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu), | 655 | zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu), |
| @@ -745,7 +745,7 @@ void __init kvm_spinlock_init(void) | |||
| 745 | if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) | 745 | if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) |
| 746 | return; | 746 | return; |
| 747 | 747 | ||
| 748 | if (kvm_para_has_hint(KVM_HINTS_DEDICATED)) | 748 | if (kvm_para_has_hint(KVM_HINTS_REALTIME)) |
| 749 | return; | 749 | return; |
| 750 | 750 | ||
| 751 | __pv_init_lock_hash(); | 751 | __pv_init_lock_hash(); |
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 98618e397342..5708e951a5c6 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c | |||
| @@ -1265,7 +1265,7 @@ static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu) | |||
| 1265 | struct kvm_run *run = vcpu->run; | 1265 | struct kvm_run *run = vcpu->run; |
| 1266 | 1266 | ||
| 1267 | kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result); | 1267 | kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result); |
| 1268 | return 1; | 1268 | return kvm_skip_emulated_instruction(vcpu); |
| 1269 | } | 1269 | } |
| 1270 | 1270 | ||
| 1271 | static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param) | 1271 | static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param) |
| @@ -1296,8 +1296,10 @@ static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param) | |||
| 1296 | if (param & ~KVM_HYPERV_CONN_ID_MASK) | 1296 | if (param & ~KVM_HYPERV_CONN_ID_MASK) |
| 1297 | return HV_STATUS_INVALID_HYPERCALL_INPUT; | 1297 | return HV_STATUS_INVALID_HYPERCALL_INPUT; |
| 1298 | 1298 | ||
| 1299 | /* conn_to_evt is protected by vcpu->kvm->srcu */ | 1299 | /* the eventfd is protected by vcpu->kvm->srcu, but conn_to_evt isn't */ |
| 1300 | rcu_read_lock(); | ||
| 1300 | eventfd = idr_find(&vcpu->kvm->arch.hyperv.conn_to_evt, param); | 1301 | eventfd = idr_find(&vcpu->kvm->arch.hyperv.conn_to_evt, param); |
| 1302 | rcu_read_unlock(); | ||
| 1301 | if (!eventfd) | 1303 | if (!eventfd) |
| 1302 | return HV_STATUS_INVALID_PORT_ID; | 1304 | return HV_STATUS_INVALID_PORT_ID; |
| 1303 | 1305 | ||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c7668806163f..3f1696570b41 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
| @@ -1494,6 +1494,12 @@ static inline bool cpu_has_vmx_vmfunc(void) | |||
| 1494 | SECONDARY_EXEC_ENABLE_VMFUNC; | 1494 | SECONDARY_EXEC_ENABLE_VMFUNC; |
| 1495 | } | 1495 | } |
| 1496 | 1496 | ||
| 1497 | static bool vmx_umip_emulated(void) | ||
| 1498 | { | ||
| 1499 | return vmcs_config.cpu_based_2nd_exec_ctrl & | ||
| 1500 | SECONDARY_EXEC_DESC; | ||
| 1501 | } | ||
| 1502 | |||
| 1497 | static inline bool report_flexpriority(void) | 1503 | static inline bool report_flexpriority(void) |
| 1498 | { | 1504 | { |
| 1499 | return flexpriority_enabled; | 1505 | return flexpriority_enabled; |
| @@ -4761,14 +4767,16 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
| 4761 | else | 4767 | else |
| 4762 | hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON; | 4768 | hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON; |
| 4763 | 4769 | ||
| 4764 | if ((cr4 & X86_CR4_UMIP) && !boot_cpu_has(X86_FEATURE_UMIP)) { | 4770 | if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) { |
| 4765 | vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, | 4771 | if (cr4 & X86_CR4_UMIP) { |
| 4766 | SECONDARY_EXEC_DESC); | 4772 | vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, |
| 4767 | hw_cr4 &= ~X86_CR4_UMIP; | ||
| 4768 | } else if (!is_guest_mode(vcpu) || | ||
| 4769 | !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC)) | ||
| 4770 | vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, | ||
| 4771 | SECONDARY_EXEC_DESC); | 4773 | SECONDARY_EXEC_DESC); |
| 4774 | hw_cr4 &= ~X86_CR4_UMIP; | ||
| 4775 | } else if (!is_guest_mode(vcpu) || | ||
| 4776 | !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC)) | ||
| 4777 | vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, | ||
| 4778 | SECONDARY_EXEC_DESC); | ||
| 4779 | } | ||
| 4772 | 4780 | ||
| 4773 | if (cr4 & X86_CR4_VMXE) { | 4781 | if (cr4 & X86_CR4_VMXE) { |
| 4774 | /* | 4782 | /* |
| @@ -9497,12 +9505,6 @@ static bool vmx_xsaves_supported(void) | |||
| 9497 | SECONDARY_EXEC_XSAVES; | 9505 | SECONDARY_EXEC_XSAVES; |
| 9498 | } | 9506 | } |
| 9499 | 9507 | ||
| 9500 | static bool vmx_umip_emulated(void) | ||
| 9501 | { | ||
| 9502 | return vmcs_config.cpu_based_2nd_exec_ctrl & | ||
| 9503 | SECONDARY_EXEC_DESC; | ||
| 9504 | } | ||
| 9505 | |||
| 9506 | static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) | 9508 | static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) |
| 9507 | { | 9509 | { |
| 9508 | u32 exit_intr_info; | 9510 | u32 exit_intr_info; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 51ecd381793b..59371de5d722 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -114,7 +114,7 @@ module_param(ignore_msrs, bool, S_IRUGO | S_IWUSR); | |||
| 114 | static bool __read_mostly report_ignored_msrs = true; | 114 | static bool __read_mostly report_ignored_msrs = true; |
| 115 | module_param(report_ignored_msrs, bool, S_IRUGO | S_IWUSR); | 115 | module_param(report_ignored_msrs, bool, S_IRUGO | S_IWUSR); |
| 116 | 116 | ||
| 117 | unsigned int min_timer_period_us = 500; | 117 | unsigned int min_timer_period_us = 200; |
| 118 | module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR); | 118 | module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR); |
| 119 | 119 | ||
| 120 | static bool __read_mostly kvmclock_periodic_sync = true; | 120 | static bool __read_mostly kvmclock_periodic_sync = true; |
| @@ -843,7 +843,10 @@ EXPORT_SYMBOL_GPL(kvm_set_cr4); | |||
| 843 | int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | 843 | int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) |
| 844 | { | 844 | { |
| 845 | #ifdef CONFIG_X86_64 | 845 | #ifdef CONFIG_X86_64 |
| 846 | cr3 &= ~CR3_PCID_INVD; | 846 | bool pcid_enabled = kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE); |
| 847 | |||
| 848 | if (pcid_enabled) | ||
| 849 | cr3 &= ~CR3_PCID_INVD; | ||
| 847 | #endif | 850 | #endif |
| 848 | 851 | ||
| 849 | if (cr3 == kvm_read_cr3(vcpu) && !pdptrs_changed(vcpu)) { | 852 | if (cr3 == kvm_read_cr3(vcpu) && !pdptrs_changed(vcpu)) { |
| @@ -6671,12 +6674,13 @@ void kvm_vcpu_deactivate_apicv(struct kvm_vcpu *vcpu) | |||
| 6671 | int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) | 6674 | int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) |
| 6672 | { | 6675 | { |
| 6673 | unsigned long nr, a0, a1, a2, a3, ret; | 6676 | unsigned long nr, a0, a1, a2, a3, ret; |
| 6674 | int op_64_bit, r; | 6677 | int op_64_bit; |
| 6675 | |||
| 6676 | r = kvm_skip_emulated_instruction(vcpu); | ||
| 6677 | 6678 | ||
| 6678 | if (kvm_hv_hypercall_enabled(vcpu->kvm)) | 6679 | if (kvm_hv_hypercall_enabled(vcpu->kvm)) { |
| 6679 | return kvm_hv_hypercall(vcpu); | 6680 | if (!kvm_hv_hypercall(vcpu)) |
| 6681 | return 0; | ||
| 6682 | goto out; | ||
| 6683 | } | ||
| 6680 | 6684 | ||
| 6681 | nr = kvm_register_read(vcpu, VCPU_REGS_RAX); | 6685 | nr = kvm_register_read(vcpu, VCPU_REGS_RAX); |
| 6682 | a0 = kvm_register_read(vcpu, VCPU_REGS_RBX); | 6686 | a0 = kvm_register_read(vcpu, VCPU_REGS_RBX); |
| @@ -6697,7 +6701,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) | |||
| 6697 | 6701 | ||
| 6698 | if (kvm_x86_ops->get_cpl(vcpu) != 0) { | 6702 | if (kvm_x86_ops->get_cpl(vcpu) != 0) { |
| 6699 | ret = -KVM_EPERM; | 6703 | ret = -KVM_EPERM; |
| 6700 | goto out; | 6704 | goto out_error; |
| 6701 | } | 6705 | } |
| 6702 | 6706 | ||
| 6703 | switch (nr) { | 6707 | switch (nr) { |
| @@ -6717,12 +6721,14 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) | |||
| 6717 | ret = -KVM_ENOSYS; | 6721 | ret = -KVM_ENOSYS; |
| 6718 | break; | 6722 | break; |
| 6719 | } | 6723 | } |
| 6720 | out: | 6724 | out_error: |
| 6721 | if (!op_64_bit) | 6725 | if (!op_64_bit) |
| 6722 | ret = (u32)ret; | 6726 | ret = (u32)ret; |
| 6723 | kvm_register_write(vcpu, VCPU_REGS_RAX, ret); | 6727 | kvm_register_write(vcpu, VCPU_REGS_RAX, ret); |
| 6728 | |||
| 6729 | out: | ||
| 6724 | ++vcpu->stat.hypercalls; | 6730 | ++vcpu->stat.hypercalls; |
| 6725 | return r; | 6731 | return kvm_skip_emulated_instruction(vcpu); |
| 6726 | } | 6732 | } |
| 6727 | EXPORT_SYMBOL_GPL(kvm_emulate_hypercall); | 6733 | EXPORT_SYMBOL_GPL(kvm_emulate_hypercall); |
| 6728 | 6734 | ||
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index d33e7dbe3129..2d76106788a3 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -42,13 +42,11 @@ xmaddr_t arbitrary_virt_to_machine(void *vaddr) | |||
| 42 | } | 42 | } |
| 43 | EXPORT_SYMBOL_GPL(arbitrary_virt_to_machine); | 43 | EXPORT_SYMBOL_GPL(arbitrary_virt_to_machine); |
| 44 | 44 | ||
| 45 | static void xen_flush_tlb_all(void) | 45 | static noinline void xen_flush_tlb_all(void) |
| 46 | { | 46 | { |
| 47 | struct mmuext_op *op; | 47 | struct mmuext_op *op; |
| 48 | struct multicall_space mcs; | 48 | struct multicall_space mcs; |
| 49 | 49 | ||
| 50 | trace_xen_mmu_flush_tlb_all(0); | ||
| 51 | |||
| 52 | preempt_disable(); | 50 | preempt_disable(); |
| 53 | 51 | ||
| 54 | mcs = xen_mc_entry(sizeof(*op)); | 52 | mcs = xen_mc_entry(sizeof(*op)); |
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 486c0a34d00b..2c30cabfda90 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c | |||
| @@ -1310,13 +1310,11 @@ unsigned long xen_read_cr2_direct(void) | |||
| 1310 | return this_cpu_read(xen_vcpu_info.arch.cr2); | 1310 | return this_cpu_read(xen_vcpu_info.arch.cr2); |
| 1311 | } | 1311 | } |
| 1312 | 1312 | ||
| 1313 | static void xen_flush_tlb(void) | 1313 | static noinline void xen_flush_tlb(void) |
| 1314 | { | 1314 | { |
| 1315 | struct mmuext_op *op; | 1315 | struct mmuext_op *op; |
| 1316 | struct multicall_space mcs; | 1316 | struct multicall_space mcs; |
| 1317 | 1317 | ||
| 1318 | trace_xen_mmu_flush_tlb(0); | ||
| 1319 | |||
| 1320 | preempt_disable(); | 1318 | preempt_disable(); |
| 1321 | 1319 | ||
| 1322 | mcs = xen_mc_entry(sizeof(*op)); | 1320 | mcs = xen_mc_entry(sizeof(*op)); |
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 514aaf948ea9..3825df923480 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h | |||
| @@ -56,6 +56,10 @@ acpi_status acpi_ns_initialize_objects(void); | |||
| 56 | 56 | ||
| 57 | acpi_status acpi_ns_initialize_devices(u32 flags); | 57 | acpi_status acpi_ns_initialize_devices(u32 flags); |
| 58 | 58 | ||
| 59 | acpi_status | ||
| 60 | acpi_ns_init_one_package(acpi_handle obj_handle, | ||
| 61 | u32 level, void *context, void **return_value); | ||
| 62 | |||
| 59 | /* | 63 | /* |
| 60 | * nsload - Namespace loading | 64 | * nsload - Namespace loading |
| 61 | */ | 65 | */ |
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 99d92cb32803..f85c6f3271f6 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c | |||
| @@ -174,6 +174,13 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
| 174 | return_ACPI_STATUS(status); | 174 | return_ACPI_STATUS(status); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | /* Complete the initialization/resolution of package objects */ | ||
| 178 | |||
| 179 | status = acpi_ns_walk_namespace(ACPI_TYPE_PACKAGE, ACPI_ROOT_OBJECT, | ||
| 180 | ACPI_UINT32_MAX, 0, | ||
| 181 | acpi_ns_init_one_package, NULL, NULL, | ||
| 182 | NULL); | ||
| 183 | |||
| 177 | /* Parameter Data (optional) */ | 184 | /* Parameter Data (optional) */ |
| 178 | 185 | ||
| 179 | if (parameter_node) { | 186 | if (parameter_node) { |
| @@ -430,6 +437,13 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
| 430 | return_ACPI_STATUS(status); | 437 | return_ACPI_STATUS(status); |
| 431 | } | 438 | } |
| 432 | 439 | ||
| 440 | /* Complete the initialization/resolution of package objects */ | ||
| 441 | |||
| 442 | status = acpi_ns_walk_namespace(ACPI_TYPE_PACKAGE, ACPI_ROOT_OBJECT, | ||
| 443 | ACPI_UINT32_MAX, 0, | ||
| 444 | acpi_ns_init_one_package, NULL, NULL, | ||
| 445 | NULL); | ||
| 446 | |||
| 433 | /* Store the ddb_handle into the Target operand */ | 447 | /* Store the ddb_handle into the Target operand */ |
| 434 | 448 | ||
| 435 | status = acpi_ex_store(ddb_handle, target, walk_state); | 449 | status = acpi_ex_store(ddb_handle, target, walk_state); |
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 77f2b5f4948a..d77257d1c827 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c | |||
| @@ -242,6 +242,58 @@ error_exit: | |||
| 242 | 242 | ||
| 243 | /******************************************************************************* | 243 | /******************************************************************************* |
| 244 | * | 244 | * |
| 245 | * FUNCTION: acpi_ns_init_one_package | ||
| 246 | * | ||
| 247 | * PARAMETERS: obj_handle - Node | ||
| 248 | * level - Current nesting level | ||
| 249 | * context - Not used | ||
| 250 | * return_value - Not used | ||
| 251 | * | ||
| 252 | * RETURN: Status | ||
| 253 | * | ||
| 254 | * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every package | ||
| 255 | * within the namespace. Used during dynamic load of an SSDT. | ||
| 256 | * | ||
| 257 | ******************************************************************************/ | ||
| 258 | |||
| 259 | acpi_status | ||
| 260 | acpi_ns_init_one_package(acpi_handle obj_handle, | ||
| 261 | u32 level, void *context, void **return_value) | ||
| 262 | { | ||
| 263 | acpi_status status; | ||
| 264 | union acpi_operand_object *obj_desc; | ||
| 265 | struct acpi_namespace_node *node = | ||
| 266 | (struct acpi_namespace_node *)obj_handle; | ||
| 267 | |||
| 268 | obj_desc = acpi_ns_get_attached_object(node); | ||
| 269 | if (!obj_desc) { | ||
| 270 | return (AE_OK); | ||
| 271 | } | ||
| 272 | |||
| 273 | /* Exit if package is already initialized */ | ||
| 274 | |||
| 275 | if (obj_desc->package.flags & AOPOBJ_DATA_VALID) { | ||
| 276 | return (AE_OK); | ||
| 277 | } | ||
| 278 | |||
| 279 | status = acpi_ds_get_package_arguments(obj_desc); | ||
| 280 | if (ACPI_FAILURE(status)) { | ||
| 281 | return (AE_OK); | ||
| 282 | } | ||
| 283 | |||
| 284 | status = | ||
| 285 | acpi_ut_walk_package_tree(obj_desc, NULL, | ||
| 286 | acpi_ds_init_package_element, NULL); | ||
| 287 | if (ACPI_FAILURE(status)) { | ||
| 288 | return (AE_OK); | ||
| 289 | } | ||
| 290 | |||
| 291 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; | ||
| 292 | return (AE_OK); | ||
| 293 | } | ||
| 294 | |||
| 295 | /******************************************************************************* | ||
| 296 | * | ||
| 245 | * FUNCTION: acpi_ns_init_one_object | 297 | * FUNCTION: acpi_ns_init_one_object |
| 246 | * | 298 | * |
| 247 | * PARAMETERS: obj_handle - Node | 299 | * PARAMETERS: obj_handle - Node |
| @@ -360,27 +412,11 @@ acpi_ns_init_one_object(acpi_handle obj_handle, | |||
| 360 | 412 | ||
| 361 | case ACPI_TYPE_PACKAGE: | 413 | case ACPI_TYPE_PACKAGE: |
| 362 | 414 | ||
| 363 | info->package_init++; | 415 | /* Complete the initialization/resolution of the package object */ |
| 364 | status = acpi_ds_get_package_arguments(obj_desc); | ||
| 365 | if (ACPI_FAILURE(status)) { | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | |||
| 369 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE, | ||
| 370 | "%s: Completing resolution of Package elements\n", | ||
| 371 | ACPI_GET_FUNCTION_NAME)); | ||
| 372 | 416 | ||
| 373 | /* | 417 | info->package_init++; |
| 374 | * Resolve all named references in package objects (and all | 418 | status = |
| 375 | * sub-packages). This action has been deferred until the entire | 419 | acpi_ns_init_one_package(obj_handle, level, NULL, NULL); |
| 376 | * namespace has been loaded, in order to support external and | ||
| 377 | * forward references from individual package elements (05/2017). | ||
| 378 | */ | ||
| 379 | status = acpi_ut_walk_package_tree(obj_desc, NULL, | ||
| 380 | acpi_ds_init_package_element, | ||
| 381 | NULL); | ||
| 382 | |||
| 383 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; | ||
| 384 | break; | 420 | break; |
| 385 | 421 | ||
| 386 | default: | 422 | default: |
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 41492e980ef4..34968a381d0f 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
| @@ -266,15 +266,13 @@ config COMMON_CLK_STM32MP157 | |||
| 266 | Support for stm32mp157 SoC family clocks | 266 | Support for stm32mp157 SoC family clocks |
| 267 | 267 | ||
| 268 | config COMMON_CLK_STM32F | 268 | config COMMON_CLK_STM32F |
| 269 | bool "Clock driver for stm32f4 and stm32f7 SoC families" | 269 | def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746) |
| 270 | depends on MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746 | ||
| 271 | help | 270 | help |
| 272 | ---help--- | 271 | ---help--- |
| 273 | Support for stm32f4 and stm32f7 SoC families clocks | 272 | Support for stm32f4 and stm32f7 SoC families clocks |
| 274 | 273 | ||
| 275 | config COMMON_CLK_STM32H7 | 274 | config COMMON_CLK_STM32H7 |
| 276 | bool "Clock driver for stm32h7 SoC family" | 275 | def_bool COMMON_CLK && MACH_STM32H743 |
| 277 | depends on MACH_STM32H743 | ||
| 278 | help | 276 | help |
| 279 | ---help--- | 277 | ---help--- |
| 280 | Support for stm32h7 SoC family clocks | 278 | Support for stm32h7 SoC family clocks |
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 114ecbb94ec5..12320118f8de 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c | |||
| @@ -464,7 +464,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) | |||
| 464 | clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000); | 464 | clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000); |
| 465 | 465 | ||
| 466 | /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */ | 466 | /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */ |
| 467 | clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]); | 467 | clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_OSC]); |
| 468 | clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]); | 468 | clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]); |
| 469 | clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]); | 469 | clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]); |
| 470 | clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]); | 470 | clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]); |
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index de55c7d57438..96b35b8b3606 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
| @@ -20,7 +20,7 @@ config ACPI_CPPC_CPUFREQ | |||
| 20 | 20 | ||
| 21 | config ARM_ARMADA_37XX_CPUFREQ | 21 | config ARM_ARMADA_37XX_CPUFREQ |
| 22 | tristate "Armada 37xx CPUFreq support" | 22 | tristate "Armada 37xx CPUFreq support" |
| 23 | depends on ARCH_MVEBU | 23 | depends on ARCH_MVEBU && CPUFREQ_DT |
| 24 | help | 24 | help |
| 25 | This adds the CPUFreq driver support for Marvell Armada 37xx SoCs. | 25 | This adds the CPUFreq driver support for Marvell Armada 37xx SoCs. |
| 26 | The Armada 37xx PMU supports 4 frequency and VDD levels. | 26 | The Armada 37xx PMU supports 4 frequency and VDD levels. |
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index d29275b97e84..4a828c18099a 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c | |||
| @@ -524,6 +524,14 @@ static int bam_alloc_chan(struct dma_chan *chan) | |||
| 524 | return 0; | 524 | return 0; |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | static int bam_pm_runtime_get_sync(struct device *dev) | ||
| 528 | { | ||
| 529 | if (pm_runtime_enabled(dev)) | ||
| 530 | return pm_runtime_get_sync(dev); | ||
| 531 | |||
| 532 | return 0; | ||
| 533 | } | ||
| 534 | |||
| 527 | /** | 535 | /** |
| 528 | * bam_free_chan - Frees dma resources associated with specific channel | 536 | * bam_free_chan - Frees dma resources associated with specific channel |
| 529 | * @chan: specified channel | 537 | * @chan: specified channel |
| @@ -539,7 +547,7 @@ static void bam_free_chan(struct dma_chan *chan) | |||
| 539 | unsigned long flags; | 547 | unsigned long flags; |
| 540 | int ret; | 548 | int ret; |
| 541 | 549 | ||
| 542 | ret = pm_runtime_get_sync(bdev->dev); | 550 | ret = bam_pm_runtime_get_sync(bdev->dev); |
| 543 | if (ret < 0) | 551 | if (ret < 0) |
| 544 | return; | 552 | return; |
| 545 | 553 | ||
| @@ -720,7 +728,7 @@ static int bam_pause(struct dma_chan *chan) | |||
| 720 | unsigned long flag; | 728 | unsigned long flag; |
| 721 | int ret; | 729 | int ret; |
| 722 | 730 | ||
| 723 | ret = pm_runtime_get_sync(bdev->dev); | 731 | ret = bam_pm_runtime_get_sync(bdev->dev); |
| 724 | if (ret < 0) | 732 | if (ret < 0) |
| 725 | return ret; | 733 | return ret; |
| 726 | 734 | ||
| @@ -746,7 +754,7 @@ static int bam_resume(struct dma_chan *chan) | |||
| 746 | unsigned long flag; | 754 | unsigned long flag; |
| 747 | int ret; | 755 | int ret; |
| 748 | 756 | ||
| 749 | ret = pm_runtime_get_sync(bdev->dev); | 757 | ret = bam_pm_runtime_get_sync(bdev->dev); |
| 750 | if (ret < 0) | 758 | if (ret < 0) |
| 751 | return ret; | 759 | return ret; |
| 752 | 760 | ||
| @@ -852,7 +860,7 @@ static irqreturn_t bam_dma_irq(int irq, void *data) | |||
| 852 | if (srcs & P_IRQ) | 860 | if (srcs & P_IRQ) |
| 853 | tasklet_schedule(&bdev->task); | 861 | tasklet_schedule(&bdev->task); |
| 854 | 862 | ||
| 855 | ret = pm_runtime_get_sync(bdev->dev); | 863 | ret = bam_pm_runtime_get_sync(bdev->dev); |
| 856 | if (ret < 0) | 864 | if (ret < 0) |
| 857 | return ret; | 865 | return ret; |
| 858 | 866 | ||
| @@ -969,7 +977,7 @@ static void bam_start_dma(struct bam_chan *bchan) | |||
| 969 | if (!vd) | 977 | if (!vd) |
| 970 | return; | 978 | return; |
| 971 | 979 | ||
| 972 | ret = pm_runtime_get_sync(bdev->dev); | 980 | ret = bam_pm_runtime_get_sync(bdev->dev); |
| 973 | if (ret < 0) | 981 | if (ret < 0) |
| 974 | return; | 982 | return; |
| 975 | 983 | ||
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index a1b9338736e3..c2c21d839727 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
| @@ -716,7 +716,7 @@ static void remove_compat_control_link(struct drm_device *dev) | |||
| 716 | if (!minor) | 716 | if (!minor) |
| 717 | return; | 717 | return; |
| 718 | 718 | ||
| 719 | name = kasprintf(GFP_KERNEL, "controlD%d", minor->index); | 719 | name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64); |
| 720 | if (!name) | 720 | if (!name) |
| 721 | return; | 721 | return; |
| 722 | 722 | ||
diff --git a/drivers/gpu/drm/drm_dumb_buffers.c b/drivers/gpu/drm/drm_dumb_buffers.c index 39ac15ce4702..9e2ae02f31e0 100644 --- a/drivers/gpu/drm/drm_dumb_buffers.c +++ b/drivers/gpu/drm/drm_dumb_buffers.c | |||
| @@ -65,12 +65,13 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev, | |||
| 65 | return -EINVAL; | 65 | return -EINVAL; |
| 66 | 66 | ||
| 67 | /* overflow checks for 32bit size calculations */ | 67 | /* overflow checks for 32bit size calculations */ |
| 68 | /* NOTE: DIV_ROUND_UP() can overflow */ | 68 | if (args->bpp > U32_MAX - 8) |
| 69 | return -EINVAL; | ||
| 69 | cpp = DIV_ROUND_UP(args->bpp, 8); | 70 | cpp = DIV_ROUND_UP(args->bpp, 8); |
| 70 | if (!cpp || cpp > 0xffffffffU / args->width) | 71 | if (cpp > U32_MAX / args->width) |
| 71 | return -EINVAL; | 72 | return -EINVAL; |
| 72 | stride = cpp * args->width; | 73 | stride = cpp * args->width; |
| 73 | if (args->height > 0xffffffffU / stride) | 74 | if (args->height > U32_MAX / stride) |
| 74 | return -EINVAL; | 75 | return -EINVAL; |
| 75 | 76 | ||
| 76 | /* test for wrap-around */ | 77 | /* test for wrap-around */ |
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index e394799979a6..6d9b9453707c 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c | |||
| @@ -212,6 +212,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) | |||
| 212 | return -ENOMEM; | 212 | return -ENOMEM; |
| 213 | 213 | ||
| 214 | filp->private_data = priv; | 214 | filp->private_data = priv; |
| 215 | filp->f_mode |= FMODE_UNSIGNED_OFFSET; | ||
| 215 | priv->filp = filp; | 216 | priv->filp = filp; |
| 216 | priv->pid = get_pid(task_pid(current)); | 217 | priv->pid = get_pid(task_pid(current)); |
| 217 | priv->minor = minor; | 218 | priv->minor = minor; |
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index d596a8302ca3..854bd51b9478 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c | |||
| @@ -778,6 +778,9 @@ i915_gem_userptr_ioctl(struct drm_device *dev, | |||
| 778 | I915_USERPTR_UNSYNCHRONIZED)) | 778 | I915_USERPTR_UNSYNCHRONIZED)) |
| 779 | return -EINVAL; | 779 | return -EINVAL; |
| 780 | 780 | ||
| 781 | if (!args->user_size) | ||
| 782 | return -EINVAL; | ||
| 783 | |||
| 781 | if (offset_in_page(args->user_ptr | args->user_size)) | 784 | if (offset_in_page(args->user_ptr | args->user_size)) |
| 782 | return -EINVAL; | 785 | return -EINVAL; |
| 783 | 786 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e6a8c0ee7df1..8a69a9275e28 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -7326,6 +7326,9 @@ enum { | |||
| 7326 | #define SLICE_ECO_CHICKEN0 _MMIO(0x7308) | 7326 | #define SLICE_ECO_CHICKEN0 _MMIO(0x7308) |
| 7327 | #define PIXEL_MASK_CAMMING_DISABLE (1 << 14) | 7327 | #define PIXEL_MASK_CAMMING_DISABLE (1 << 14) |
| 7328 | 7328 | ||
| 7329 | #define GEN9_WM_CHICKEN3 _MMIO(0x5588) | ||
| 7330 | #define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9) | ||
| 7331 | |||
| 7329 | /* WaCatErrorRejectionIssue */ | 7332 | /* WaCatErrorRejectionIssue */ |
| 7330 | #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG _MMIO(0x9030) | 7333 | #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG _MMIO(0x9030) |
| 7331 | #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) | 7334 | #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) |
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 4ba139c27fba..f7c25828d3bb 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c | |||
| @@ -1149,6 +1149,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) | |||
| 1149 | WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK, | 1149 | WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK, |
| 1150 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); | 1150 | GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); |
| 1151 | 1151 | ||
| 1152 | /* WaClearHIZ_WM_CHICKEN3:bxt,glk */ | ||
| 1153 | if (IS_GEN9_LP(dev_priv)) | ||
| 1154 | WA_SET_BIT_MASKED(GEN9_WM_CHICKEN3, GEN9_FACTOR_IN_CLR_VAL_HIZ); | ||
| 1155 | |||
| 1152 | /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */ | 1156 | /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */ |
| 1153 | ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); | 1157 | ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); |
| 1154 | if (ret) | 1158 | if (ret) |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index e3a5f673ff67..8704f7f8d072 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
| @@ -884,6 +884,7 @@ static void execlists_submission_tasklet(unsigned long data) | |||
| 884 | 884 | ||
| 885 | head = execlists->csb_head; | 885 | head = execlists->csb_head; |
| 886 | tail = READ_ONCE(buf[write_idx]); | 886 | tail = READ_ONCE(buf[write_idx]); |
| 887 | rmb(); /* Hopefully paired with a wmb() in HW */ | ||
| 887 | } | 888 | } |
| 888 | GEM_TRACE("%s cs-irq head=%d [%d%s], tail=%d [%d%s]\n", | 889 | GEM_TRACE("%s cs-irq head=%d [%d%s], tail=%d [%d%s]\n", |
| 889 | engine->name, | 890 | engine->name, |
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 94b99c90425a..7c95ed5c5cac 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c | |||
| @@ -130,6 +130,7 @@ static void vc4_close(struct drm_device *dev, struct drm_file *file) | |||
| 130 | struct vc4_file *vc4file = file->driver_priv; | 130 | struct vc4_file *vc4file = file->driver_priv; |
| 131 | 131 | ||
| 132 | vc4_perfmon_close_file(vc4file); | 132 | vc4_perfmon_close_file(vc4file); |
| 133 | kfree(vc4file); | ||
| 133 | } | 134 | } |
| 134 | 135 | ||
| 135 | static const struct vm_operations_struct vc4_vm_ops = { | 136 | static const struct vm_operations_struct vc4_vm_ops = { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 648f8127f65a..3d667e903beb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | |||
| @@ -482,6 +482,8 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, | |||
| 482 | return ret; | 482 | return ret; |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | vps->dmabuf_size = size; | ||
| 486 | |||
| 485 | /* | 487 | /* |
| 486 | * TTM already thinks the buffer is pinned, but make sure the | 488 | * TTM already thinks the buffer is pinned, but make sure the |
| 487 | * pin_count is upped. | 489 | * pin_count is upped. |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index f249a4428458..6ec307c93ece 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -272,7 +272,7 @@ config SENSORS_K8TEMP | |||
| 272 | 272 | ||
| 273 | config SENSORS_K10TEMP | 273 | config SENSORS_K10TEMP |
| 274 | tristate "AMD Family 10h+ temperature sensor" | 274 | tristate "AMD Family 10h+ temperature sensor" |
| 275 | depends on X86 && PCI | 275 | depends on X86 && PCI && AMD_NB |
| 276 | help | 276 | help |
| 277 | If you say yes here you get support for the temperature | 277 | If you say yes here you get support for the temperature |
| 278 | sensor(s) inside your CPU. Supported are later revisions of | 278 | sensor(s) inside your CPU. Supported are later revisions of |
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index d2cc55e21374..3b73dee6fdc6 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
| 26 | #include <asm/amd_nb.h> | ||
| 26 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
| 27 | 28 | ||
| 28 | MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor"); | 29 | MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor"); |
| @@ -40,8 +41,8 @@ static DEFINE_MUTEX(nb_smu_ind_mutex); | |||
| 40 | #define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 | 41 | #define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 |
| 41 | #endif | 42 | #endif |
| 42 | 43 | ||
| 43 | #ifndef PCI_DEVICE_ID_AMD_17H_RR_NB | 44 | #ifndef PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 |
| 44 | #define PCI_DEVICE_ID_AMD_17H_RR_NB 0x15d0 | 45 | #define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 0x15eb |
| 45 | #endif | 46 | #endif |
| 46 | 47 | ||
| 47 | /* CPUID function 0x80000001, ebx */ | 48 | /* CPUID function 0x80000001, ebx */ |
| @@ -63,10 +64,12 @@ static DEFINE_MUTEX(nb_smu_ind_mutex); | |||
| 63 | #define NB_CAP_HTC 0x00000400 | 64 | #define NB_CAP_HTC 0x00000400 |
| 64 | 65 | ||
| 65 | /* | 66 | /* |
| 66 | * For F15h M60h, functionality of REG_REPORTED_TEMPERATURE | 67 | * For F15h M60h and M70h, REG_HARDWARE_THERMAL_CONTROL |
| 67 | * has been moved to D0F0xBC_xD820_0CA4 [Reported Temperature | 68 | * and REG_REPORTED_TEMPERATURE have been moved to |
| 68 | * Control] | 69 | * D0F0xBC_xD820_0C64 [Hardware Temperature Control] |
| 70 | * D0F0xBC_xD820_0CA4 [Reported Temperature Control] | ||
| 69 | */ | 71 | */ |
| 72 | #define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET 0xd8200c64 | ||
| 70 | #define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4 | 73 | #define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4 |
| 71 | 74 | ||
| 72 | /* F17h M01h Access througn SMN */ | 75 | /* F17h M01h Access througn SMN */ |
| @@ -74,6 +77,7 @@ static DEFINE_MUTEX(nb_smu_ind_mutex); | |||
| 74 | 77 | ||
| 75 | struct k10temp_data { | 78 | struct k10temp_data { |
| 76 | struct pci_dev *pdev; | 79 | struct pci_dev *pdev; |
| 80 | void (*read_htcreg)(struct pci_dev *pdev, u32 *regval); | ||
| 77 | void (*read_tempreg)(struct pci_dev *pdev, u32 *regval); | 81 | void (*read_tempreg)(struct pci_dev *pdev, u32 *regval); |
| 78 | int temp_offset; | 82 | int temp_offset; |
| 79 | u32 temp_adjust_mask; | 83 | u32 temp_adjust_mask; |
| @@ -98,6 +102,11 @@ static const struct tctl_offset tctl_offset_table[] = { | |||
| 98 | { 0x17, "AMD Ryzen Threadripper 1910", 10000 }, | 102 | { 0x17, "AMD Ryzen Threadripper 1910", 10000 }, |
| 99 | }; | 103 | }; |
| 100 | 104 | ||
| 105 | static void read_htcreg_pci(struct pci_dev *pdev, u32 *regval) | ||
| 106 | { | ||
| 107 | pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, regval); | ||
| 108 | } | ||
| 109 | |||
| 101 | static void read_tempreg_pci(struct pci_dev *pdev, u32 *regval) | 110 | static void read_tempreg_pci(struct pci_dev *pdev, u32 *regval) |
| 102 | { | 111 | { |
| 103 | pci_read_config_dword(pdev, REG_REPORTED_TEMPERATURE, regval); | 112 | pci_read_config_dword(pdev, REG_REPORTED_TEMPERATURE, regval); |
| @@ -114,6 +123,12 @@ static void amd_nb_index_read(struct pci_dev *pdev, unsigned int devfn, | |||
| 114 | mutex_unlock(&nb_smu_ind_mutex); | 123 | mutex_unlock(&nb_smu_ind_mutex); |
| 115 | } | 124 | } |
| 116 | 125 | ||
| 126 | static void read_htcreg_nb_f15(struct pci_dev *pdev, u32 *regval) | ||
| 127 | { | ||
| 128 | amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8, | ||
| 129 | F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET, regval); | ||
| 130 | } | ||
| 131 | |||
| 117 | static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval) | 132 | static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval) |
| 118 | { | 133 | { |
| 119 | amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8, | 134 | amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8, |
| @@ -122,8 +137,8 @@ static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval) | |||
| 122 | 137 | ||
| 123 | static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval) | 138 | static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval) |
| 124 | { | 139 | { |
| 125 | amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0x60, | 140 | amd_smn_read(amd_pci_dev_to_node_id(pdev), |
| 126 | F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval); | 141 | F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval); |
| 127 | } | 142 | } |
| 128 | 143 | ||
| 129 | static ssize_t temp1_input_show(struct device *dev, | 144 | static ssize_t temp1_input_show(struct device *dev, |
| @@ -160,8 +175,7 @@ static ssize_t show_temp_crit(struct device *dev, | |||
| 160 | u32 regval; | 175 | u32 regval; |
| 161 | int value; | 176 | int value; |
| 162 | 177 | ||
| 163 | pci_read_config_dword(data->pdev, | 178 | data->read_htcreg(data->pdev, ®val); |
| 164 | REG_HARDWARE_THERMAL_CONTROL, ®val); | ||
| 165 | value = ((regval >> 16) & 0x7f) * 500 + 52000; | 179 | value = ((regval >> 16) & 0x7f) * 500 + 52000; |
| 166 | if (show_hyst) | 180 | if (show_hyst) |
| 167 | value -= ((regval >> 24) & 0xf) * 500; | 181 | value -= ((regval >> 24) & 0xf) * 500; |
| @@ -181,13 +195,18 @@ static umode_t k10temp_is_visible(struct kobject *kobj, | |||
| 181 | struct pci_dev *pdev = data->pdev; | 195 | struct pci_dev *pdev = data->pdev; |
| 182 | 196 | ||
| 183 | if (index >= 2) { | 197 | if (index >= 2) { |
| 184 | u32 reg_caps, reg_htc; | 198 | u32 reg; |
| 199 | |||
| 200 | if (!data->read_htcreg) | ||
| 201 | return 0; | ||
| 185 | 202 | ||
| 186 | pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, | 203 | pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, |
| 187 | ®_caps); | 204 | ®); |
| 188 | pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, | 205 | if (!(reg & NB_CAP_HTC)) |
| 189 | ®_htc); | 206 | return 0; |
| 190 | if (!(reg_caps & NB_CAP_HTC) || !(reg_htc & HTC_ENABLE)) | 207 | |
| 208 | data->read_htcreg(data->pdev, ®); | ||
| 209 | if (!(reg & HTC_ENABLE)) | ||
| 191 | return 0; | 210 | return 0; |
| 192 | } | 211 | } |
| 193 | return attr->mode; | 212 | return attr->mode; |
| @@ -268,11 +287,13 @@ static int k10temp_probe(struct pci_dev *pdev, | |||
| 268 | 287 | ||
| 269 | if (boot_cpu_data.x86 == 0x15 && (boot_cpu_data.x86_model == 0x60 || | 288 | if (boot_cpu_data.x86 == 0x15 && (boot_cpu_data.x86_model == 0x60 || |
| 270 | boot_cpu_data.x86_model == 0x70)) { | 289 | boot_cpu_data.x86_model == 0x70)) { |
| 290 | data->read_htcreg = read_htcreg_nb_f15; | ||
| 271 | data->read_tempreg = read_tempreg_nb_f15; | 291 | data->read_tempreg = read_tempreg_nb_f15; |
| 272 | } else if (boot_cpu_data.x86 == 0x17) { | 292 | } else if (boot_cpu_data.x86 == 0x17) { |
| 273 | data->temp_adjust_mask = 0x80000; | 293 | data->temp_adjust_mask = 0x80000; |
| 274 | data->read_tempreg = read_tempreg_nb_f17; | 294 | data->read_tempreg = read_tempreg_nb_f17; |
| 275 | } else { | 295 | } else { |
| 296 | data->read_htcreg = read_htcreg_pci; | ||
| 276 | data->read_tempreg = read_tempreg_pci; | 297 | data->read_tempreg = read_tempreg_pci; |
| 277 | } | 298 | } |
| 278 | 299 | ||
| @@ -302,7 +323,7 @@ static const struct pci_device_id k10temp_id_table[] = { | |||
| 302 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, | 323 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, |
| 303 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, | 324 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, |
| 304 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, | 325 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, |
| 305 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_RR_NB) }, | 326 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) }, |
| 306 | {} | 327 | {} |
| 307 | }; | 328 | }; |
| 308 | MODULE_DEVICE_TABLE(pci, k10temp_id_table); | 329 | MODULE_DEVICE_TABLE(pci, k10temp_id_table); |
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index fd36c39ddf4e..0cdba29ae0a9 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c | |||
| @@ -209,7 +209,10 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) | |||
| 209 | i2c_dw_disable_int(dev); | 209 | i2c_dw_disable_int(dev); |
| 210 | 210 | ||
| 211 | /* Enable the adapter */ | 211 | /* Enable the adapter */ |
| 212 | __i2c_dw_enable_and_wait(dev, true); | 212 | __i2c_dw_enable(dev, true); |
| 213 | |||
| 214 | /* Dummy read to avoid the register getting stuck on Bay Trail */ | ||
| 215 | dw_readl(dev, DW_IC_ENABLE_STATUS); | ||
| 213 | 216 | ||
| 214 | /* Clear and enable interrupts */ | 217 | /* Clear and enable interrupts */ |
| 215 | dw_readl(dev, DW_IC_CLR_INTR); | 218 | dw_readl(dev, DW_IC_CLR_INTR); |
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 2aa0e83174c5..dae8ac618a52 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c | |||
| @@ -564,10 +564,10 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap, | |||
| 564 | * TODO: We could potentially loop and retry in the case | 564 | * TODO: We could potentially loop and retry in the case |
| 565 | * of MSP_TWI_XFER_TIMEOUT. | 565 | * of MSP_TWI_XFER_TIMEOUT. |
| 566 | */ | 566 | */ |
| 567 | return -1; | 567 | return -EIO; |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | return 0; | 570 | return num; |
| 571 | } | 571 | } |
| 572 | 572 | ||
| 573 | static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter) | 573 | static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter) |
diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c index e4be86b3de9a..7235c7302bb7 100644 --- a/drivers/i2c/busses/i2c-viperboard.c +++ b/drivers/i2c/busses/i2c-viperboard.c | |||
| @@ -337,7 +337,7 @@ static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs, | |||
| 337 | } | 337 | } |
| 338 | mutex_unlock(&vb->lock); | 338 | mutex_unlock(&vb->lock); |
| 339 | } | 339 | } |
| 340 | return 0; | 340 | return num; |
| 341 | error: | 341 | error: |
| 342 | mutex_unlock(&vb->lock); | 342 | mutex_unlock(&vb->lock); |
| 343 | return error; | 343 | return error; |
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index a9126b3cda61..7c3b4740b94b 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c | |||
| @@ -445,10 +445,17 @@ static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, | |||
| 445 | msgs[1].buf = buffer; | 445 | msgs[1].buf = buffer; |
| 446 | 446 | ||
| 447 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | 447 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
| 448 | if (ret < 0) | 448 | if (ret < 0) { |
| 449 | dev_err(&client->adapter->dev, "i2c read failed\n"); | 449 | /* Getting a NACK is unfortunately normal with some DSTDs */ |
| 450 | else | 450 | if (ret == -EREMOTEIO) |
| 451 | dev_dbg(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n", | ||
| 452 | data_len, client->addr, cmd, ret); | ||
| 453 | else | ||
| 454 | dev_err(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n", | ||
| 455 | data_len, client->addr, cmd, ret); | ||
| 456 | } else { | ||
| 451 | memcpy(data, buffer, data_len); | 457 | memcpy(data, buffer, data_len); |
| 458 | } | ||
| 452 | 459 | ||
| 453 | kfree(buffer); | 460 | kfree(buffer); |
| 454 | return ret; | 461 | return ret; |
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c index 4e63c6f6c04d..d030ce3025a6 100644 --- a/drivers/md/bcache/debug.c +++ b/drivers/md/bcache/debug.c | |||
| @@ -250,7 +250,9 @@ void bch_debug_exit(void) | |||
| 250 | 250 | ||
| 251 | int __init bch_debug_init(struct kobject *kobj) | 251 | int __init bch_debug_init(struct kobject *kobj) |
| 252 | { | 252 | { |
| 253 | bcache_debug = debugfs_create_dir("bcache", NULL); | 253 | if (!IS_ENABLED(CONFIG_DEBUG_FS)) |
| 254 | return 0; | ||
| 254 | 255 | ||
| 256 | bcache_debug = debugfs_create_dir("bcache", NULL); | ||
| 255 | return IS_ERR_OR_NULL(bcache_debug); | 257 | return IS_ERR_OR_NULL(bcache_debug); |
| 256 | } | 258 | } |
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index a4c9c8297a6d..918d4fb742d1 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h | |||
| @@ -717,6 +717,7 @@ struct cxl { | |||
| 717 | bool perst_select_user; | 717 | bool perst_select_user; |
| 718 | bool perst_same_image; | 718 | bool perst_same_image; |
| 719 | bool psl_timebase_synced; | 719 | bool psl_timebase_synced; |
| 720 | bool tunneled_ops_supported; | ||
| 720 | 721 | ||
| 721 | /* | 722 | /* |
| 722 | * number of contexts mapped on to this card. Possible values are: | 723 | * number of contexts mapped on to this card. Possible values are: |
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 83f1d08058fc..4d6736f9d463 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
| @@ -1742,6 +1742,15 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) | |||
| 1742 | /* Required for devices using CAPP DMA mode, harmless for others */ | 1742 | /* Required for devices using CAPP DMA mode, harmless for others */ |
| 1743 | pci_set_master(dev); | 1743 | pci_set_master(dev); |
| 1744 | 1744 | ||
| 1745 | adapter->tunneled_ops_supported = false; | ||
| 1746 | |||
| 1747 | if (cxl_is_power9()) { | ||
| 1748 | if (pnv_pci_set_tunnel_bar(dev, 0x00020000E0000000ull, 1)) | ||
| 1749 | dev_info(&dev->dev, "Tunneled operations unsupported\n"); | ||
| 1750 | else | ||
| 1751 | adapter->tunneled_ops_supported = true; | ||
| 1752 | } | ||
| 1753 | |||
| 1745 | if ((rc = pnv_phb_to_cxl_mode(dev, adapter->native->sl_ops->capi_mode))) | 1754 | if ((rc = pnv_phb_to_cxl_mode(dev, adapter->native->sl_ops->capi_mode))) |
| 1746 | goto err; | 1755 | goto err; |
| 1747 | 1756 | ||
| @@ -1768,6 +1777,9 @@ static void cxl_deconfigure_adapter(struct cxl *adapter) | |||
| 1768 | { | 1777 | { |
| 1769 | struct pci_dev *pdev = to_pci_dev(adapter->dev.parent); | 1778 | struct pci_dev *pdev = to_pci_dev(adapter->dev.parent); |
| 1770 | 1779 | ||
| 1780 | if (cxl_is_power9()) | ||
| 1781 | pnv_pci_set_tunnel_bar(pdev, 0x00020000E0000000ull, 0); | ||
| 1782 | |||
| 1771 | cxl_native_release_psl_err_irq(adapter); | 1783 | cxl_native_release_psl_err_irq(adapter); |
| 1772 | cxl_unmap_adapter_regs(adapter); | 1784 | cxl_unmap_adapter_regs(adapter); |
| 1773 | 1785 | ||
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 95285b7f636f..4b5a4c5d3c01 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c | |||
| @@ -78,6 +78,15 @@ static ssize_t psl_timebase_synced_show(struct device *device, | |||
| 78 | return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced); | 78 | return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static ssize_t tunneled_ops_supported_show(struct device *device, | ||
| 82 | struct device_attribute *attr, | ||
| 83 | char *buf) | ||
| 84 | { | ||
| 85 | struct cxl *adapter = to_cxl_adapter(device); | ||
| 86 | |||
| 87 | return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->tunneled_ops_supported); | ||
| 88 | } | ||
| 89 | |||
| 81 | static ssize_t reset_adapter_store(struct device *device, | 90 | static ssize_t reset_adapter_store(struct device *device, |
| 82 | struct device_attribute *attr, | 91 | struct device_attribute *attr, |
| 83 | const char *buf, size_t count) | 92 | const char *buf, size_t count) |
| @@ -183,6 +192,7 @@ static struct device_attribute adapter_attrs[] = { | |||
| 183 | __ATTR_RO(base_image), | 192 | __ATTR_RO(base_image), |
| 184 | __ATTR_RO(image_loaded), | 193 | __ATTR_RO(image_loaded), |
| 185 | __ATTR_RO(psl_timebase_synced), | 194 | __ATTR_RO(psl_timebase_synced), |
| 195 | __ATTR_RO(tunneled_ops_supported), | ||
| 186 | __ATTR_RW(load_image_on_perst), | 196 | __ATTR_RW(load_image_on_perst), |
| 187 | __ATTR_RW(perst_reloads_same_image), | 197 | __ATTR_RW(perst_reloads_same_image), |
| 188 | __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), | 198 | __ATTR(reset, S_IWUSR, NULL, reset_adapter_store), |
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 0c125f207aea..33053b0d1fdf 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c | |||
| @@ -518,7 +518,7 @@ static int at24_get_pdata(struct device *dev, struct at24_platform_data *pdata) | |||
| 518 | if (of_node && of_match_device(at24_of_match, dev)) | 518 | if (of_node && of_match_device(at24_of_match, dev)) |
| 519 | cdata = of_device_get_match_data(dev); | 519 | cdata = of_device_get_match_data(dev); |
| 520 | else if (id) | 520 | else if (id) |
| 521 | cdata = (void *)&id->driver_data; | 521 | cdata = (void *)id->driver_data; |
| 522 | else | 522 | else |
| 523 | cdata = acpi_device_get_match_data(dev); | 523 | cdata = acpi_device_get_match_data(dev); |
| 524 | 524 | ||
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index db5ec4e8bde9..ebb1d141b900 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c | |||
| @@ -1194,11 +1194,13 @@ static void marvell_nfc_hw_ecc_bch_read_chunk(struct nand_chip *chip, int chunk, | |||
| 1194 | NDCB0_CMD2(NAND_CMD_READSTART); | 1194 | NDCB0_CMD2(NAND_CMD_READSTART); |
| 1195 | 1195 | ||
| 1196 | /* | 1196 | /* |
| 1197 | * Trigger the naked read operation only on the last chunk. | 1197 | * Trigger the monolithic read on the first chunk, then naked read on |
| 1198 | * Otherwise, use monolithic read. | 1198 | * intermediate chunks and finally a last naked read on the last chunk. |
| 1199 | */ | 1199 | */ |
| 1200 | if (lt->nchunks == 1 || (chunk < lt->nchunks - 1)) | 1200 | if (chunk == 0) |
| 1201 | nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_MONOLITHIC_RW); | 1201 | nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_MONOLITHIC_RW); |
| 1202 | else if (chunk < lt->nchunks - 1) | ||
| 1203 | nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_NAKED_RW); | ||
| 1202 | else | 1204 | else |
| 1203 | nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_LAST_NAKED_RW); | 1205 | nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_LAST_NAKED_RW); |
| 1204 | 1206 | ||
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index bc309c5327ff..566644bb496a 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -168,8 +168,8 @@ config DELL_WMI | |||
| 168 | depends on DMI | 168 | depends on DMI |
| 169 | depends on INPUT | 169 | depends on INPUT |
| 170 | depends on ACPI_VIDEO || ACPI_VIDEO = n | 170 | depends on ACPI_VIDEO || ACPI_VIDEO = n |
| 171 | depends on DELL_SMBIOS | ||
| 171 | select DELL_WMI_DESCRIPTOR | 172 | select DELL_WMI_DESCRIPTOR |
| 172 | select DELL_SMBIOS | ||
| 173 | select INPUT_SPARSEKMAP | 173 | select INPUT_SPARSEKMAP |
| 174 | ---help--- | 174 | ---help--- |
| 175 | Say Y here if you want to support WMI-based hotkeys on Dell laptops. | 175 | Say Y here if you want to support WMI-based hotkeys on Dell laptops. |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 439991d71b14..4c14ce428e92 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
| @@ -141,7 +141,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) | |||
| 141 | int i; | 141 | int i; |
| 142 | 142 | ||
| 143 | for (i = 0; i < nr_queues; i++) { | 143 | for (i = 0; i < nr_queues; i++) { |
| 144 | q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); | 144 | q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL); |
| 145 | if (!q) | 145 | if (!q) |
| 146 | return -ENOMEM; | 146 | return -ENOMEM; |
| 147 | 147 | ||
| @@ -456,7 +456,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) | |||
| 456 | { | 456 | { |
| 457 | struct ciw *ciw; | 457 | struct ciw *ciw; |
| 458 | struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; | 458 | struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; |
| 459 | int rc; | ||
| 460 | 459 | ||
| 461 | memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); | 460 | memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); |
| 462 | memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); | 461 | memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); |
| @@ -493,16 +492,14 @@ int qdio_setup_irq(struct qdio_initialize *init_data) | |||
| 493 | ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); | 492 | ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); |
| 494 | if (!ciw) { | 493 | if (!ciw) { |
| 495 | DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); | 494 | DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); |
| 496 | rc = -EINVAL; | 495 | return -EINVAL; |
| 497 | goto out_err; | ||
| 498 | } | 496 | } |
| 499 | irq_ptr->equeue = *ciw; | 497 | irq_ptr->equeue = *ciw; |
| 500 | 498 | ||
| 501 | ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); | 499 | ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); |
| 502 | if (!ciw) { | 500 | if (!ciw) { |
| 503 | DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); | 501 | DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); |
| 504 | rc = -EINVAL; | 502 | return -EINVAL; |
| 505 | goto out_err; | ||
| 506 | } | 503 | } |
| 507 | irq_ptr->aqueue = *ciw; | 504 | irq_ptr->aqueue = *ciw; |
| 508 | 505 | ||
| @@ -512,9 +509,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) | |||
| 512 | init_data->cdev->handler = qdio_int_handler; | 509 | init_data->cdev->handler = qdio_int_handler; |
| 513 | spin_unlock_irq(get_ccwdev_lock(irq_ptr->cdev)); | 510 | spin_unlock_irq(get_ccwdev_lock(irq_ptr->cdev)); |
| 514 | return 0; | 511 | return 0; |
| 515 | out_err: | ||
| 516 | qdio_release_memory(irq_ptr); | ||
| 517 | return rc; | ||
| 518 | } | 512 | } |
| 519 | 513 | ||
| 520 | void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, | 514 | void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, |
diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index 2c7550797ec2..dce92b2a895d 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c | |||
| @@ -715,6 +715,10 @@ void cp_free(struct channel_program *cp) | |||
| 715 | * and stores the result to ccwchain list. @cp must have been | 715 | * and stores the result to ccwchain list. @cp must have been |
| 716 | * initialized by a previous call with cp_init(). Otherwise, undefined | 716 | * initialized by a previous call with cp_init(). Otherwise, undefined |
| 717 | * behavior occurs. | 717 | * behavior occurs. |
| 718 | * For each chain composing the channel program: | ||
| 719 | * - On entry ch_len holds the count of CCWs to be translated. | ||
| 720 | * - On exit ch_len is adjusted to the count of successfully translated CCWs. | ||
| 721 | * This allows cp_free to find in ch_len the count of CCWs to free in a chain. | ||
| 718 | * | 722 | * |
| 719 | * The S/390 CCW Translation APIS (prefixed by 'cp_') are introduced | 723 | * The S/390 CCW Translation APIS (prefixed by 'cp_') are introduced |
| 720 | * as helpers to do ccw chain translation inside the kernel. Basically | 724 | * as helpers to do ccw chain translation inside the kernel. Basically |
| @@ -749,11 +753,18 @@ int cp_prefetch(struct channel_program *cp) | |||
| 749 | for (idx = 0; idx < len; idx++) { | 753 | for (idx = 0; idx < len; idx++) { |
| 750 | ret = ccwchain_fetch_one(chain, idx, cp); | 754 | ret = ccwchain_fetch_one(chain, idx, cp); |
| 751 | if (ret) | 755 | if (ret) |
| 752 | return ret; | 756 | goto out_err; |
| 753 | } | 757 | } |
| 754 | } | 758 | } |
| 755 | 759 | ||
| 756 | return 0; | 760 | return 0; |
| 761 | out_err: | ||
| 762 | /* Only cleanup the chain elements that were actually translated. */ | ||
| 763 | chain->ch_len = idx; | ||
| 764 | list_for_each_entry_continue(chain, &cp->ccwchain_list, next) { | ||
| 765 | chain->ch_len = 0; | ||
| 766 | } | ||
| 767 | return ret; | ||
| 757 | } | 768 | } |
| 758 | 769 | ||
| 759 | /** | 770 | /** |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 0156c9623c35..d62ddd63f4fe 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
| @@ -724,6 +724,8 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, | |||
| 724 | int wait; | 724 | int wait; |
| 725 | unsigned long flags = 0; | 725 | unsigned long flags = 0; |
| 726 | unsigned long mflags = 0; | 726 | unsigned long mflags = 0; |
| 727 | struct aac_hba_cmd_req *hbacmd = (struct aac_hba_cmd_req *) | ||
| 728 | fibptr->hw_fib_va; | ||
| 727 | 729 | ||
| 728 | fibptr->flags = (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA); | 730 | fibptr->flags = (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA); |
| 729 | if (callback) { | 731 | if (callback) { |
| @@ -734,11 +736,9 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback, | |||
| 734 | wait = 1; | 736 | wait = 1; |
| 735 | 737 | ||
| 736 | 738 | ||
| 737 | if (command == HBA_IU_TYPE_SCSI_CMD_REQ) { | 739 | hbacmd->iu_type = command; |
| 738 | struct aac_hba_cmd_req *hbacmd = | ||
| 739 | (struct aac_hba_cmd_req *)fibptr->hw_fib_va; | ||
| 740 | 740 | ||
| 741 | hbacmd->iu_type = command; | 741 | if (command == HBA_IU_TYPE_SCSI_CMD_REQ) { |
| 742 | /* bit1 of request_id must be 0 */ | 742 | /* bit1 of request_id must be 0 */ |
| 743 | hbacmd->request_id = | 743 | hbacmd->request_id = |
| 744 | cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1); | 744 | cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1); |
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index c374e3b5c678..777e5f1e52d1 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c | |||
| @@ -609,7 +609,7 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter, | |||
| 609 | break; | 609 | break; |
| 610 | 610 | ||
| 611 | case BTSTAT_ABORTQUEUE: | 611 | case BTSTAT_ABORTQUEUE: |
| 612 | cmd->result = (DID_ABORT << 16); | 612 | cmd->result = (DID_BUS_BUSY << 16); |
| 613 | break; | 613 | break; |
| 614 | 614 | ||
| 615 | case BTSTAT_SCSIPARITY: | 615 | case BTSTAT_SCSIPARITY: |
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 1596d35498c5..6573152ce893 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c | |||
| @@ -490,7 +490,7 @@ static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi, | |||
| 490 | 490 | ||
| 491 | static void bcm_qspi_enable_bspi(struct bcm_qspi *qspi) | 491 | static void bcm_qspi_enable_bspi(struct bcm_qspi *qspi) |
| 492 | { | 492 | { |
| 493 | if (!has_bspi(qspi) || (qspi->bspi_enabled)) | 493 | if (!has_bspi(qspi)) |
| 494 | return; | 494 | return; |
| 495 | 495 | ||
| 496 | qspi->bspi_enabled = 1; | 496 | qspi->bspi_enabled = 1; |
| @@ -505,7 +505,7 @@ static void bcm_qspi_enable_bspi(struct bcm_qspi *qspi) | |||
| 505 | 505 | ||
| 506 | static void bcm_qspi_disable_bspi(struct bcm_qspi *qspi) | 506 | static void bcm_qspi_disable_bspi(struct bcm_qspi *qspi) |
| 507 | { | 507 | { |
| 508 | if (!has_bspi(qspi) || (!qspi->bspi_enabled)) | 508 | if (!has_bspi(qspi)) |
| 509 | return; | 509 | return; |
| 510 | 510 | ||
| 511 | qspi->bspi_enabled = 0; | 511 | qspi->bspi_enabled = 0; |
| @@ -519,16 +519,19 @@ static void bcm_qspi_disable_bspi(struct bcm_qspi *qspi) | |||
| 519 | 519 | ||
| 520 | static void bcm_qspi_chip_select(struct bcm_qspi *qspi, int cs) | 520 | static void bcm_qspi_chip_select(struct bcm_qspi *qspi, int cs) |
| 521 | { | 521 | { |
| 522 | u32 data = 0; | 522 | u32 rd = 0; |
| 523 | u32 wr = 0; | ||
| 523 | 524 | ||
| 524 | if (qspi->curr_cs == cs) | ||
| 525 | return; | ||
| 526 | if (qspi->base[CHIP_SELECT]) { | 525 | if (qspi->base[CHIP_SELECT]) { |
| 527 | data = bcm_qspi_read(qspi, CHIP_SELECT, 0); | 526 | rd = bcm_qspi_read(qspi, CHIP_SELECT, 0); |
| 528 | data = (data & ~0xff) | (1 << cs); | 527 | wr = (rd & ~0xff) | (1 << cs); |
| 529 | bcm_qspi_write(qspi, CHIP_SELECT, 0, data); | 528 | if (rd == wr) |
| 529 | return; | ||
| 530 | bcm_qspi_write(qspi, CHIP_SELECT, 0, wr); | ||
| 530 | usleep_range(10, 20); | 531 | usleep_range(10, 20); |
| 531 | } | 532 | } |
| 533 | |||
| 534 | dev_dbg(&qspi->pdev->dev, "using cs:%d\n", cs); | ||
| 532 | qspi->curr_cs = cs; | 535 | qspi->curr_cs = cs; |
| 533 | } | 536 | } |
| 534 | 537 | ||
| @@ -755,8 +758,13 @@ static int write_to_hw(struct bcm_qspi *qspi, struct spi_device *spi) | |||
| 755 | dev_dbg(&qspi->pdev->dev, "WR %04x\n", val); | 758 | dev_dbg(&qspi->pdev->dev, "WR %04x\n", val); |
| 756 | } | 759 | } |
| 757 | mspi_cdram = MSPI_CDRAM_CONT_BIT; | 760 | mspi_cdram = MSPI_CDRAM_CONT_BIT; |
| 758 | mspi_cdram |= (~(1 << spi->chip_select) & | 761 | |
| 759 | MSPI_CDRAM_PCS); | 762 | if (has_bspi(qspi)) |
| 763 | mspi_cdram &= ~1; | ||
| 764 | else | ||
| 765 | mspi_cdram |= (~(1 << spi->chip_select) & | ||
| 766 | MSPI_CDRAM_PCS); | ||
| 767 | |||
| 760 | mspi_cdram |= ((tp.trans->bits_per_word <= 8) ? 0 : | 768 | mspi_cdram |= ((tp.trans->bits_per_word <= 8) ? 0 : |
| 761 | MSPI_CDRAM_BITSE_BIT); | 769 | MSPI_CDRAM_BITSE_BIT); |
| 762 | 770 | ||
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 1431cb98fe40..3094d818cf06 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c | |||
| @@ -184,6 +184,11 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) | |||
| 184 | struct bcm2835aux_spi *bs = spi_master_get_devdata(master); | 184 | struct bcm2835aux_spi *bs = spi_master_get_devdata(master); |
| 185 | irqreturn_t ret = IRQ_NONE; | 185 | irqreturn_t ret = IRQ_NONE; |
| 186 | 186 | ||
| 187 | /* IRQ may be shared, so return if our interrupts are disabled */ | ||
| 188 | if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) & | ||
| 189 | (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE))) | ||
| 190 | return ret; | ||
| 191 | |||
| 187 | /* check if we have data to read */ | 192 | /* check if we have data to read */ |
| 188 | while (bs->rx_len && | 193 | while (bs->rx_len && |
| 189 | (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & | 194 | (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & |
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 5c9516ae4942..4a001634023e 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c | |||
| @@ -313,6 +313,14 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) | |||
| 313 | 313 | ||
| 314 | while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) && | 314 | while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) && |
| 315 | (xspi->tx_bytes > 0)) { | 315 | (xspi->tx_bytes > 0)) { |
| 316 | |||
| 317 | /* When xspi in busy condition, bytes may send failed, | ||
| 318 | * then spi control did't work thoroughly, add one byte delay | ||
| 319 | */ | ||
| 320 | if (cdns_spi_read(xspi, CDNS_SPI_ISR) & | ||
| 321 | CDNS_SPI_IXR_TXFULL) | ||
| 322 | usleep_range(10, 20); | ||
| 323 | |||
| 316 | if (xspi->txbuf) | 324 | if (xspi->txbuf) |
| 317 | cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); | 325 | cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); |
| 318 | else | 326 | else |
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 6f57592a7f95..a056ee88a960 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
| @@ -1701,7 +1701,7 @@ static struct platform_driver spi_imx_driver = { | |||
| 1701 | }; | 1701 | }; |
| 1702 | module_platform_driver(spi_imx_driver); | 1702 | module_platform_driver(spi_imx_driver); |
| 1703 | 1703 | ||
| 1704 | MODULE_DESCRIPTION("SPI Master Controller driver"); | 1704 | MODULE_DESCRIPTION("SPI Controller driver"); |
| 1705 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); | 1705 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); |
| 1706 | MODULE_LICENSE("GPL"); | 1706 | MODULE_LICENSE("GPL"); |
| 1707 | MODULE_ALIAS("platform:" DRIVER_NAME); | 1707 | MODULE_ALIAS("platform:" DRIVER_NAME); |
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 513ec6c6e25b..0ae7defd3492 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h | |||
| @@ -38,7 +38,7 @@ struct driver_data { | |||
| 38 | 38 | ||
| 39 | /* SSP register addresses */ | 39 | /* SSP register addresses */ |
| 40 | void __iomem *ioaddr; | 40 | void __iomem *ioaddr; |
| 41 | u32 ssdr_physical; | 41 | phys_addr_t ssdr_physical; |
| 42 | 42 | ||
| 43 | /* SSP masks*/ | 43 | /* SSP masks*/ |
| 44 | u32 dma_cr1; | 44 | u32 dma_cr1; |
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index ae086aab57d5..8171eedbfc90 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c | |||
| @@ -283,6 +283,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, | |||
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_div_table) - 1); | 285 | k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_div_table) - 1); |
| 286 | brps = min_t(int, brps, 32); | ||
| 286 | 287 | ||
| 287 | scr = sh_msiof_spi_div_table[k].brdv | SCR_BRPS(brps); | 288 | scr = sh_msiof_spi_div_table[k].brdv | SCR_BRPS(brps); |
| 288 | sh_msiof_write(p, TSCR, scr); | 289 | sh_msiof_write(p, TSCR, scr); |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 72ebbc908e19..32cd52ca8318 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
| @@ -354,7 +354,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, | |||
| 354 | 354 | ||
| 355 | slot_id = 0; | 355 | slot_id = 0; |
| 356 | for (i = 0; i < MAX_HC_SLOTS; i++) { | 356 | for (i = 0; i < MAX_HC_SLOTS; i++) { |
| 357 | if (!xhci->devs[i]) | 357 | if (!xhci->devs[i] || !xhci->devs[i]->udev) |
| 358 | continue; | 358 | continue; |
| 359 | speed = xhci->devs[i]->udev->speed; | 359 | speed = xhci->devs[i]->udev->speed; |
| 360 | if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3)) | 360 | if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3)) |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index e7f99d55922a..15a42cee0a9c 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
| @@ -2524,8 +2524,11 @@ static int musb_bus_suspend(struct usb_hcd *hcd) | |||
| 2524 | { | 2524 | { |
| 2525 | struct musb *musb = hcd_to_musb(hcd); | 2525 | struct musb *musb = hcd_to_musb(hcd); |
| 2526 | u8 devctl; | 2526 | u8 devctl; |
| 2527 | int ret; | ||
| 2527 | 2528 | ||
| 2528 | musb_port_suspend(musb, true); | 2529 | ret = musb_port_suspend(musb, true); |
| 2530 | if (ret) | ||
| 2531 | return ret; | ||
| 2529 | 2532 | ||
| 2530 | if (!is_host_active(musb)) | 2533 | if (!is_host_active(musb)) |
| 2531 | return 0; | 2534 | return 0; |
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 72392bbcd0a4..2999845632ce 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h | |||
| @@ -67,7 +67,7 @@ extern void musb_host_rx(struct musb *, u8); | |||
| 67 | extern void musb_root_disconnect(struct musb *musb); | 67 | extern void musb_root_disconnect(struct musb *musb); |
| 68 | extern void musb_host_resume_root_hub(struct musb *musb); | 68 | extern void musb_host_resume_root_hub(struct musb *musb); |
| 69 | extern void musb_host_poke_root_hub(struct musb *musb); | 69 | extern void musb_host_poke_root_hub(struct musb *musb); |
| 70 | extern void musb_port_suspend(struct musb *musb, bool do_suspend); | 70 | extern int musb_port_suspend(struct musb *musb, bool do_suspend); |
| 71 | extern void musb_port_reset(struct musb *musb, bool do_reset); | 71 | extern void musb_port_reset(struct musb *musb, bool do_reset); |
| 72 | extern void musb_host_finish_resume(struct work_struct *work); | 72 | extern void musb_host_finish_resume(struct work_struct *work); |
| 73 | #else | 73 | #else |
| @@ -99,7 +99,10 @@ static inline void musb_root_disconnect(struct musb *musb) {} | |||
| 99 | static inline void musb_host_resume_root_hub(struct musb *musb) {} | 99 | static inline void musb_host_resume_root_hub(struct musb *musb) {} |
| 100 | static inline void musb_host_poll_rh_status(struct musb *musb) {} | 100 | static inline void musb_host_poll_rh_status(struct musb *musb) {} |
| 101 | static inline void musb_host_poke_root_hub(struct musb *musb) {} | 101 | static inline void musb_host_poke_root_hub(struct musb *musb) {} |
| 102 | static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {} | 102 | static inline int musb_port_suspend(struct musb *musb, bool do_suspend) |
| 103 | { | ||
| 104 | return 0; | ||
| 105 | } | ||
| 103 | static inline void musb_port_reset(struct musb *musb, bool do_reset) {} | 106 | static inline void musb_port_reset(struct musb *musb, bool do_reset) {} |
| 104 | static inline void musb_host_finish_resume(struct work_struct *work) {} | 107 | static inline void musb_host_finish_resume(struct work_struct *work) {} |
| 105 | #endif | 108 | #endif |
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 5165d2b07ade..2f8dd9826e94 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
| @@ -48,14 +48,14 @@ void musb_host_finish_resume(struct work_struct *work) | |||
| 48 | spin_unlock_irqrestore(&musb->lock, flags); | 48 | spin_unlock_irqrestore(&musb->lock, flags); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | void musb_port_suspend(struct musb *musb, bool do_suspend) | 51 | int musb_port_suspend(struct musb *musb, bool do_suspend) |
| 52 | { | 52 | { |
| 53 | struct usb_otg *otg = musb->xceiv->otg; | 53 | struct usb_otg *otg = musb->xceiv->otg; |
| 54 | u8 power; | 54 | u8 power; |
| 55 | void __iomem *mbase = musb->mregs; | 55 | void __iomem *mbase = musb->mregs; |
| 56 | 56 | ||
| 57 | if (!is_host_active(musb)) | 57 | if (!is_host_active(musb)) |
| 58 | return; | 58 | return 0; |
| 59 | 59 | ||
| 60 | /* NOTE: this doesn't necessarily put PHY into low power mode, | 60 | /* NOTE: this doesn't necessarily put PHY into low power mode, |
| 61 | * turning off its clock; that's a function of PHY integration and | 61 | * turning off its clock; that's a function of PHY integration and |
| @@ -66,16 +66,20 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) | |||
| 66 | if (do_suspend) { | 66 | if (do_suspend) { |
| 67 | int retries = 10000; | 67 | int retries = 10000; |
| 68 | 68 | ||
| 69 | power &= ~MUSB_POWER_RESUME; | 69 | if (power & MUSB_POWER_RESUME) |
| 70 | power |= MUSB_POWER_SUSPENDM; | 70 | return -EBUSY; |
| 71 | musb_writeb(mbase, MUSB_POWER, power); | ||
| 72 | 71 | ||
| 73 | /* Needed for OPT A tests */ | 72 | if (!(power & MUSB_POWER_SUSPENDM)) { |
| 74 | power = musb_readb(mbase, MUSB_POWER); | 73 | power |= MUSB_POWER_SUSPENDM; |
| 75 | while (power & MUSB_POWER_SUSPENDM) { | 74 | musb_writeb(mbase, MUSB_POWER, power); |
| 75 | |||
| 76 | /* Needed for OPT A tests */ | ||
| 76 | power = musb_readb(mbase, MUSB_POWER); | 77 | power = musb_readb(mbase, MUSB_POWER); |
| 77 | if (retries-- < 1) | 78 | while (power & MUSB_POWER_SUSPENDM) { |
| 78 | break; | 79 | power = musb_readb(mbase, MUSB_POWER); |
| 80 | if (retries-- < 1) | ||
| 81 | break; | ||
| 82 | } | ||
| 79 | } | 83 | } |
| 80 | 84 | ||
| 81 | musb_dbg(musb, "Root port suspended, power %02x", power); | 85 | musb_dbg(musb, "Root port suspended, power %02x", power); |
| @@ -111,6 +115,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) | |||
| 111 | schedule_delayed_work(&musb->finish_resume_work, | 115 | schedule_delayed_work(&musb->finish_resume_work, |
| 112 | msecs_to_jiffies(USB_RESUME_TIMEOUT)); | 116 | msecs_to_jiffies(USB_RESUME_TIMEOUT)); |
| 113 | } | 117 | } |
| 118 | return 0; | ||
| 114 | } | 119 | } |
| 115 | 120 | ||
| 116 | void musb_port_reset(struct musb *musb, bool do_reset) | 121 | void musb_port_reset(struct musb *musb, bool do_reset) |
diff --git a/drivers/usb/usbip/stub.h b/drivers/usb/usbip/stub.h index 14a72357800a..35618ceb2791 100644 --- a/drivers/usb/usbip/stub.h +++ b/drivers/usb/usbip/stub.h | |||
| @@ -73,6 +73,7 @@ struct bus_id_priv { | |||
| 73 | struct stub_device *sdev; | 73 | struct stub_device *sdev; |
| 74 | struct usb_device *udev; | 74 | struct usb_device *udev; |
| 75 | char shutdown_busid; | 75 | char shutdown_busid; |
| 76 | spinlock_t busid_lock; | ||
| 76 | }; | 77 | }; |
| 77 | 78 | ||
| 78 | /* stub_priv is allocated from stub_priv_cache */ | 79 | /* stub_priv is allocated from stub_priv_cache */ |
| @@ -83,6 +84,7 @@ extern struct usb_device_driver stub_driver; | |||
| 83 | 84 | ||
| 84 | /* stub_main.c */ | 85 | /* stub_main.c */ |
| 85 | struct bus_id_priv *get_busid_priv(const char *busid); | 86 | struct bus_id_priv *get_busid_priv(const char *busid); |
| 87 | void put_busid_priv(struct bus_id_priv *bid); | ||
| 86 | int del_match_busid(char *busid); | 88 | int del_match_busid(char *busid); |
| 87 | void stub_device_cleanup_urbs(struct stub_device *sdev); | 89 | void stub_device_cleanup_urbs(struct stub_device *sdev); |
| 88 | 90 | ||
diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index dd8ef36ab10e..c0d6ff1baa72 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c | |||
| @@ -300,9 +300,9 @@ static int stub_probe(struct usb_device *udev) | |||
| 300 | struct stub_device *sdev = NULL; | 300 | struct stub_device *sdev = NULL; |
| 301 | const char *udev_busid = dev_name(&udev->dev); | 301 | const char *udev_busid = dev_name(&udev->dev); |
| 302 | struct bus_id_priv *busid_priv; | 302 | struct bus_id_priv *busid_priv; |
| 303 | int rc; | 303 | int rc = 0; |
| 304 | 304 | ||
| 305 | dev_dbg(&udev->dev, "Enter\n"); | 305 | dev_dbg(&udev->dev, "Enter probe\n"); |
| 306 | 306 | ||
| 307 | /* check we should claim or not by busid_table */ | 307 | /* check we should claim or not by busid_table */ |
| 308 | busid_priv = get_busid_priv(udev_busid); | 308 | busid_priv = get_busid_priv(udev_busid); |
| @@ -317,13 +317,15 @@ static int stub_probe(struct usb_device *udev) | |||
| 317 | * other matched drivers by the driver core. | 317 | * other matched drivers by the driver core. |
| 318 | * See driver_probe_device() in driver/base/dd.c | 318 | * See driver_probe_device() in driver/base/dd.c |
| 319 | */ | 319 | */ |
| 320 | return -ENODEV; | 320 | rc = -ENODEV; |
| 321 | goto call_put_busid_priv; | ||
| 321 | } | 322 | } |
| 322 | 323 | ||
| 323 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { | 324 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { |
| 324 | dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n", | 325 | dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n", |
| 325 | udev_busid); | 326 | udev_busid); |
| 326 | return -ENODEV; | 327 | rc = -ENODEV; |
| 328 | goto call_put_busid_priv; | ||
| 327 | } | 329 | } |
| 328 | 330 | ||
| 329 | if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { | 331 | if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { |
| @@ -331,13 +333,16 @@ static int stub_probe(struct usb_device *udev) | |||
| 331 | "%s is attached on vhci_hcd... skip!\n", | 333 | "%s is attached on vhci_hcd... skip!\n", |
| 332 | udev_busid); | 334 | udev_busid); |
| 333 | 335 | ||
| 334 | return -ENODEV; | 336 | rc = -ENODEV; |
| 337 | goto call_put_busid_priv; | ||
| 335 | } | 338 | } |
| 336 | 339 | ||
| 337 | /* ok, this is my device */ | 340 | /* ok, this is my device */ |
| 338 | sdev = stub_device_alloc(udev); | 341 | sdev = stub_device_alloc(udev); |
| 339 | if (!sdev) | 342 | if (!sdev) { |
| 340 | return -ENOMEM; | 343 | rc = -ENOMEM; |
| 344 | goto call_put_busid_priv; | ||
| 345 | } | ||
| 341 | 346 | ||
| 342 | dev_info(&udev->dev, | 347 | dev_info(&udev->dev, |
| 343 | "usbip-host: register new device (bus %u dev %u)\n", | 348 | "usbip-host: register new device (bus %u dev %u)\n", |
| @@ -369,7 +374,9 @@ static int stub_probe(struct usb_device *udev) | |||
| 369 | } | 374 | } |
| 370 | busid_priv->status = STUB_BUSID_ALLOC; | 375 | busid_priv->status = STUB_BUSID_ALLOC; |
| 371 | 376 | ||
| 372 | return 0; | 377 | rc = 0; |
| 378 | goto call_put_busid_priv; | ||
| 379 | |||
| 373 | err_files: | 380 | err_files: |
| 374 | usb_hub_release_port(udev->parent, udev->portnum, | 381 | usb_hub_release_port(udev->parent, udev->portnum, |
| 375 | (struct usb_dev_state *) udev); | 382 | (struct usb_dev_state *) udev); |
| @@ -379,6 +386,9 @@ err_port: | |||
| 379 | 386 | ||
| 380 | busid_priv->sdev = NULL; | 387 | busid_priv->sdev = NULL; |
| 381 | stub_device_free(sdev); | 388 | stub_device_free(sdev); |
| 389 | |||
| 390 | call_put_busid_priv: | ||
| 391 | put_busid_priv(busid_priv); | ||
| 382 | return rc; | 392 | return rc; |
| 383 | } | 393 | } |
| 384 | 394 | ||
| @@ -404,7 +414,7 @@ static void stub_disconnect(struct usb_device *udev) | |||
| 404 | struct bus_id_priv *busid_priv; | 414 | struct bus_id_priv *busid_priv; |
| 405 | int rc; | 415 | int rc; |
| 406 | 416 | ||
| 407 | dev_dbg(&udev->dev, "Enter\n"); | 417 | dev_dbg(&udev->dev, "Enter disconnect\n"); |
| 408 | 418 | ||
| 409 | busid_priv = get_busid_priv(udev_busid); | 419 | busid_priv = get_busid_priv(udev_busid); |
| 410 | if (!busid_priv) { | 420 | if (!busid_priv) { |
| @@ -417,7 +427,7 @@ static void stub_disconnect(struct usb_device *udev) | |||
| 417 | /* get stub_device */ | 427 | /* get stub_device */ |
| 418 | if (!sdev) { | 428 | if (!sdev) { |
| 419 | dev_err(&udev->dev, "could not get device"); | 429 | dev_err(&udev->dev, "could not get device"); |
| 420 | return; | 430 | goto call_put_busid_priv; |
| 421 | } | 431 | } |
| 422 | 432 | ||
| 423 | dev_set_drvdata(&udev->dev, NULL); | 433 | dev_set_drvdata(&udev->dev, NULL); |
| @@ -432,12 +442,12 @@ static void stub_disconnect(struct usb_device *udev) | |||
| 432 | (struct usb_dev_state *) udev); | 442 | (struct usb_dev_state *) udev); |
| 433 | if (rc) { | 443 | if (rc) { |
| 434 | dev_dbg(&udev->dev, "unable to release port\n"); | 444 | dev_dbg(&udev->dev, "unable to release port\n"); |
| 435 | return; | 445 | goto call_put_busid_priv; |
| 436 | } | 446 | } |
| 437 | 447 | ||
| 438 | /* If usb reset is called from event handler */ | 448 | /* If usb reset is called from event handler */ |
| 439 | if (usbip_in_eh(current)) | 449 | if (usbip_in_eh(current)) |
| 440 | return; | 450 | goto call_put_busid_priv; |
| 441 | 451 | ||
| 442 | /* shutdown the current connection */ | 452 | /* shutdown the current connection */ |
| 443 | shutdown_busid(busid_priv); | 453 | shutdown_busid(busid_priv); |
| @@ -448,12 +458,11 @@ static void stub_disconnect(struct usb_device *udev) | |||
| 448 | busid_priv->sdev = NULL; | 458 | busid_priv->sdev = NULL; |
| 449 | stub_device_free(sdev); | 459 | stub_device_free(sdev); |
| 450 | 460 | ||
| 451 | if (busid_priv->status == STUB_BUSID_ALLOC) { | 461 | if (busid_priv->status == STUB_BUSID_ALLOC) |
| 452 | busid_priv->status = STUB_BUSID_ADDED; | 462 | busid_priv->status = STUB_BUSID_ADDED; |
| 453 | } else { | 463 | |
| 454 | busid_priv->status = STUB_BUSID_OTHER; | 464 | call_put_busid_priv: |
| 455 | del_match_busid((char *)udev_busid); | 465 | put_busid_priv(busid_priv); |
| 456 | } | ||
| 457 | } | 466 | } |
| 458 | 467 | ||
| 459 | #ifdef CONFIG_PM | 468 | #ifdef CONFIG_PM |
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c index d41d0cdeec0f..bf8a5feb0ee9 100644 --- a/drivers/usb/usbip/stub_main.c +++ b/drivers/usb/usbip/stub_main.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #define DRIVER_DESC "USB/IP Host Driver" | 14 | #define DRIVER_DESC "USB/IP Host Driver" |
| 15 | 15 | ||
| 16 | struct kmem_cache *stub_priv_cache; | 16 | struct kmem_cache *stub_priv_cache; |
| 17 | |||
| 17 | /* | 18 | /* |
| 18 | * busid_tables defines matching busids that usbip can grab. A user can change | 19 | * busid_tables defines matching busids that usbip can grab. A user can change |
| 19 | * dynamically what device is locally used and what device is exported to a | 20 | * dynamically what device is locally used and what device is exported to a |
| @@ -25,6 +26,8 @@ static spinlock_t busid_table_lock; | |||
| 25 | 26 | ||
| 26 | static void init_busid_table(void) | 27 | static void init_busid_table(void) |
| 27 | { | 28 | { |
| 29 | int i; | ||
| 30 | |||
| 28 | /* | 31 | /* |
| 29 | * This also sets the bus_table[i].status to | 32 | * This also sets the bus_table[i].status to |
| 30 | * STUB_BUSID_OTHER, which is 0. | 33 | * STUB_BUSID_OTHER, which is 0. |
| @@ -32,6 +35,9 @@ static void init_busid_table(void) | |||
| 32 | memset(busid_table, 0, sizeof(busid_table)); | 35 | memset(busid_table, 0, sizeof(busid_table)); |
| 33 | 36 | ||
| 34 | spin_lock_init(&busid_table_lock); | 37 | spin_lock_init(&busid_table_lock); |
| 38 | |||
| 39 | for (i = 0; i < MAX_BUSID; i++) | ||
| 40 | spin_lock_init(&busid_table[i].busid_lock); | ||
| 35 | } | 41 | } |
| 36 | 42 | ||
| 37 | /* | 43 | /* |
| @@ -43,15 +49,20 @@ static int get_busid_idx(const char *busid) | |||
| 43 | int i; | 49 | int i; |
| 44 | int idx = -1; | 50 | int idx = -1; |
| 45 | 51 | ||
| 46 | for (i = 0; i < MAX_BUSID; i++) | 52 | for (i = 0; i < MAX_BUSID; i++) { |
| 53 | spin_lock(&busid_table[i].busid_lock); | ||
| 47 | if (busid_table[i].name[0]) | 54 | if (busid_table[i].name[0]) |
| 48 | if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) { | 55 | if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) { |
| 49 | idx = i; | 56 | idx = i; |
| 57 | spin_unlock(&busid_table[i].busid_lock); | ||
| 50 | break; | 58 | break; |
| 51 | } | 59 | } |
| 60 | spin_unlock(&busid_table[i].busid_lock); | ||
| 61 | } | ||
| 52 | return idx; | 62 | return idx; |
| 53 | } | 63 | } |
| 54 | 64 | ||
| 65 | /* Returns holding busid_lock. Should call put_busid_priv() to unlock */ | ||
| 55 | struct bus_id_priv *get_busid_priv(const char *busid) | 66 | struct bus_id_priv *get_busid_priv(const char *busid) |
| 56 | { | 67 | { |
| 57 | int idx; | 68 | int idx; |
| @@ -59,13 +70,22 @@ struct bus_id_priv *get_busid_priv(const char *busid) | |||
| 59 | 70 | ||
| 60 | spin_lock(&busid_table_lock); | 71 | spin_lock(&busid_table_lock); |
| 61 | idx = get_busid_idx(busid); | 72 | idx = get_busid_idx(busid); |
| 62 | if (idx >= 0) | 73 | if (idx >= 0) { |
| 63 | bid = &(busid_table[idx]); | 74 | bid = &(busid_table[idx]); |
| 75 | /* get busid_lock before returning */ | ||
| 76 | spin_lock(&bid->busid_lock); | ||
| 77 | } | ||
| 64 | spin_unlock(&busid_table_lock); | 78 | spin_unlock(&busid_table_lock); |
| 65 | 79 | ||
| 66 | return bid; | 80 | return bid; |
| 67 | } | 81 | } |
| 68 | 82 | ||
| 83 | void put_busid_priv(struct bus_id_priv *bid) | ||
| 84 | { | ||
| 85 | if (bid) | ||
| 86 | spin_unlock(&bid->busid_lock); | ||
| 87 | } | ||
| 88 | |||
| 69 | static int add_match_busid(char *busid) | 89 | static int add_match_busid(char *busid) |
| 70 | { | 90 | { |
| 71 | int i; | 91 | int i; |
| @@ -78,15 +98,19 @@ static int add_match_busid(char *busid) | |||
| 78 | goto out; | 98 | goto out; |
| 79 | } | 99 | } |
| 80 | 100 | ||
| 81 | for (i = 0; i < MAX_BUSID; i++) | 101 | for (i = 0; i < MAX_BUSID; i++) { |
| 102 | spin_lock(&busid_table[i].busid_lock); | ||
| 82 | if (!busid_table[i].name[0]) { | 103 | if (!busid_table[i].name[0]) { |
| 83 | strlcpy(busid_table[i].name, busid, BUSID_SIZE); | 104 | strlcpy(busid_table[i].name, busid, BUSID_SIZE); |
| 84 | if ((busid_table[i].status != STUB_BUSID_ALLOC) && | 105 | if ((busid_table[i].status != STUB_BUSID_ALLOC) && |
| 85 | (busid_table[i].status != STUB_BUSID_REMOV)) | 106 | (busid_table[i].status != STUB_BUSID_REMOV)) |
| 86 | busid_table[i].status = STUB_BUSID_ADDED; | 107 | busid_table[i].status = STUB_BUSID_ADDED; |
| 87 | ret = 0; | 108 | ret = 0; |
| 109 | spin_unlock(&busid_table[i].busid_lock); | ||
| 88 | break; | 110 | break; |
| 89 | } | 111 | } |
| 112 | spin_unlock(&busid_table[i].busid_lock); | ||
| 113 | } | ||
| 90 | 114 | ||
| 91 | out: | 115 | out: |
| 92 | spin_unlock(&busid_table_lock); | 116 | spin_unlock(&busid_table_lock); |
| @@ -107,6 +131,8 @@ int del_match_busid(char *busid) | |||
| 107 | /* found */ | 131 | /* found */ |
| 108 | ret = 0; | 132 | ret = 0; |
| 109 | 133 | ||
| 134 | spin_lock(&busid_table[idx].busid_lock); | ||
| 135 | |||
| 110 | if (busid_table[idx].status == STUB_BUSID_OTHER) | 136 | if (busid_table[idx].status == STUB_BUSID_OTHER) |
| 111 | memset(busid_table[idx].name, 0, BUSID_SIZE); | 137 | memset(busid_table[idx].name, 0, BUSID_SIZE); |
| 112 | 138 | ||
| @@ -114,6 +140,7 @@ int del_match_busid(char *busid) | |||
| 114 | (busid_table[idx].status != STUB_BUSID_ADDED)) | 140 | (busid_table[idx].status != STUB_BUSID_ADDED)) |
| 115 | busid_table[idx].status = STUB_BUSID_REMOV; | 141 | busid_table[idx].status = STUB_BUSID_REMOV; |
| 116 | 142 | ||
| 143 | spin_unlock(&busid_table[idx].busid_lock); | ||
| 117 | out: | 144 | out: |
| 118 | spin_unlock(&busid_table_lock); | 145 | spin_unlock(&busid_table_lock); |
| 119 | 146 | ||
| @@ -126,9 +153,12 @@ static ssize_t match_busid_show(struct device_driver *drv, char *buf) | |||
| 126 | char *out = buf; | 153 | char *out = buf; |
| 127 | 154 | ||
| 128 | spin_lock(&busid_table_lock); | 155 | spin_lock(&busid_table_lock); |
| 129 | for (i = 0; i < MAX_BUSID; i++) | 156 | for (i = 0; i < MAX_BUSID; i++) { |
| 157 | spin_lock(&busid_table[i].busid_lock); | ||
| 130 | if (busid_table[i].name[0]) | 158 | if (busid_table[i].name[0]) |
| 131 | out += sprintf(out, "%s ", busid_table[i].name); | 159 | out += sprintf(out, "%s ", busid_table[i].name); |
| 160 | spin_unlock(&busid_table[i].busid_lock); | ||
| 161 | } | ||
| 132 | spin_unlock(&busid_table_lock); | 162 | spin_unlock(&busid_table_lock); |
| 133 | out += sprintf(out, "\n"); | 163 | out += sprintf(out, "\n"); |
| 134 | 164 | ||
| @@ -169,6 +199,51 @@ static ssize_t match_busid_store(struct device_driver *dev, const char *buf, | |||
| 169 | } | 199 | } |
| 170 | static DRIVER_ATTR_RW(match_busid); | 200 | static DRIVER_ATTR_RW(match_busid); |
| 171 | 201 | ||
| 202 | static int do_rebind(char *busid, struct bus_id_priv *busid_priv) | ||
| 203 | { | ||
| 204 | int ret; | ||
| 205 | |||
| 206 | /* device_attach() callers should hold parent lock for USB */ | ||
| 207 | if (busid_priv->udev->dev.parent) | ||
| 208 | device_lock(busid_priv->udev->dev.parent); | ||
| 209 | ret = device_attach(&busid_priv->udev->dev); | ||
| 210 | if (busid_priv->udev->dev.parent) | ||
| 211 | device_unlock(busid_priv->udev->dev.parent); | ||
| 212 | if (ret < 0) { | ||
| 213 | dev_err(&busid_priv->udev->dev, "rebind failed\n"); | ||
| 214 | return ret; | ||
| 215 | } | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static void stub_device_rebind(void) | ||
| 220 | { | ||
| 221 | #if IS_MODULE(CONFIG_USBIP_HOST) | ||
| 222 | struct bus_id_priv *busid_priv; | ||
| 223 | int i; | ||
| 224 | |||
| 225 | /* update status to STUB_BUSID_OTHER so probe ignores the device */ | ||
| 226 | spin_lock(&busid_table_lock); | ||
| 227 | for (i = 0; i < MAX_BUSID; i++) { | ||
| 228 | if (busid_table[i].name[0] && | ||
| 229 | busid_table[i].shutdown_busid) { | ||
| 230 | busid_priv = &(busid_table[i]); | ||
| 231 | busid_priv->status = STUB_BUSID_OTHER; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | spin_unlock(&busid_table_lock); | ||
| 235 | |||
| 236 | /* now run rebind - no need to hold locks. driver files are removed */ | ||
| 237 | for (i = 0; i < MAX_BUSID; i++) { | ||
| 238 | if (busid_table[i].name[0] && | ||
| 239 | busid_table[i].shutdown_busid) { | ||
| 240 | busid_priv = &(busid_table[i]); | ||
| 241 | do_rebind(busid_table[i].name, busid_priv); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | #endif | ||
| 245 | } | ||
| 246 | |||
| 172 | static ssize_t rebind_store(struct device_driver *dev, const char *buf, | 247 | static ssize_t rebind_store(struct device_driver *dev, const char *buf, |
| 173 | size_t count) | 248 | size_t count) |
| 174 | { | 249 | { |
| @@ -186,16 +261,17 @@ static ssize_t rebind_store(struct device_driver *dev, const char *buf, | |||
| 186 | if (!bid) | 261 | if (!bid) |
| 187 | return -ENODEV; | 262 | return -ENODEV; |
| 188 | 263 | ||
| 189 | /* device_attach() callers should hold parent lock for USB */ | 264 | /* mark the device for deletion so probe ignores it during rescan */ |
| 190 | if (bid->udev->dev.parent) | 265 | bid->status = STUB_BUSID_OTHER; |
| 191 | device_lock(bid->udev->dev.parent); | 266 | /* release the busid lock */ |
| 192 | ret = device_attach(&bid->udev->dev); | 267 | put_busid_priv(bid); |
| 193 | if (bid->udev->dev.parent) | 268 | |
| 194 | device_unlock(bid->udev->dev.parent); | 269 | ret = do_rebind((char *) buf, bid); |
| 195 | if (ret < 0) { | 270 | if (ret < 0) |
| 196 | dev_err(&bid->udev->dev, "rebind failed\n"); | ||
| 197 | return ret; | 271 | return ret; |
| 198 | } | 272 | |
| 273 | /* delete device from busid_table */ | ||
| 274 | del_match_busid((char *) buf); | ||
| 199 | 275 | ||
| 200 | return count; | 276 | return count; |
| 201 | } | 277 | } |
| @@ -317,6 +393,9 @@ static void __exit usbip_host_exit(void) | |||
| 317 | */ | 393 | */ |
| 318 | usb_deregister_device_driver(&stub_driver); | 394 | usb_deregister_device_driver(&stub_driver); |
| 319 | 395 | ||
| 396 | /* initiate scan to attach devices */ | ||
| 397 | stub_device_rebind(); | ||
| 398 | |||
| 320 | kmem_cache_destroy(stub_priv_cache); | 399 | kmem_cache_destroy(stub_priv_cache); |
| 321 | } | 400 | } |
| 322 | 401 | ||
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c index 3bedfed608a2..7587fb665ff1 100644 --- a/fs/afs/addr_list.c +++ b/fs/afs/addr_list.c | |||
| @@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | |||
| 121 | p = text; | 121 | p = text; |
| 122 | do { | 122 | do { |
| 123 | struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs]; | 123 | struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs]; |
| 124 | char tdelim = delim; | 124 | const char *q, *stop; |
| 125 | 125 | ||
| 126 | if (*p == delim) { | 126 | if (*p == delim) { |
| 127 | p++; | 127 | p++; |
| @@ -130,28 +130,33 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, | |||
| 130 | 130 | ||
| 131 | if (*p == '[') { | 131 | if (*p == '[') { |
| 132 | p++; | 132 | p++; |
| 133 | tdelim = ']'; | 133 | q = memchr(p, ']', end - p); |
| 134 | } else { | ||
| 135 | for (q = p; q < end; q++) | ||
| 136 | if (*q == '+' || *q == delim) | ||
| 137 | break; | ||
| 134 | } | 138 | } |
| 135 | 139 | ||
| 136 | if (in4_pton(p, end - p, | 140 | if (in4_pton(p, q - p, |
| 137 | (u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3], | 141 | (u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3], |
| 138 | tdelim, &p)) { | 142 | -1, &stop)) { |
| 139 | srx->transport.sin6.sin6_addr.s6_addr32[0] = 0; | 143 | srx->transport.sin6.sin6_addr.s6_addr32[0] = 0; |
| 140 | srx->transport.sin6.sin6_addr.s6_addr32[1] = 0; | 144 | srx->transport.sin6.sin6_addr.s6_addr32[1] = 0; |
| 141 | srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); | 145 | srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); |
| 142 | } else if (in6_pton(p, end - p, | 146 | } else if (in6_pton(p, q - p, |
| 143 | srx->transport.sin6.sin6_addr.s6_addr, | 147 | srx->transport.sin6.sin6_addr.s6_addr, |
| 144 | tdelim, &p)) { | 148 | -1, &stop)) { |
| 145 | /* Nothing to do */ | 149 | /* Nothing to do */ |
| 146 | } else { | 150 | } else { |
| 147 | goto bad_address; | 151 | goto bad_address; |
| 148 | } | 152 | } |
| 149 | 153 | ||
| 150 | if (tdelim == ']') { | 154 | if (stop != q) |
| 151 | if (p == end || *p != ']') | 155 | goto bad_address; |
| 152 | goto bad_address; | 156 | |
| 157 | p = q; | ||
| 158 | if (q < end && *q == ']') | ||
| 153 | p++; | 159 | p++; |
| 154 | } | ||
| 155 | 160 | ||
| 156 | if (p < end) { | 161 | if (p < end) { |
| 157 | if (*p == '+') { | 162 | if (*p == '+') { |
diff --git a/fs/afs/callback.c b/fs/afs/callback.c index abd9a84f4e88..571437dcb252 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c | |||
| @@ -23,36 +23,55 @@ | |||
| 23 | /* | 23 | /* |
| 24 | * Set up an interest-in-callbacks record for a volume on a server and | 24 | * Set up an interest-in-callbacks record for a volume on a server and |
| 25 | * register it with the server. | 25 | * register it with the server. |
| 26 | * - Called with volume->server_sem held. | 26 | * - Called with vnode->io_lock held. |
| 27 | */ | 27 | */ |
| 28 | int afs_register_server_cb_interest(struct afs_vnode *vnode, | 28 | int afs_register_server_cb_interest(struct afs_vnode *vnode, |
| 29 | struct afs_server_entry *entry) | 29 | struct afs_server_list *slist, |
| 30 | unsigned int index) | ||
| 30 | { | 31 | { |
| 31 | struct afs_cb_interest *cbi = entry->cb_interest, *vcbi, *new, *x; | 32 | struct afs_server_entry *entry = &slist->servers[index]; |
| 33 | struct afs_cb_interest *cbi, *vcbi, *new, *old; | ||
| 32 | struct afs_server *server = entry->server; | 34 | struct afs_server *server = entry->server; |
| 33 | 35 | ||
| 34 | again: | 36 | again: |
| 37 | if (vnode->cb_interest && | ||
| 38 | likely(vnode->cb_interest == entry->cb_interest)) | ||
| 39 | return 0; | ||
| 40 | |||
| 41 | read_lock(&slist->lock); | ||
| 42 | cbi = afs_get_cb_interest(entry->cb_interest); | ||
| 43 | read_unlock(&slist->lock); | ||
| 44 | |||
| 35 | vcbi = vnode->cb_interest; | 45 | vcbi = vnode->cb_interest; |
| 36 | if (vcbi) { | 46 | if (vcbi) { |
| 37 | if (vcbi == cbi) | 47 | if (vcbi == cbi) { |
| 48 | afs_put_cb_interest(afs_v2net(vnode), cbi); | ||
| 38 | return 0; | 49 | return 0; |
| 50 | } | ||
| 39 | 51 | ||
| 52 | /* Use a new interest in the server list for the same server | ||
| 53 | * rather than an old one that's still attached to a vnode. | ||
| 54 | */ | ||
| 40 | if (cbi && vcbi->server == cbi->server) { | 55 | if (cbi && vcbi->server == cbi->server) { |
| 41 | write_seqlock(&vnode->cb_lock); | 56 | write_seqlock(&vnode->cb_lock); |
| 42 | vnode->cb_interest = afs_get_cb_interest(cbi); | 57 | old = vnode->cb_interest; |
| 58 | vnode->cb_interest = cbi; | ||
| 43 | write_sequnlock(&vnode->cb_lock); | 59 | write_sequnlock(&vnode->cb_lock); |
| 44 | afs_put_cb_interest(afs_v2net(vnode), cbi); | 60 | afs_put_cb_interest(afs_v2net(vnode), old); |
| 45 | return 0; | 61 | return 0; |
| 46 | } | 62 | } |
| 47 | 63 | ||
| 64 | /* Re-use the one attached to the vnode. */ | ||
| 48 | if (!cbi && vcbi->server == server) { | 65 | if (!cbi && vcbi->server == server) { |
| 49 | afs_get_cb_interest(vcbi); | 66 | write_lock(&slist->lock); |
| 50 | x = cmpxchg(&entry->cb_interest, cbi, vcbi); | 67 | if (entry->cb_interest) { |
| 51 | if (x != cbi) { | 68 | write_unlock(&slist->lock); |
| 52 | cbi = x; | 69 | afs_put_cb_interest(afs_v2net(vnode), cbi); |
| 53 | afs_put_cb_interest(afs_v2net(vnode), vcbi); | ||
| 54 | goto again; | 70 | goto again; |
| 55 | } | 71 | } |
| 72 | |||
| 73 | entry->cb_interest = cbi; | ||
| 74 | write_unlock(&slist->lock); | ||
| 56 | return 0; | 75 | return 0; |
| 57 | } | 76 | } |
| 58 | } | 77 | } |
| @@ -72,13 +91,16 @@ again: | |||
| 72 | list_add_tail(&new->cb_link, &server->cb_interests); | 91 | list_add_tail(&new->cb_link, &server->cb_interests); |
| 73 | write_unlock(&server->cb_break_lock); | 92 | write_unlock(&server->cb_break_lock); |
| 74 | 93 | ||
| 75 | x = cmpxchg(&entry->cb_interest, cbi, new); | 94 | write_lock(&slist->lock); |
| 76 | if (x == cbi) { | 95 | if (!entry->cb_interest) { |
| 96 | entry->cb_interest = afs_get_cb_interest(new); | ||
| 77 | cbi = new; | 97 | cbi = new; |
| 98 | new = NULL; | ||
| 78 | } else { | 99 | } else { |
| 79 | cbi = x; | 100 | cbi = afs_get_cb_interest(entry->cb_interest); |
| 80 | afs_put_cb_interest(afs_v2net(vnode), new); | ||
| 81 | } | 101 | } |
| 102 | write_unlock(&slist->lock); | ||
| 103 | afs_put_cb_interest(afs_v2net(vnode), new); | ||
| 82 | } | 104 | } |
| 83 | 105 | ||
| 84 | ASSERT(cbi); | 106 | ASSERT(cbi); |
| @@ -88,11 +110,14 @@ again: | |||
| 88 | */ | 110 | */ |
| 89 | write_seqlock(&vnode->cb_lock); | 111 | write_seqlock(&vnode->cb_lock); |
| 90 | 112 | ||
| 91 | vnode->cb_interest = afs_get_cb_interest(cbi); | 113 | old = vnode->cb_interest; |
| 114 | vnode->cb_interest = cbi; | ||
| 92 | vnode->cb_s_break = cbi->server->cb_s_break; | 115 | vnode->cb_s_break = cbi->server->cb_s_break; |
| 116 | vnode->cb_v_break = vnode->volume->cb_v_break; | ||
| 93 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | 117 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); |
| 94 | 118 | ||
| 95 | write_sequnlock(&vnode->cb_lock); | 119 | write_sequnlock(&vnode->cb_lock); |
| 120 | afs_put_cb_interest(afs_v2net(vnode), old); | ||
| 96 | return 0; | 121 | return 0; |
| 97 | } | 122 | } |
| 98 | 123 | ||
| @@ -171,13 +196,24 @@ static void afs_break_one_callback(struct afs_server *server, | |||
| 171 | if (cbi->vid != fid->vid) | 196 | if (cbi->vid != fid->vid) |
| 172 | continue; | 197 | continue; |
| 173 | 198 | ||
| 174 | data.volume = NULL; | 199 | if (fid->vnode == 0 && fid->unique == 0) { |
| 175 | data.fid = *fid; | 200 | /* The callback break applies to an entire volume. */ |
| 176 | inode = ilookup5_nowait(cbi->sb, fid->vnode, afs_iget5_test, &data); | 201 | struct afs_super_info *as = AFS_FS_S(cbi->sb); |
| 177 | if (inode) { | 202 | struct afs_volume *volume = as->volume; |
| 178 | vnode = AFS_FS_I(inode); | 203 | |
| 179 | afs_break_callback(vnode); | 204 | write_lock(&volume->cb_break_lock); |
| 180 | iput(inode); | 205 | volume->cb_v_break++; |
| 206 | write_unlock(&volume->cb_break_lock); | ||
| 207 | } else { | ||
| 208 | data.volume = NULL; | ||
| 209 | data.fid = *fid; | ||
| 210 | inode = ilookup5_nowait(cbi->sb, fid->vnode, | ||
| 211 | afs_iget5_test, &data); | ||
| 212 | if (inode) { | ||
| 213 | vnode = AFS_FS_I(inode); | ||
| 214 | afs_break_callback(vnode); | ||
| 215 | iput(inode); | ||
| 216 | } | ||
| 181 | } | 217 | } |
| 182 | } | 218 | } |
| 183 | 219 | ||
| @@ -195,6 +231,8 @@ void afs_break_callbacks(struct afs_server *server, size_t count, | |||
| 195 | ASSERT(server != NULL); | 231 | ASSERT(server != NULL); |
| 196 | ASSERTCMP(count, <=, AFSCBMAX); | 232 | ASSERTCMP(count, <=, AFSCBMAX); |
| 197 | 233 | ||
| 234 | /* TODO: Sort the callback break list by volume ID */ | ||
| 235 | |||
| 198 | for (; count > 0; callbacks++, count--) { | 236 | for (; count > 0; callbacks++, count--) { |
| 199 | _debug("- Fid { vl=%08x n=%u u=%u } CB { v=%u x=%u t=%u }", | 237 | _debug("- Fid { vl=%08x n=%u u=%u } CB { v=%u x=%u t=%u }", |
| 200 | callbacks->fid.vid, | 238 | callbacks->fid.vid, |
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 357de908df3a..c332c95a6940 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
| @@ -133,21 +133,10 @@ bool afs_cm_incoming_call(struct afs_call *call) | |||
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | /* | 135 | /* |
| 136 | * clean up a cache manager call | 136 | * Clean up a cache manager call. |
| 137 | */ | 137 | */ |
| 138 | static void afs_cm_destructor(struct afs_call *call) | 138 | static void afs_cm_destructor(struct afs_call *call) |
| 139 | { | 139 | { |
| 140 | _enter(""); | ||
| 141 | |||
| 142 | /* Break the callbacks here so that we do it after the final ACK is | ||
| 143 | * received. The step number here must match the final number in | ||
| 144 | * afs_deliver_cb_callback(). | ||
| 145 | */ | ||
| 146 | if (call->unmarshall == 5) { | ||
| 147 | ASSERT(call->cm_server && call->count && call->request); | ||
| 148 | afs_break_callbacks(call->cm_server, call->count, call->request); | ||
| 149 | } | ||
| 150 | |||
| 151 | kfree(call->buffer); | 140 | kfree(call->buffer); |
| 152 | call->buffer = NULL; | 141 | call->buffer = NULL; |
| 153 | } | 142 | } |
| @@ -161,14 +150,14 @@ static void SRXAFSCB_CallBack(struct work_struct *work) | |||
| 161 | 150 | ||
| 162 | _enter(""); | 151 | _enter(""); |
| 163 | 152 | ||
| 164 | /* be sure to send the reply *before* attempting to spam the AFS server | 153 | /* We need to break the callbacks before sending the reply as the |
| 165 | * with FSFetchStatus requests on the vnodes with broken callbacks lest | 154 | * server holds up change visibility till it receives our reply so as |
| 166 | * the AFS server get into a vicious cycle of trying to break further | 155 | * to maintain cache coherency. |
| 167 | * callbacks because it hadn't received completion of the CBCallBack op | 156 | */ |
| 168 | * yet */ | 157 | if (call->cm_server) |
| 169 | afs_send_empty_reply(call); | 158 | afs_break_callbacks(call->cm_server, call->count, call->request); |
| 170 | 159 | ||
| 171 | afs_break_callbacks(call->cm_server, call->count, call->request); | 160 | afs_send_empty_reply(call); |
| 172 | afs_put_call(call); | 161 | afs_put_call(call); |
| 173 | _leave(""); | 162 | _leave(""); |
| 174 | } | 163 | } |
| @@ -180,7 +169,6 @@ static int afs_deliver_cb_callback(struct afs_call *call) | |||
| 180 | { | 169 | { |
| 181 | struct afs_callback_break *cb; | 170 | struct afs_callback_break *cb; |
| 182 | struct sockaddr_rxrpc srx; | 171 | struct sockaddr_rxrpc srx; |
| 183 | struct afs_server *server; | ||
| 184 | __be32 *bp; | 172 | __be32 *bp; |
| 185 | int ret, loop; | 173 | int ret, loop; |
| 186 | 174 | ||
| @@ -267,15 +255,6 @@ static int afs_deliver_cb_callback(struct afs_call *call) | |||
| 267 | 255 | ||
| 268 | call->offset = 0; | 256 | call->offset = 0; |
| 269 | call->unmarshall++; | 257 | call->unmarshall++; |
| 270 | |||
| 271 | /* Record that the message was unmarshalled successfully so | ||
| 272 | * that the call destructor can know do the callback breaking | ||
| 273 | * work, even if the final ACK isn't received. | ||
| 274 | * | ||
| 275 | * If the step number changes, then afs_cm_destructor() must be | ||
| 276 | * updated also. | ||
| 277 | */ | ||
| 278 | call->unmarshall++; | ||
| 279 | case 5: | 258 | case 5: |
| 280 | break; | 259 | break; |
| 281 | } | 260 | } |
| @@ -286,10 +265,9 @@ static int afs_deliver_cb_callback(struct afs_call *call) | |||
| 286 | /* we'll need the file server record as that tells us which set of | 265 | /* we'll need the file server record as that tells us which set of |
| 287 | * vnodes to operate upon */ | 266 | * vnodes to operate upon */ |
| 288 | rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); | 267 | rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); |
| 289 | server = afs_find_server(call->net, &srx); | 268 | call->cm_server = afs_find_server(call->net, &srx); |
| 290 | if (!server) | 269 | if (!call->cm_server) |
| 291 | return -ENOTCONN; | 270 | trace_afs_cm_no_server(call, &srx); |
| 292 | call->cm_server = server; | ||
| 293 | 271 | ||
| 294 | return afs_queue_call_work(call); | 272 | return afs_queue_call_work(call); |
| 295 | } | 273 | } |
| @@ -303,7 +281,8 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work) | |||
| 303 | 281 | ||
| 304 | _enter("{%p}", call->cm_server); | 282 | _enter("{%p}", call->cm_server); |
| 305 | 283 | ||
| 306 | afs_init_callback_state(call->cm_server); | 284 | if (call->cm_server) |
| 285 | afs_init_callback_state(call->cm_server); | ||
| 307 | afs_send_empty_reply(call); | 286 | afs_send_empty_reply(call); |
| 308 | afs_put_call(call); | 287 | afs_put_call(call); |
| 309 | _leave(""); | 288 | _leave(""); |
| @@ -315,7 +294,6 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work) | |||
| 315 | static int afs_deliver_cb_init_call_back_state(struct afs_call *call) | 294 | static int afs_deliver_cb_init_call_back_state(struct afs_call *call) |
| 316 | { | 295 | { |
| 317 | struct sockaddr_rxrpc srx; | 296 | struct sockaddr_rxrpc srx; |
| 318 | struct afs_server *server; | ||
| 319 | int ret; | 297 | int ret; |
| 320 | 298 | ||
| 321 | _enter(""); | 299 | _enter(""); |
| @@ -328,10 +306,9 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call) | |||
| 328 | 306 | ||
| 329 | /* we'll need the file server record as that tells us which set of | 307 | /* we'll need the file server record as that tells us which set of |
| 330 | * vnodes to operate upon */ | 308 | * vnodes to operate upon */ |
| 331 | server = afs_find_server(call->net, &srx); | 309 | call->cm_server = afs_find_server(call->net, &srx); |
| 332 | if (!server) | 310 | if (!call->cm_server) |
| 333 | return -ENOTCONN; | 311 | trace_afs_cm_no_server(call, &srx); |
| 334 | call->cm_server = server; | ||
| 335 | 312 | ||
| 336 | return afs_queue_call_work(call); | 313 | return afs_queue_call_work(call); |
| 337 | } | 314 | } |
| @@ -341,8 +318,6 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call) | |||
| 341 | */ | 318 | */ |
| 342 | static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) | 319 | static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) |
| 343 | { | 320 | { |
| 344 | struct sockaddr_rxrpc srx; | ||
| 345 | struct afs_server *server; | ||
| 346 | struct afs_uuid *r; | 321 | struct afs_uuid *r; |
| 347 | unsigned loop; | 322 | unsigned loop; |
| 348 | __be32 *b; | 323 | __be32 *b; |
| @@ -398,11 +373,11 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) | |||
| 398 | 373 | ||
| 399 | /* we'll need the file server record as that tells us which set of | 374 | /* we'll need the file server record as that tells us which set of |
| 400 | * vnodes to operate upon */ | 375 | * vnodes to operate upon */ |
| 401 | rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); | 376 | rcu_read_lock(); |
| 402 | server = afs_find_server(call->net, &srx); | 377 | call->cm_server = afs_find_server_by_uuid(call->net, call->request); |
| 403 | if (!server) | 378 | rcu_read_unlock(); |
| 404 | return -ENOTCONN; | 379 | if (!call->cm_server) |
| 405 | call->cm_server = server; | 380 | trace_afs_cm_no_server_u(call, call->request); |
| 406 | 381 | ||
| 407 | return afs_queue_call_work(call); | 382 | return afs_queue_call_work(call); |
| 408 | } | 383 | } |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 5889f70d4d27..7d623008157f 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -180,6 +180,7 @@ static int afs_dir_open(struct inode *inode, struct file *file) | |||
| 180 | * get reclaimed during the iteration. | 180 | * get reclaimed during the iteration. |
| 181 | */ | 181 | */ |
| 182 | static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) | 182 | static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key) |
| 183 | __acquires(&dvnode->validate_lock) | ||
| 183 | { | 184 | { |
| 184 | struct afs_read *req; | 185 | struct afs_read *req; |
| 185 | loff_t i_size; | 186 | loff_t i_size; |
| @@ -261,18 +262,21 @@ retry: | |||
| 261 | /* If we're going to reload, we need to lock all the pages to prevent | 262 | /* If we're going to reload, we need to lock all the pages to prevent |
| 262 | * races. | 263 | * races. |
| 263 | */ | 264 | */ |
| 264 | if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) { | 265 | ret = -ERESTARTSYS; |
| 265 | ret = -ERESTARTSYS; | 266 | if (down_read_killable(&dvnode->validate_lock) < 0) |
| 266 | for (i = 0; i < req->nr_pages; i++) | 267 | goto error; |
| 267 | if (lock_page_killable(req->pages[i]) < 0) | ||
| 268 | goto error_unlock; | ||
| 269 | 268 | ||
| 270 | if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) | 269 | if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) |
| 271 | goto success; | 270 | goto success; |
| 271 | |||
| 272 | up_read(&dvnode->validate_lock); | ||
| 273 | if (down_write_killable(&dvnode->validate_lock) < 0) | ||
| 274 | goto error; | ||
| 272 | 275 | ||
| 276 | if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) { | ||
| 273 | ret = afs_fetch_data(dvnode, key, req); | 277 | ret = afs_fetch_data(dvnode, key, req); |
| 274 | if (ret < 0) | 278 | if (ret < 0) |
| 275 | goto error_unlock_all; | 279 | goto error_unlock; |
| 276 | 280 | ||
| 277 | task_io_account_read(PAGE_SIZE * req->nr_pages); | 281 | task_io_account_read(PAGE_SIZE * req->nr_pages); |
| 278 | 282 | ||
| @@ -284,33 +288,26 @@ retry: | |||
| 284 | for (i = 0; i < req->nr_pages; i++) | 288 | for (i = 0; i < req->nr_pages; i++) |
| 285 | if (!afs_dir_check_page(dvnode, req->pages[i], | 289 | if (!afs_dir_check_page(dvnode, req->pages[i], |
| 286 | req->actual_len)) | 290 | req->actual_len)) |
| 287 | goto error_unlock_all; | 291 | goto error_unlock; |
| 288 | 292 | ||
| 289 | // TODO: Trim excess pages | 293 | // TODO: Trim excess pages |
| 290 | 294 | ||
| 291 | set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags); | 295 | set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags); |
| 292 | } | 296 | } |
| 293 | 297 | ||
| 298 | downgrade_write(&dvnode->validate_lock); | ||
| 294 | success: | 299 | success: |
| 295 | i = req->nr_pages; | ||
| 296 | while (i > 0) | ||
| 297 | unlock_page(req->pages[--i]); | ||
| 298 | return req; | 300 | return req; |
| 299 | 301 | ||
| 300 | error_unlock_all: | ||
| 301 | i = req->nr_pages; | ||
| 302 | error_unlock: | 302 | error_unlock: |
| 303 | while (i > 0) | 303 | up_write(&dvnode->validate_lock); |
| 304 | unlock_page(req->pages[--i]); | ||
| 305 | error: | 304 | error: |
| 306 | afs_put_read(req); | 305 | afs_put_read(req); |
| 307 | _leave(" = %d", ret); | 306 | _leave(" = %d", ret); |
| 308 | return ERR_PTR(ret); | 307 | return ERR_PTR(ret); |
| 309 | 308 | ||
| 310 | content_has_grown: | 309 | content_has_grown: |
| 311 | i = req->nr_pages; | 310 | up_write(&dvnode->validate_lock); |
| 312 | while (i > 0) | ||
| 313 | unlock_page(req->pages[--i]); | ||
| 314 | afs_put_read(req); | 311 | afs_put_read(req); |
| 315 | goto retry; | 312 | goto retry; |
| 316 | } | 313 | } |
| @@ -473,6 +470,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx, | |||
| 473 | } | 470 | } |
| 474 | 471 | ||
| 475 | out: | 472 | out: |
| 473 | up_read(&dvnode->validate_lock); | ||
| 476 | afs_put_read(req); | 474 | afs_put_read(req); |
| 477 | _leave(" = %d", ret); | 475 | _leave(" = %d", ret); |
| 478 | return ret; | 476 | return ret; |
| @@ -1143,7 +1141,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 1143 | ret = -ERESTARTSYS; | 1141 | ret = -ERESTARTSYS; |
| 1144 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { | 1142 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { |
| 1145 | while (afs_select_fileserver(&fc)) { | 1143 | while (afs_select_fileserver(&fc)) { |
| 1146 | fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; | 1144 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1147 | afs_fs_create(&fc, dentry->d_name.name, mode, data_version, | 1145 | afs_fs_create(&fc, dentry->d_name.name, mode, data_version, |
| 1148 | &newfid, &newstatus, &newcb); | 1146 | &newfid, &newstatus, &newcb); |
| 1149 | } | 1147 | } |
| @@ -1213,7 +1211,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1213 | ret = -ERESTARTSYS; | 1211 | ret = -ERESTARTSYS; |
| 1214 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { | 1212 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { |
| 1215 | while (afs_select_fileserver(&fc)) { | 1213 | while (afs_select_fileserver(&fc)) { |
| 1216 | fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; | 1214 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1217 | afs_fs_remove(&fc, dentry->d_name.name, true, | 1215 | afs_fs_remove(&fc, dentry->d_name.name, true, |
| 1218 | data_version); | 1216 | data_version); |
| 1219 | } | 1217 | } |
| @@ -1316,7 +1314,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1316 | ret = -ERESTARTSYS; | 1314 | ret = -ERESTARTSYS; |
| 1317 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { | 1315 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { |
| 1318 | while (afs_select_fileserver(&fc)) { | 1316 | while (afs_select_fileserver(&fc)) { |
| 1319 | fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; | 1317 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1320 | afs_fs_remove(&fc, dentry->d_name.name, false, | 1318 | afs_fs_remove(&fc, dentry->d_name.name, false, |
| 1321 | data_version); | 1319 | data_version); |
| 1322 | } | 1320 | } |
| @@ -1373,7 +1371,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 1373 | ret = -ERESTARTSYS; | 1371 | ret = -ERESTARTSYS; |
| 1374 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { | 1372 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { |
| 1375 | while (afs_select_fileserver(&fc)) { | 1373 | while (afs_select_fileserver(&fc)) { |
| 1376 | fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; | 1374 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1377 | afs_fs_create(&fc, dentry->d_name.name, mode, data_version, | 1375 | afs_fs_create(&fc, dentry->d_name.name, mode, data_version, |
| 1378 | &newfid, &newstatus, &newcb); | 1376 | &newfid, &newstatus, &newcb); |
| 1379 | } | 1377 | } |
| @@ -1443,8 +1441,8 @@ static int afs_link(struct dentry *from, struct inode *dir, | |||
| 1443 | } | 1441 | } |
| 1444 | 1442 | ||
| 1445 | while (afs_select_fileserver(&fc)) { | 1443 | while (afs_select_fileserver(&fc)) { |
| 1446 | fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; | 1444 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1447 | fc.cb_break_2 = vnode->cb_break + vnode->cb_s_break; | 1445 | fc.cb_break_2 = afs_calc_vnode_cb_break(vnode); |
| 1448 | afs_fs_link(&fc, vnode, dentry->d_name.name, data_version); | 1446 | afs_fs_link(&fc, vnode, dentry->d_name.name, data_version); |
| 1449 | } | 1447 | } |
| 1450 | 1448 | ||
| @@ -1512,7 +1510,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 1512 | ret = -ERESTARTSYS; | 1510 | ret = -ERESTARTSYS; |
| 1513 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { | 1511 | if (afs_begin_vnode_operation(&fc, dvnode, key)) { |
| 1514 | while (afs_select_fileserver(&fc)) { | 1512 | while (afs_select_fileserver(&fc)) { |
| 1515 | fc.cb_break = dvnode->cb_break + dvnode->cb_s_break; | 1513 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1516 | afs_fs_symlink(&fc, dentry->d_name.name, | 1514 | afs_fs_symlink(&fc, dentry->d_name.name, |
| 1517 | content, data_version, | 1515 | content, data_version, |
| 1518 | &newfid, &newstatus); | 1516 | &newfid, &newstatus); |
| @@ -1588,8 +1586,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1588 | } | 1586 | } |
| 1589 | } | 1587 | } |
| 1590 | while (afs_select_fileserver(&fc)) { | 1588 | while (afs_select_fileserver(&fc)) { |
| 1591 | fc.cb_break = orig_dvnode->cb_break + orig_dvnode->cb_s_break; | 1589 | fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode); |
| 1592 | fc.cb_break_2 = new_dvnode->cb_break + new_dvnode->cb_s_break; | 1590 | fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode); |
| 1593 | afs_fs_rename(&fc, old_dentry->d_name.name, | 1591 | afs_fs_rename(&fc, old_dentry->d_name.name, |
| 1594 | new_dvnode, new_dentry->d_name.name, | 1592 | new_dvnode, new_dentry->d_name.name, |
| 1595 | orig_data_version, new_data_version); | 1593 | orig_data_version, new_data_version); |
diff --git a/fs/afs/file.c b/fs/afs/file.c index c24c08016dd9..7d4f26198573 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
| @@ -238,7 +238,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de | |||
| 238 | ret = -ERESTARTSYS; | 238 | ret = -ERESTARTSYS; |
| 239 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | 239 | if (afs_begin_vnode_operation(&fc, vnode, key)) { |
| 240 | while (afs_select_fileserver(&fc)) { | 240 | while (afs_select_fileserver(&fc)) { |
| 241 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 241 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 242 | afs_fs_fetch_data(&fc, desc); | 242 | afs_fs_fetch_data(&fc, desc); |
| 243 | } | 243 | } |
| 244 | 244 | ||
diff --git a/fs/afs/flock.c b/fs/afs/flock.c index 7a0e017070ec..dc62d15a964b 100644 --- a/fs/afs/flock.c +++ b/fs/afs/flock.c | |||
| @@ -86,7 +86,7 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key, | |||
| 86 | ret = -ERESTARTSYS; | 86 | ret = -ERESTARTSYS; |
| 87 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | 87 | if (afs_begin_vnode_operation(&fc, vnode, key)) { |
| 88 | while (afs_select_fileserver(&fc)) { | 88 | while (afs_select_fileserver(&fc)) { |
| 89 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 89 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 90 | afs_fs_set_lock(&fc, type); | 90 | afs_fs_set_lock(&fc, type); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| @@ -117,7 +117,7 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key) | |||
| 117 | ret = -ERESTARTSYS; | 117 | ret = -ERESTARTSYS; |
| 118 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | 118 | if (afs_begin_vnode_operation(&fc, vnode, key)) { |
| 119 | while (afs_select_current_fileserver(&fc)) { | 119 | while (afs_select_current_fileserver(&fc)) { |
| 120 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 120 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 121 | afs_fs_extend_lock(&fc); | 121 | afs_fs_extend_lock(&fc); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| @@ -148,7 +148,7 @@ static int afs_release_lock(struct afs_vnode *vnode, struct key *key) | |||
| 148 | ret = -ERESTARTSYS; | 148 | ret = -ERESTARTSYS; |
| 149 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | 149 | if (afs_begin_vnode_operation(&fc, vnode, key)) { |
| 150 | while (afs_select_current_fileserver(&fc)) { | 150 | while (afs_select_current_fileserver(&fc)) { |
| 151 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 151 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 152 | afs_fs_release_lock(&fc); | 152 | afs_fs_release_lock(&fc); |
| 153 | } | 153 | } |
| 154 | 154 | ||
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index efacdb7c1dee..b273e1d60478 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
| @@ -134,6 +134,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 134 | struct afs_read *read_req) | 134 | struct afs_read *read_req) |
| 135 | { | 135 | { |
| 136 | const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp; | 136 | const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp; |
| 137 | bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus); | ||
| 137 | u64 data_version, size; | 138 | u64 data_version, size; |
| 138 | u32 type, abort_code; | 139 | u32 type, abort_code; |
| 139 | u8 flags = 0; | 140 | u8 flags = 0; |
| @@ -142,13 +143,32 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 142 | if (vnode) | 143 | if (vnode) |
| 143 | write_seqlock(&vnode->cb_lock); | 144 | write_seqlock(&vnode->cb_lock); |
| 144 | 145 | ||
| 146 | abort_code = ntohl(xdr->abort_code); | ||
| 147 | |||
| 145 | if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { | 148 | if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { |
| 149 | if (xdr->if_version == htonl(0) && | ||
| 150 | abort_code != 0 && | ||
| 151 | inline_error) { | ||
| 152 | /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus | ||
| 153 | * whereby it doesn't set the interface version in the error | ||
| 154 | * case. | ||
| 155 | */ | ||
| 156 | status->abort_code = abort_code; | ||
| 157 | ret = 0; | ||
| 158 | goto out; | ||
| 159 | } | ||
| 160 | |||
| 146 | pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); | 161 | pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); |
| 147 | goto bad; | 162 | goto bad; |
| 148 | } | 163 | } |
| 149 | 164 | ||
| 165 | if (abort_code != 0 && inline_error) { | ||
| 166 | status->abort_code = abort_code; | ||
| 167 | ret = 0; | ||
| 168 | goto out; | ||
| 169 | } | ||
| 170 | |||
| 150 | type = ntohl(xdr->type); | 171 | type = ntohl(xdr->type); |
| 151 | abort_code = ntohl(xdr->abort_code); | ||
| 152 | switch (type) { | 172 | switch (type) { |
| 153 | case AFS_FTYPE_FILE: | 173 | case AFS_FTYPE_FILE: |
| 154 | case AFS_FTYPE_DIR: | 174 | case AFS_FTYPE_DIR: |
| @@ -165,13 +185,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 165 | } | 185 | } |
| 166 | status->type = type; | 186 | status->type = type; |
| 167 | break; | 187 | break; |
| 168 | case AFS_FTYPE_INVALID: | ||
| 169 | if (abort_code != 0) { | ||
| 170 | status->abort_code = abort_code; | ||
| 171 | ret = 0; | ||
| 172 | goto out; | ||
| 173 | } | ||
| 174 | /* Fall through */ | ||
| 175 | default: | 188 | default: |
| 176 | goto bad; | 189 | goto bad; |
| 177 | } | 190 | } |
| @@ -248,7 +261,7 @@ static void xdr_decode_AFSCallBack(struct afs_call *call, | |||
| 248 | 261 | ||
| 249 | write_seqlock(&vnode->cb_lock); | 262 | write_seqlock(&vnode->cb_lock); |
| 250 | 263 | ||
| 251 | if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) { | 264 | if (call->cb_break == afs_cb_break_sum(vnode, cbi)) { |
| 252 | vnode->cb_version = ntohl(*bp++); | 265 | vnode->cb_version = ntohl(*bp++); |
| 253 | cb_expiry = ntohl(*bp++); | 266 | cb_expiry = ntohl(*bp++); |
| 254 | vnode->cb_type = ntohl(*bp++); | 267 | vnode->cb_type = ntohl(*bp++); |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 06194cfe9724..479b7fdda124 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
| @@ -108,7 +108,7 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode) | |||
| 108 | ret = -ERESTARTSYS; | 108 | ret = -ERESTARTSYS; |
| 109 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | 109 | if (afs_begin_vnode_operation(&fc, vnode, key)) { |
| 110 | while (afs_select_fileserver(&fc)) { | 110 | while (afs_select_fileserver(&fc)) { |
| 111 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 111 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 112 | afs_fs_fetch_file_status(&fc, NULL, new_inode); | 112 | afs_fs_fetch_file_status(&fc, NULL, new_inode); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| @@ -393,15 +393,18 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
| 393 | read_seqlock_excl(&vnode->cb_lock); | 393 | read_seqlock_excl(&vnode->cb_lock); |
| 394 | 394 | ||
| 395 | if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { | 395 | if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { |
| 396 | if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break) { | 396 | if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break || |
| 397 | vnode->cb_v_break != vnode->volume->cb_v_break) { | ||
| 397 | vnode->cb_s_break = vnode->cb_interest->server->cb_s_break; | 398 | vnode->cb_s_break = vnode->cb_interest->server->cb_s_break; |
| 399 | vnode->cb_v_break = vnode->volume->cb_v_break; | ||
| 400 | valid = false; | ||
| 398 | } else if (vnode->status.type == AFS_FTYPE_DIR && | 401 | } else if (vnode->status.type == AFS_FTYPE_DIR && |
| 399 | test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) && | 402 | test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) && |
| 400 | vnode->cb_expires_at - 10 > now) { | 403 | vnode->cb_expires_at - 10 > now) { |
| 401 | valid = true; | 404 | valid = true; |
| 402 | } else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) && | 405 | } else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) && |
| 403 | vnode->cb_expires_at - 10 > now) { | 406 | vnode->cb_expires_at - 10 > now) { |
| 404 | valid = true; | 407 | valid = true; |
| 405 | } | 408 | } |
| 406 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { | 409 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { |
| 407 | valid = true; | 410 | valid = true; |
| @@ -415,7 +418,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
| 415 | if (valid) | 418 | if (valid) |
| 416 | goto valid; | 419 | goto valid; |
| 417 | 420 | ||
| 418 | mutex_lock(&vnode->validate_lock); | 421 | down_write(&vnode->validate_lock); |
| 419 | 422 | ||
| 420 | /* if the promise has expired, we need to check the server again to get | 423 | /* if the promise has expired, we need to check the server again to get |
| 421 | * a new promise - note that if the (parent) directory's metadata was | 424 | * a new promise - note that if the (parent) directory's metadata was |
| @@ -444,13 +447,13 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
| 444 | * different */ | 447 | * different */ |
| 445 | if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) | 448 | if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) |
| 446 | afs_zap_data(vnode); | 449 | afs_zap_data(vnode); |
| 447 | mutex_unlock(&vnode->validate_lock); | 450 | up_write(&vnode->validate_lock); |
| 448 | valid: | 451 | valid: |
| 449 | _leave(" = 0"); | 452 | _leave(" = 0"); |
| 450 | return 0; | 453 | return 0; |
| 451 | 454 | ||
| 452 | error_unlock: | 455 | error_unlock: |
| 453 | mutex_unlock(&vnode->validate_lock); | 456 | up_write(&vnode->validate_lock); |
| 454 | _leave(" = %d", ret); | 457 | _leave(" = %d", ret); |
| 455 | return ret; | 458 | return ret; |
| 456 | } | 459 | } |
| @@ -574,7 +577,7 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 574 | ret = -ERESTARTSYS; | 577 | ret = -ERESTARTSYS; |
| 575 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | 578 | if (afs_begin_vnode_operation(&fc, vnode, key)) { |
| 576 | while (afs_select_fileserver(&fc)) { | 579 | while (afs_select_fileserver(&fc)) { |
| 577 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 580 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 578 | afs_fs_setattr(&fc, attr); | 581 | afs_fs_setattr(&fc, attr); |
| 579 | } | 582 | } |
| 580 | 583 | ||
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index f8086ec95e24..e3f8a46663db 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -396,6 +396,7 @@ struct afs_server { | |||
| 396 | #define AFS_SERVER_FL_PROBED 5 /* The fileserver has been probed */ | 396 | #define AFS_SERVER_FL_PROBED 5 /* The fileserver has been probed */ |
| 397 | #define AFS_SERVER_FL_PROBING 6 /* Fileserver is being probed */ | 397 | #define AFS_SERVER_FL_PROBING 6 /* Fileserver is being probed */ |
| 398 | #define AFS_SERVER_FL_NO_IBULK 7 /* Fileserver doesn't support FS.InlineBulkStatus */ | 398 | #define AFS_SERVER_FL_NO_IBULK 7 /* Fileserver doesn't support FS.InlineBulkStatus */ |
| 399 | #define AFS_SERVER_FL_MAY_HAVE_CB 8 /* May have callbacks on this fileserver */ | ||
| 399 | atomic_t usage; | 400 | atomic_t usage; |
| 400 | u32 addr_version; /* Address list version */ | 401 | u32 addr_version; /* Address list version */ |
| 401 | 402 | ||
| @@ -433,6 +434,7 @@ struct afs_server_list { | |||
| 433 | unsigned short index; /* Server currently in use */ | 434 | unsigned short index; /* Server currently in use */ |
| 434 | unsigned short vnovol_mask; /* Servers to be skipped due to VNOVOL */ | 435 | unsigned short vnovol_mask; /* Servers to be skipped due to VNOVOL */ |
| 435 | unsigned int seq; /* Set to ->servers_seq when installed */ | 436 | unsigned int seq; /* Set to ->servers_seq when installed */ |
| 437 | rwlock_t lock; | ||
| 436 | struct afs_server_entry servers[]; | 438 | struct afs_server_entry servers[]; |
| 437 | }; | 439 | }; |
| 438 | 440 | ||
| @@ -459,6 +461,9 @@ struct afs_volume { | |||
| 459 | rwlock_t servers_lock; /* Lock for ->servers */ | 461 | rwlock_t servers_lock; /* Lock for ->servers */ |
| 460 | unsigned int servers_seq; /* Incremented each time ->servers changes */ | 462 | unsigned int servers_seq; /* Incremented each time ->servers changes */ |
| 461 | 463 | ||
| 464 | unsigned cb_v_break; /* Break-everything counter. */ | ||
| 465 | rwlock_t cb_break_lock; | ||
| 466 | |||
| 462 | afs_voltype_t type; /* type of volume */ | 467 | afs_voltype_t type; /* type of volume */ |
| 463 | short error; | 468 | short error; |
| 464 | char type_force; /* force volume type (suppress R/O -> R/W) */ | 469 | char type_force; /* force volume type (suppress R/O -> R/W) */ |
| @@ -494,7 +499,7 @@ struct afs_vnode { | |||
| 494 | #endif | 499 | #endif |
| 495 | struct afs_permits __rcu *permit_cache; /* cache of permits so far obtained */ | 500 | struct afs_permits __rcu *permit_cache; /* cache of permits so far obtained */ |
| 496 | struct mutex io_lock; /* Lock for serialising I/O on this mutex */ | 501 | struct mutex io_lock; /* Lock for serialising I/O on this mutex */ |
| 497 | struct mutex validate_lock; /* lock for validating this vnode */ | 502 | struct rw_semaphore validate_lock; /* lock for validating this vnode */ |
| 498 | spinlock_t wb_lock; /* lock for wb_keys */ | 503 | spinlock_t wb_lock; /* lock for wb_keys */ |
| 499 | spinlock_t lock; /* waitqueue/flags lock */ | 504 | spinlock_t lock; /* waitqueue/flags lock */ |
| 500 | unsigned long flags; | 505 | unsigned long flags; |
| @@ -519,6 +524,7 @@ struct afs_vnode { | |||
| 519 | /* outstanding callback notification on this file */ | 524 | /* outstanding callback notification on this file */ |
| 520 | struct afs_cb_interest *cb_interest; /* Server on which this resides */ | 525 | struct afs_cb_interest *cb_interest; /* Server on which this resides */ |
| 521 | unsigned int cb_s_break; /* Mass break counter on ->server */ | 526 | unsigned int cb_s_break; /* Mass break counter on ->server */ |
| 527 | unsigned int cb_v_break; /* Mass break counter on ->volume */ | ||
| 522 | unsigned int cb_break; /* Break counter on vnode */ | 528 | unsigned int cb_break; /* Break counter on vnode */ |
| 523 | seqlock_t cb_lock; /* Lock for ->cb_interest, ->status, ->cb_*break */ | 529 | seqlock_t cb_lock; /* Lock for ->cb_interest, ->status, ->cb_*break */ |
| 524 | 530 | ||
| @@ -648,16 +654,29 @@ extern void afs_init_callback_state(struct afs_server *); | |||
| 648 | extern void afs_break_callback(struct afs_vnode *); | 654 | extern void afs_break_callback(struct afs_vnode *); |
| 649 | extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*); | 655 | extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*); |
| 650 | 656 | ||
| 651 | extern int afs_register_server_cb_interest(struct afs_vnode *, struct afs_server_entry *); | 657 | extern int afs_register_server_cb_interest(struct afs_vnode *, |
| 658 | struct afs_server_list *, unsigned int); | ||
| 652 | extern void afs_put_cb_interest(struct afs_net *, struct afs_cb_interest *); | 659 | extern void afs_put_cb_interest(struct afs_net *, struct afs_cb_interest *); |
| 653 | extern void afs_clear_callback_interests(struct afs_net *, struct afs_server_list *); | 660 | extern void afs_clear_callback_interests(struct afs_net *, struct afs_server_list *); |
| 654 | 661 | ||
| 655 | static inline struct afs_cb_interest *afs_get_cb_interest(struct afs_cb_interest *cbi) | 662 | static inline struct afs_cb_interest *afs_get_cb_interest(struct afs_cb_interest *cbi) |
| 656 | { | 663 | { |
| 657 | refcount_inc(&cbi->usage); | 664 | if (cbi) |
| 665 | refcount_inc(&cbi->usage); | ||
| 658 | return cbi; | 666 | return cbi; |
| 659 | } | 667 | } |
| 660 | 668 | ||
| 669 | static inline unsigned int afs_calc_vnode_cb_break(struct afs_vnode *vnode) | ||
| 670 | { | ||
| 671 | return vnode->cb_break + vnode->cb_s_break + vnode->cb_v_break; | ||
| 672 | } | ||
| 673 | |||
| 674 | static inline unsigned int afs_cb_break_sum(struct afs_vnode *vnode, | ||
| 675 | struct afs_cb_interest *cbi) | ||
| 676 | { | ||
| 677 | return vnode->cb_break + cbi->server->cb_s_break + vnode->volume->cb_v_break; | ||
| 678 | } | ||
| 679 | |||
| 661 | /* | 680 | /* |
| 662 | * cell.c | 681 | * cell.c |
| 663 | */ | 682 | */ |
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index ac0feac9d746..e065bc0768e6 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c | |||
| @@ -179,7 +179,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
| 179 | */ | 179 | */ |
| 180 | if (fc->flags & AFS_FS_CURSOR_VNOVOL) { | 180 | if (fc->flags & AFS_FS_CURSOR_VNOVOL) { |
| 181 | fc->ac.error = -EREMOTEIO; | 181 | fc->ac.error = -EREMOTEIO; |
| 182 | goto failed; | 182 | goto next_server; |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | write_lock(&vnode->volume->servers_lock); | 185 | write_lock(&vnode->volume->servers_lock); |
| @@ -201,7 +201,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) | |||
| 201 | */ | 201 | */ |
| 202 | if (vnode->volume->servers == fc->server_list) { | 202 | if (vnode->volume->servers == fc->server_list) { |
| 203 | fc->ac.error = -EREMOTEIO; | 203 | fc->ac.error = -EREMOTEIO; |
| 204 | goto failed; | 204 | goto next_server; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | /* Try again */ | 207 | /* Try again */ |
| @@ -350,8 +350,8 @@ use_server: | |||
| 350 | * break request before we've finished decoding the reply and | 350 | * break request before we've finished decoding the reply and |
| 351 | * installing the vnode. | 351 | * installing the vnode. |
| 352 | */ | 352 | */ |
| 353 | fc->ac.error = afs_register_server_cb_interest( | 353 | fc->ac.error = afs_register_server_cb_interest(vnode, fc->server_list, |
| 354 | vnode, &fc->server_list->servers[fc->index]); | 354 | fc->index); |
| 355 | if (fc->ac.error < 0) | 355 | if (fc->ac.error < 0) |
| 356 | goto failed; | 356 | goto failed; |
| 357 | 357 | ||
| @@ -369,8 +369,16 @@ use_server: | |||
| 369 | if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) { | 369 | if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) { |
| 370 | fc->ac.alist = afs_get_addrlist(alist); | 370 | fc->ac.alist = afs_get_addrlist(alist); |
| 371 | 371 | ||
| 372 | if (!afs_probe_fileserver(fc)) | 372 | if (!afs_probe_fileserver(fc)) { |
| 373 | goto failed; | 373 | switch (fc->ac.error) { |
| 374 | case -ENOMEM: | ||
| 375 | case -ERESTARTSYS: | ||
| 376 | case -EINTR: | ||
| 377 | goto failed; | ||
| 378 | default: | ||
| 379 | goto next_server; | ||
| 380 | } | ||
| 381 | } | ||
| 374 | } | 382 | } |
| 375 | 383 | ||
| 376 | if (!fc->ac.alist) | 384 | if (!fc->ac.alist) |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 5c6263972ec9..08735948f15d 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
| @@ -41,6 +41,7 @@ int afs_open_socket(struct afs_net *net) | |||
| 41 | { | 41 | { |
| 42 | struct sockaddr_rxrpc srx; | 42 | struct sockaddr_rxrpc srx; |
| 43 | struct socket *socket; | 43 | struct socket *socket; |
| 44 | unsigned int min_level; | ||
| 44 | int ret; | 45 | int ret; |
| 45 | 46 | ||
| 46 | _enter(""); | 47 | _enter(""); |
| @@ -60,6 +61,12 @@ int afs_open_socket(struct afs_net *net) | |||
| 60 | srx.transport.sin6.sin6_family = AF_INET6; | 61 | srx.transport.sin6.sin6_family = AF_INET6; |
| 61 | srx.transport.sin6.sin6_port = htons(AFS_CM_PORT); | 62 | srx.transport.sin6.sin6_port = htons(AFS_CM_PORT); |
| 62 | 63 | ||
| 64 | min_level = RXRPC_SECURITY_ENCRYPT; | ||
| 65 | ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL, | ||
| 66 | (void *)&min_level, sizeof(min_level)); | ||
| 67 | if (ret < 0) | ||
| 68 | goto error_2; | ||
| 69 | |||
| 63 | ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx)); | 70 | ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx)); |
| 64 | if (ret == -EADDRINUSE) { | 71 | if (ret == -EADDRINUSE) { |
| 65 | srx.transport.sin6.sin6_port = 0; | 72 | srx.transport.sin6.sin6_port = 0; |
| @@ -482,8 +489,12 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
| 482 | state = READ_ONCE(call->state); | 489 | state = READ_ONCE(call->state); |
| 483 | switch (ret) { | 490 | switch (ret) { |
| 484 | case 0: | 491 | case 0: |
| 485 | if (state == AFS_CALL_CL_PROC_REPLY) | 492 | if (state == AFS_CALL_CL_PROC_REPLY) { |
| 493 | if (call->cbi) | ||
| 494 | set_bit(AFS_SERVER_FL_MAY_HAVE_CB, | ||
| 495 | &call->cbi->server->flags); | ||
| 486 | goto call_complete; | 496 | goto call_complete; |
| 497 | } | ||
| 487 | ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY); | 498 | ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY); |
| 488 | goto done; | 499 | goto done; |
| 489 | case -EINPROGRESS: | 500 | case -EINPROGRESS: |
| @@ -493,11 +504,6 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
| 493 | case -ECONNABORTED: | 504 | case -ECONNABORTED: |
| 494 | ASSERTCMP(state, ==, AFS_CALL_COMPLETE); | 505 | ASSERTCMP(state, ==, AFS_CALL_COMPLETE); |
| 495 | goto done; | 506 | goto done; |
| 496 | case -ENOTCONN: | ||
| 497 | abort_code = RX_CALL_DEAD; | ||
| 498 | rxrpc_kernel_abort_call(call->net->socket, call->rxcall, | ||
| 499 | abort_code, ret, "KNC"); | ||
| 500 | goto local_abort; | ||
| 501 | case -ENOTSUPP: | 507 | case -ENOTSUPP: |
| 502 | abort_code = RXGEN_OPCODE; | 508 | abort_code = RXGEN_OPCODE; |
| 503 | rxrpc_kernel_abort_call(call->net->socket, call->rxcall, | 509 | rxrpc_kernel_abort_call(call->net->socket, call->rxcall, |
diff --git a/fs/afs/security.c b/fs/afs/security.c index cea2fff313dc..1992b0ffa543 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c | |||
| @@ -147,8 +147,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | |||
| 147 | break; | 147 | break; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | if (cb_break != (vnode->cb_break + | 150 | if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest)) { |
| 151 | vnode->cb_interest->server->cb_s_break)) { | ||
| 152 | changed = true; | 151 | changed = true; |
| 153 | break; | 152 | break; |
| 154 | } | 153 | } |
| @@ -178,7 +177,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | |||
| 178 | } | 177 | } |
| 179 | } | 178 | } |
| 180 | 179 | ||
| 181 | if (cb_break != (vnode->cb_break + vnode->cb_interest->server->cb_s_break)) | 180 | if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest)) |
| 182 | goto someone_else_changed_it; | 181 | goto someone_else_changed_it; |
| 183 | 182 | ||
| 184 | /* We need a ref on any permits list we want to copy as we'll have to | 183 | /* We need a ref on any permits list we want to copy as we'll have to |
| @@ -257,7 +256,7 @@ found: | |||
| 257 | 256 | ||
| 258 | spin_lock(&vnode->lock); | 257 | spin_lock(&vnode->lock); |
| 259 | zap = rcu_access_pointer(vnode->permit_cache); | 258 | zap = rcu_access_pointer(vnode->permit_cache); |
| 260 | if (cb_break == (vnode->cb_break + vnode->cb_interest->server->cb_s_break) && | 259 | if (cb_break == afs_cb_break_sum(vnode, vnode->cb_interest) && |
| 261 | zap == permits) | 260 | zap == permits) |
| 262 | rcu_assign_pointer(vnode->permit_cache, replacement); | 261 | rcu_assign_pointer(vnode->permit_cache, replacement); |
| 263 | else | 262 | else |
diff --git a/fs/afs/server.c b/fs/afs/server.c index 629c74986cff..3af4625e2f8c 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c | |||
| @@ -67,12 +67,6 @@ struct afs_server *afs_find_server(struct afs_net *net, | |||
| 67 | sizeof(struct in6_addr)); | 67 | sizeof(struct in6_addr)); |
| 68 | if (diff == 0) | 68 | if (diff == 0) |
| 69 | goto found; | 69 | goto found; |
| 70 | if (diff < 0) { | ||
| 71 | // TODO: Sort the list | ||
| 72 | //if (i == alist->nr_ipv4) | ||
| 73 | // goto not_found; | ||
| 74 | break; | ||
| 75 | } | ||
| 76 | } | 70 | } |
| 77 | } | 71 | } |
| 78 | } else { | 72 | } else { |
| @@ -87,17 +81,10 @@ struct afs_server *afs_find_server(struct afs_net *net, | |||
| 87 | (u32 __force)b->sin6_addr.s6_addr32[3]); | 81 | (u32 __force)b->sin6_addr.s6_addr32[3]); |
| 88 | if (diff == 0) | 82 | if (diff == 0) |
| 89 | goto found; | 83 | goto found; |
| 90 | if (diff < 0) { | ||
| 91 | // TODO: Sort the list | ||
| 92 | //if (i == 0) | ||
| 93 | // goto not_found; | ||
| 94 | break; | ||
| 95 | } | ||
| 96 | } | 84 | } |
| 97 | } | 85 | } |
| 98 | } | 86 | } |
| 99 | 87 | ||
| 100 | //not_found: | ||
| 101 | server = NULL; | 88 | server = NULL; |
| 102 | found: | 89 | found: |
| 103 | if (server && !atomic_inc_not_zero(&server->usage)) | 90 | if (server && !atomic_inc_not_zero(&server->usage)) |
| @@ -395,14 +382,16 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) | |||
| 395 | struct afs_addr_list *alist = rcu_access_pointer(server->addresses); | 382 | struct afs_addr_list *alist = rcu_access_pointer(server->addresses); |
| 396 | struct afs_addr_cursor ac = { | 383 | struct afs_addr_cursor ac = { |
| 397 | .alist = alist, | 384 | .alist = alist, |
| 398 | .addr = &alist->addrs[0], | ||
| 399 | .start = alist->index, | 385 | .start = alist->index, |
| 400 | .index = alist->index, | 386 | .index = 0, |
| 387 | .addr = &alist->addrs[alist->index], | ||
| 401 | .error = 0, | 388 | .error = 0, |
| 402 | }; | 389 | }; |
| 403 | _enter("%p", server); | 390 | _enter("%p", server); |
| 404 | 391 | ||
| 405 | afs_fs_give_up_all_callbacks(net, server, &ac, NULL); | 392 | if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags)) |
| 393 | afs_fs_give_up_all_callbacks(net, server, &ac, NULL); | ||
| 394 | |||
| 406 | call_rcu(&server->rcu, afs_server_rcu); | 395 | call_rcu(&server->rcu, afs_server_rcu); |
| 407 | afs_dec_servers_outstanding(net); | 396 | afs_dec_servers_outstanding(net); |
| 408 | } | 397 | } |
diff --git a/fs/afs/server_list.c b/fs/afs/server_list.c index 0f8dc4c8f07c..8a5760aa5832 100644 --- a/fs/afs/server_list.c +++ b/fs/afs/server_list.c | |||
| @@ -49,6 +49,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, | |||
| 49 | goto error; | 49 | goto error; |
| 50 | 50 | ||
| 51 | refcount_set(&slist->usage, 1); | 51 | refcount_set(&slist->usage, 1); |
| 52 | rwlock_init(&slist->lock); | ||
| 52 | 53 | ||
| 53 | /* Make sure a records exists for each server in the list. */ | 54 | /* Make sure a records exists for each server in the list. */ |
| 54 | for (i = 0; i < vldb->nr_servers; i++) { | 55 | for (i = 0; i < vldb->nr_servers; i++) { |
| @@ -64,9 +65,11 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, | |||
| 64 | goto error_2; | 65 | goto error_2; |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | /* Insertion-sort by server pointer */ | 68 | /* Insertion-sort by UUID */ |
| 68 | for (j = 0; j < slist->nr_servers; j++) | 69 | for (j = 0; j < slist->nr_servers; j++) |
| 69 | if (slist->servers[j].server >= server) | 70 | if (memcmp(&slist->servers[j].server->uuid, |
| 71 | &server->uuid, | ||
| 72 | sizeof(server->uuid)) >= 0) | ||
| 70 | break; | 73 | break; |
| 71 | if (j < slist->nr_servers) { | 74 | if (j < slist->nr_servers) { |
| 72 | if (slist->servers[j].server == server) { | 75 | if (slist->servers[j].server == server) { |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 65081ec3c36e..9e5d7966621c 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
| @@ -590,7 +590,7 @@ static void afs_i_init_once(void *_vnode) | |||
| 590 | memset(vnode, 0, sizeof(*vnode)); | 590 | memset(vnode, 0, sizeof(*vnode)); |
| 591 | inode_init_once(&vnode->vfs_inode); | 591 | inode_init_once(&vnode->vfs_inode); |
| 592 | mutex_init(&vnode->io_lock); | 592 | mutex_init(&vnode->io_lock); |
| 593 | mutex_init(&vnode->validate_lock); | 593 | init_rwsem(&vnode->validate_lock); |
| 594 | spin_lock_init(&vnode->wb_lock); | 594 | spin_lock_init(&vnode->wb_lock); |
| 595 | spin_lock_init(&vnode->lock); | 595 | spin_lock_init(&vnode->lock); |
| 596 | INIT_LIST_HEAD(&vnode->wb_keys); | 596 | INIT_LIST_HEAD(&vnode->wb_keys); |
| @@ -688,7 +688,7 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 688 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | 688 | if (afs_begin_vnode_operation(&fc, vnode, key)) { |
| 689 | fc.flags |= AFS_FS_CURSOR_NO_VSLEEP; | 689 | fc.flags |= AFS_FS_CURSOR_NO_VSLEEP; |
| 690 | while (afs_select_fileserver(&fc)) { | 690 | while (afs_select_fileserver(&fc)) { |
| 691 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 691 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 692 | afs_fs_get_volume_status(&fc, &vs); | 692 | afs_fs_get_volume_status(&fc, &vs); |
| 693 | } | 693 | } |
| 694 | 694 | ||
diff --git a/fs/afs/write.c b/fs/afs/write.c index c164698dc304..8b39e6ebb40b 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
| @@ -351,7 +351,7 @@ found_key: | |||
| 351 | ret = -ERESTARTSYS; | 351 | ret = -ERESTARTSYS; |
| 352 | if (afs_begin_vnode_operation(&fc, vnode, wbk->key)) { | 352 | if (afs_begin_vnode_operation(&fc, vnode, wbk->key)) { |
| 353 | while (afs_select_fileserver(&fc)) { | 353 | while (afs_select_fileserver(&fc)) { |
| 354 | fc.cb_break = vnode->cb_break + vnode->cb_s_break; | 354 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 355 | afs_fs_store_data(&fc, mapping, first, last, offset, to); | 355 | afs_fs_store_data(&fc, mapping, first, last, offset, to); |
| 356 | } | 356 | } |
| 357 | 357 | ||
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 513c357c734b..a6c0f54c48c3 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
| @@ -588,6 +588,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 588 | return 0; | 588 | return 0; |
| 589 | 589 | ||
| 590 | out_put_hidden_dir: | 590 | out_put_hidden_dir: |
| 591 | cancel_delayed_work_sync(&sbi->sync_work); | ||
| 591 | iput(sbi->hidden_dir); | 592 | iput(sbi->hidden_dir); |
| 592 | out_put_root: | 593 | out_put_root: |
| 593 | dput(sb->s_root); | 594 | dput(sb->s_root); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1b2ede6abcdf..1a76d751cf3c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -261,7 +261,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf, | |||
| 261 | * Inherently racy -- command line shares address space | 261 | * Inherently racy -- command line shares address space |
| 262 | * with code and data. | 262 | * with code and data. |
| 263 | */ | 263 | */ |
| 264 | rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0); | 264 | rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON); |
| 265 | if (rv <= 0) | 265 | if (rv <= 0) |
| 266 | goto out_free_page; | 266 | goto out_free_page; |
| 267 | 267 | ||
| @@ -279,7 +279,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf, | |||
| 279 | int nr_read; | 279 | int nr_read; |
| 280 | 280 | ||
| 281 | _count = min3(count, len, PAGE_SIZE); | 281 | _count = min3(count, len, PAGE_SIZE); |
| 282 | nr_read = access_remote_vm(mm, p, page, _count, 0); | 282 | nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON); |
| 283 | if (nr_read < 0) | 283 | if (nr_read < 0) |
| 284 | rv = nr_read; | 284 | rv = nr_read; |
| 285 | if (nr_read <= 0) | 285 | if (nr_read <= 0) |
| @@ -325,7 +325,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf, | |||
| 325 | bool final; | 325 | bool final; |
| 326 | 326 | ||
| 327 | _count = min3(count, len, PAGE_SIZE); | 327 | _count = min3(count, len, PAGE_SIZE); |
| 328 | nr_read = access_remote_vm(mm, p, page, _count, 0); | 328 | nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON); |
| 329 | if (nr_read < 0) | 329 | if (nr_read < 0) |
| 330 | rv = nr_read; | 330 | rv = nr_read; |
| 331 | if (nr_read <= 0) | 331 | if (nr_read <= 0) |
| @@ -946,7 +946,7 @@ static ssize_t environ_read(struct file *file, char __user *buf, | |||
| 946 | max_len = min_t(size_t, PAGE_SIZE, count); | 946 | max_len = min_t(size_t, PAGE_SIZE, count); |
| 947 | this_len = min(max_len, this_len); | 947 | this_len = min(max_len, this_len); |
| 948 | 948 | ||
| 949 | retval = access_remote_vm(mm, (env_start + src), page, this_len, 0); | 949 | retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON); |
| 950 | 950 | ||
| 951 | if (retval <= 0) { | 951 | if (retval <= 0) { |
| 952 | ret = retval; | 952 | ret = retval; |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 6930c63126c7..6d6e79c59e68 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
| @@ -1045,13 +1045,7 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) | |||
| 1045 | 1045 | ||
| 1046 | #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING | 1046 | #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING |
| 1047 | 1047 | ||
| 1048 | #ifdef CONFIG_S390 | 1048 | #define KVM_MAX_IRQ_ROUTES 4096 /* might need extension/rework in the future */ |
| 1049 | #define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that... | ||
| 1050 | #elif defined(CONFIG_ARM64) | ||
| 1051 | #define KVM_MAX_IRQ_ROUTES 4096 | ||
| 1052 | #else | ||
| 1053 | #define KVM_MAX_IRQ_ROUTES 1024 | ||
| 1054 | #endif | ||
| 1055 | 1049 | ||
| 1056 | bool kvm_arch_can_set_irq_routing(struct kvm *kvm); | 1050 | bool kvm_arch_can_set_irq_routing(struct kvm *kvm); |
| 1057 | int kvm_set_irq_routing(struct kvm *kvm, | 1051 | int kvm_set_irq_routing(struct kvm *kvm, |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 1ac1f06a4be6..c6fa9a255dbf 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -2466,6 +2466,13 @@ static inline vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma, | |||
| 2466 | return VM_FAULT_NOPAGE; | 2466 | return VM_FAULT_NOPAGE; |
| 2467 | } | 2467 | } |
| 2468 | 2468 | ||
| 2469 | static inline vm_fault_t vmf_error(int err) | ||
| 2470 | { | ||
| 2471 | if (err == -ENOMEM) | ||
| 2472 | return VM_FAULT_OOM; | ||
| 2473 | return VM_FAULT_SIGBUS; | ||
| 2474 | } | ||
| 2475 | |||
| 2469 | struct page *follow_page_mask(struct vm_area_struct *vma, | 2476 | struct page *follow_page_mask(struct vm_area_struct *vma, |
| 2470 | unsigned long address, unsigned int foll_flags, | 2477 | unsigned long address, unsigned int foll_flags, |
| 2471 | unsigned int *page_mask); | 2478 | unsigned int *page_mask); |
| @@ -2493,6 +2500,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, | |||
| 2493 | #define FOLL_MLOCK 0x1000 /* lock present pages */ | 2500 | #define FOLL_MLOCK 0x1000 /* lock present pages */ |
| 2494 | #define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */ | 2501 | #define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */ |
| 2495 | #define FOLL_COW 0x4000 /* internal GUP flag */ | 2502 | #define FOLL_COW 0x4000 /* internal GUP flag */ |
| 2503 | #define FOLL_ANON 0x8000 /* don't do file mappings */ | ||
| 2496 | 2504 | ||
| 2497 | static inline int vm_fault_to_errno(int vm_fault, int foll_flags) | 2505 | static inline int vm_fault_to_errno(int vm_fault, int foll_flags) |
| 2498 | { | 2506 | { |
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index b5b43f94f311..01b990e4b228 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h | |||
| @@ -312,7 +312,7 @@ void map_destroy(struct mtd_info *mtd); | |||
| 312 | ({ \ | 312 | ({ \ |
| 313 | int i, ret = 1; \ | 313 | int i, ret = 1; \ |
| 314 | for (i = 0; i < map_words(map); i++) { \ | 314 | for (i = 0; i < map_words(map); i++) { \ |
| 315 | if (((val1).x[i] & (val2).x[i]) != (val2).x[i]) { \ | 315 | if (((val1).x[i] & (val2).x[i]) != (val3).x[i]) { \ |
| 316 | ret = 0; \ | 316 | ret = 0; \ |
| 317 | break; \ | 317 | break; \ |
| 318 | } \ | 318 | } \ |
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 5dad59b31244..17c919436f48 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h | |||
| @@ -867,12 +867,18 @@ struct nand_op_instr { | |||
| 867 | * tBERS (during an erase) which all of them are u64 values that cannot be | 867 | * tBERS (during an erase) which all of them are u64 values that cannot be |
| 868 | * divided by usual kernel macros and must be handled with the special | 868 | * divided by usual kernel macros and must be handled with the special |
| 869 | * DIV_ROUND_UP_ULL() macro. | 869 | * DIV_ROUND_UP_ULL() macro. |
| 870 | * | ||
| 871 | * Cast to type of dividend is needed here to guarantee that the result won't | ||
| 872 | * be an unsigned long long when the dividend is an unsigned long (or smaller), | ||
| 873 | * which is what the compiler does when it sees ternary operator with 2 | ||
| 874 | * different return types (picks the largest type to make sure there's no | ||
| 875 | * loss). | ||
| 870 | */ | 876 | */ |
| 871 | #define __DIVIDE(dividend, divisor) ({ \ | 877 | #define __DIVIDE(dividend, divisor) ({ \ |
| 872 | sizeof(dividend) == sizeof(u32) ? \ | 878 | (__typeof__(dividend))(sizeof(dividend) <= sizeof(unsigned long) ? \ |
| 873 | DIV_ROUND_UP(dividend, divisor) : \ | 879 | DIV_ROUND_UP(dividend, divisor) : \ |
| 874 | DIV_ROUND_UP_ULL(dividend, divisor); \ | 880 | DIV_ROUND_UP_ULL(dividend, divisor)); \ |
| 875 | }) | 881 | }) |
| 876 | #define PSEC_TO_NSEC(x) __DIVIDE(x, 1000) | 882 | #define PSEC_TO_NSEC(x) __DIVIDE(x, 1000) |
| 877 | #define PSEC_TO_MSEC(x) __DIVIDE(x, 1000000000) | 883 | #define PSEC_TO_MSEC(x) __DIVIDE(x, 1000000000) |
| 878 | 884 | ||
diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index f0820554caa9..d0a341bc4540 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h | |||
| @@ -575,6 +575,48 @@ TRACE_EVENT(afs_protocol_error, | |||
| 575 | __entry->call, __entry->error, __entry->where) | 575 | __entry->call, __entry->error, __entry->where) |
| 576 | ); | 576 | ); |
| 577 | 577 | ||
| 578 | TRACE_EVENT(afs_cm_no_server, | ||
| 579 | TP_PROTO(struct afs_call *call, struct sockaddr_rxrpc *srx), | ||
| 580 | |||
| 581 | TP_ARGS(call, srx), | ||
| 582 | |||
| 583 | TP_STRUCT__entry( | ||
| 584 | __field(unsigned int, call ) | ||
| 585 | __field(unsigned int, op_id ) | ||
| 586 | __field_struct(struct sockaddr_rxrpc, srx ) | ||
| 587 | ), | ||
| 588 | |||
| 589 | TP_fast_assign( | ||
| 590 | __entry->call = call->debug_id; | ||
| 591 | __entry->op_id = call->operation_ID; | ||
| 592 | memcpy(&__entry->srx, srx, sizeof(__entry->srx)); | ||
| 593 | ), | ||
| 594 | |||
| 595 | TP_printk("c=%08x op=%u %pISpc", | ||
| 596 | __entry->call, __entry->op_id, &__entry->srx.transport) | ||
| 597 | ); | ||
| 598 | |||
| 599 | TRACE_EVENT(afs_cm_no_server_u, | ||
| 600 | TP_PROTO(struct afs_call *call, const uuid_t *uuid), | ||
| 601 | |||
| 602 | TP_ARGS(call, uuid), | ||
| 603 | |||
| 604 | TP_STRUCT__entry( | ||
| 605 | __field(unsigned int, call ) | ||
| 606 | __field(unsigned int, op_id ) | ||
| 607 | __field_struct(uuid_t, uuid ) | ||
| 608 | ), | ||
| 609 | |||
| 610 | TP_fast_assign( | ||
| 611 | __entry->call = call->debug_id; | ||
| 612 | __entry->op_id = call->operation_ID; | ||
| 613 | memcpy(&__entry->uuid, uuid, sizeof(__entry->uuid)); | ||
| 614 | ), | ||
| 615 | |||
| 616 | TP_printk("c=%08x op=%u %pU", | ||
| 617 | __entry->call, __entry->op_id, &__entry->uuid) | ||
| 618 | ); | ||
| 619 | |||
| 578 | #endif /* _TRACE_AFS_H */ | 620 | #endif /* _TRACE_AFS_H */ |
| 579 | 621 | ||
| 580 | /* This part must be outside protection */ | 622 | /* This part must be outside protection */ |
diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 7dd8f34c37df..fdcf88bcf0ea 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h | |||
| @@ -352,22 +352,6 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, | |||
| 352 | DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); | 352 | DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); |
| 353 | DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); | 353 | DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); |
| 354 | 354 | ||
| 355 | TRACE_EVENT(xen_mmu_flush_tlb_all, | ||
| 356 | TP_PROTO(int x), | ||
| 357 | TP_ARGS(x), | ||
| 358 | TP_STRUCT__entry(__array(char, x, 0)), | ||
| 359 | TP_fast_assign((void)x), | ||
| 360 | TP_printk("%s", "") | ||
| 361 | ); | ||
| 362 | |||
| 363 | TRACE_EVENT(xen_mmu_flush_tlb, | ||
| 364 | TP_PROTO(int x), | ||
| 365 | TP_ARGS(x), | ||
| 366 | TP_STRUCT__entry(__array(char, x, 0)), | ||
| 367 | TP_fast_assign((void)x), | ||
| 368 | TP_printk("%s", "") | ||
| 369 | ); | ||
| 370 | |||
| 371 | TRACE_EVENT(xen_mmu_flush_tlb_one_user, | 355 | TRACE_EVENT(xen_mmu_flush_tlb_one_user, |
| 372 | TP_PROTO(unsigned long addr), | 356 | TP_PROTO(unsigned long addr), |
| 373 | TP_ARGS(addr), | 357 | TP_ARGS(addr), |
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index da9e10c827df..43e0cbedc3a0 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
| @@ -1612,11 +1612,9 @@ static void set_iter_tags(struct radix_tree_iter *iter, | |||
| 1612 | static void __rcu **skip_siblings(struct radix_tree_node **nodep, | 1612 | static void __rcu **skip_siblings(struct radix_tree_node **nodep, |
| 1613 | void __rcu **slot, struct radix_tree_iter *iter) | 1613 | void __rcu **slot, struct radix_tree_iter *iter) |
| 1614 | { | 1614 | { |
| 1615 | void *sib = node_to_entry(slot - 1); | ||
| 1616 | |||
| 1617 | while (iter->index < iter->next_index) { | 1615 | while (iter->index < iter->next_index) { |
| 1618 | *nodep = rcu_dereference_raw(*slot); | 1616 | *nodep = rcu_dereference_raw(*slot); |
| 1619 | if (*nodep && *nodep != sib) | 1617 | if (*nodep && !is_sibling_entry(iter->node, *nodep)) |
| 1620 | return slot; | 1618 | return slot; |
| 1621 | slot++; | 1619 | slot++; |
| 1622 | iter->index = __radix_tree_iter_add(iter, 1); | 1620 | iter->index = __radix_tree_iter_add(iter, 1); |
| @@ -1631,7 +1629,7 @@ void __rcu **__radix_tree_next_slot(void __rcu **slot, | |||
| 1631 | struct radix_tree_iter *iter, unsigned flags) | 1629 | struct radix_tree_iter *iter, unsigned flags) |
| 1632 | { | 1630 | { |
| 1633 | unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK; | 1631 | unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK; |
| 1634 | struct radix_tree_node *node = rcu_dereference_raw(*slot); | 1632 | struct radix_tree_node *node; |
| 1635 | 1633 | ||
| 1636 | slot = skip_siblings(&node, slot, iter); | 1634 | slot = skip_siblings(&node, slot, iter); |
| 1637 | 1635 | ||
diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c index de16f7869fb1..6cd7d0740005 100644 --- a/lib/test_bitmap.c +++ b/lib/test_bitmap.c | |||
| @@ -331,23 +331,32 @@ static void noinline __init test_mem_optimisations(void) | |||
| 331 | unsigned int start, nbits; | 331 | unsigned int start, nbits; |
| 332 | 332 | ||
| 333 | for (start = 0; start < 1024; start += 8) { | 333 | for (start = 0; start < 1024; start += 8) { |
| 334 | memset(bmap1, 0x5a, sizeof(bmap1)); | ||
| 335 | memset(bmap2, 0x5a, sizeof(bmap2)); | ||
| 336 | for (nbits = 0; nbits < 1024 - start; nbits += 8) { | 334 | for (nbits = 0; nbits < 1024 - start; nbits += 8) { |
| 335 | memset(bmap1, 0x5a, sizeof(bmap1)); | ||
| 336 | memset(bmap2, 0x5a, sizeof(bmap2)); | ||
| 337 | |||
| 337 | bitmap_set(bmap1, start, nbits); | 338 | bitmap_set(bmap1, start, nbits); |
| 338 | __bitmap_set(bmap2, start, nbits); | 339 | __bitmap_set(bmap2, start, nbits); |
| 339 | if (!bitmap_equal(bmap1, bmap2, 1024)) | 340 | if (!bitmap_equal(bmap1, bmap2, 1024)) { |
| 340 | printk("set not equal %d %d\n", start, nbits); | 341 | printk("set not equal %d %d\n", start, nbits); |
| 341 | if (!__bitmap_equal(bmap1, bmap2, 1024)) | 342 | failed_tests++; |
| 343 | } | ||
| 344 | if (!__bitmap_equal(bmap1, bmap2, 1024)) { | ||
| 342 | printk("set not __equal %d %d\n", start, nbits); | 345 | printk("set not __equal %d %d\n", start, nbits); |
| 346 | failed_tests++; | ||
| 347 | } | ||
| 343 | 348 | ||
| 344 | bitmap_clear(bmap1, start, nbits); | 349 | bitmap_clear(bmap1, start, nbits); |
| 345 | __bitmap_clear(bmap2, start, nbits); | 350 | __bitmap_clear(bmap2, start, nbits); |
| 346 | if (!bitmap_equal(bmap1, bmap2, 1024)) | 351 | if (!bitmap_equal(bmap1, bmap2, 1024)) { |
| 347 | printk("clear not equal %d %d\n", start, nbits); | 352 | printk("clear not equal %d %d\n", start, nbits); |
| 348 | if (!__bitmap_equal(bmap1, bmap2, 1024)) | 353 | failed_tests++; |
| 354 | } | ||
| 355 | if (!__bitmap_equal(bmap1, bmap2, 1024)) { | ||
| 349 | printk("clear not __equal %d %d\n", start, | 356 | printk("clear not __equal %d %d\n", start, |
| 350 | nbits); | 357 | nbits); |
| 358 | failed_tests++; | ||
| 359 | } | ||
| 351 | } | 360 | } |
| 352 | } | 361 | } |
| 353 | } | 362 | } |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 30c0cb8cc9bc..23920c5ff728 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -1669,19 +1669,22 @@ char *pointer_string(char *buf, char *end, const void *ptr, | |||
| 1669 | return number(buf, end, (unsigned long int)ptr, spec); | 1669 | return number(buf, end, (unsigned long int)ptr, spec); |
| 1670 | } | 1670 | } |
| 1671 | 1671 | ||
| 1672 | static bool have_filled_random_ptr_key __read_mostly; | 1672 | static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); |
| 1673 | static siphash_key_t ptr_key __read_mostly; | 1673 | static siphash_key_t ptr_key __read_mostly; |
| 1674 | 1674 | ||
| 1675 | static void fill_random_ptr_key(struct random_ready_callback *unused) | 1675 | static void enable_ptr_key_workfn(struct work_struct *work) |
| 1676 | { | 1676 | { |
| 1677 | get_random_bytes(&ptr_key, sizeof(ptr_key)); | 1677 | get_random_bytes(&ptr_key, sizeof(ptr_key)); |
| 1678 | /* | 1678 | /* Needs to run from preemptible context */ |
| 1679 | * have_filled_random_ptr_key==true is dependent on get_random_bytes(). | 1679 | static_branch_disable(¬_filled_random_ptr_key); |
| 1680 | * ptr_to_id() needs to see have_filled_random_ptr_key==true | 1680 | } |
| 1681 | * after get_random_bytes() returns. | 1681 | |
| 1682 | */ | 1682 | static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn); |
| 1683 | smp_mb(); | 1683 | |
| 1684 | WRITE_ONCE(have_filled_random_ptr_key, true); | 1684 | static void fill_random_ptr_key(struct random_ready_callback *unused) |
| 1685 | { | ||
| 1686 | /* This may be in an interrupt handler. */ | ||
| 1687 | queue_work(system_unbound_wq, &enable_ptr_key_work); | ||
| 1685 | } | 1688 | } |
| 1686 | 1689 | ||
| 1687 | static struct random_ready_callback random_ready = { | 1690 | static struct random_ready_callback random_ready = { |
| @@ -1695,7 +1698,8 @@ static int __init initialize_ptr_random(void) | |||
| 1695 | if (!ret) { | 1698 | if (!ret) { |
| 1696 | return 0; | 1699 | return 0; |
| 1697 | } else if (ret == -EALREADY) { | 1700 | } else if (ret == -EALREADY) { |
| 1698 | fill_random_ptr_key(&random_ready); | 1701 | /* This is in preemptible context */ |
| 1702 | enable_ptr_key_workfn(&enable_ptr_key_work); | ||
| 1699 | return 0; | 1703 | return 0; |
| 1700 | } | 1704 | } |
| 1701 | 1705 | ||
| @@ -1709,7 +1713,7 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) | |||
| 1709 | unsigned long hashval; | 1713 | unsigned long hashval; |
| 1710 | const int default_width = 2 * sizeof(ptr); | 1714 | const int default_width = 2 * sizeof(ptr); |
| 1711 | 1715 | ||
| 1712 | if (unlikely(!have_filled_random_ptr_key)) { | 1716 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { |
| 1713 | spec.field_width = default_width; | 1717 | spec.field_width = default_width; |
| 1714 | /* string length must be less than default_width */ | 1718 | /* string length must be less than default_width */ |
| 1715 | return string(buf, end, "(ptrval)", spec); | 1719 | return string(buf, end, "(ptrval)", spec); |
diff --git a/mm/Kconfig b/mm/Kconfig index d5004d82a1d6..e14c01513bfd 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
| @@ -636,6 +636,7 @@ config DEFERRED_STRUCT_PAGE_INIT | |||
| 636 | default n | 636 | default n |
| 637 | depends on NO_BOOTMEM | 637 | depends on NO_BOOTMEM |
| 638 | depends on !FLATMEM | 638 | depends on !FLATMEM |
| 639 | depends on !NEED_PER_CPU_KM | ||
| 639 | help | 640 | help |
| 640 | Ordinarily all struct pages are initialised during early boot in a | 641 | Ordinarily all struct pages are initialised during early boot in a |
| 641 | single thread. On very large machines this can take a considerable | 642 | single thread. On very large machines this can take a considerable |
| @@ -544,6 +544,9 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags) | |||
| 544 | if (vm_flags & (VM_IO | VM_PFNMAP)) | 544 | if (vm_flags & (VM_IO | VM_PFNMAP)) |
| 545 | return -EFAULT; | 545 | return -EFAULT; |
| 546 | 546 | ||
| 547 | if (gup_flags & FOLL_ANON && !vma_is_anonymous(vma)) | ||
| 548 | return -EFAULT; | ||
| 549 | |||
| 547 | if (write) { | 550 | if (write) { |
| 548 | if (!(vm_flags & VM_WRITE)) { | 551 | if (!(vm_flags & VM_WRITE)) { |
| 549 | if (!(gup_flags & FOLL_FORCE)) | 552 | if (!(gup_flags & FOLL_FORCE)) |
| @@ -1327,7 +1327,7 @@ static inline int mlock_future_check(struct mm_struct *mm, | |||
| 1327 | static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) | 1327 | static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) |
| 1328 | { | 1328 | { |
| 1329 | if (S_ISREG(inode->i_mode)) | 1329 | if (S_ISREG(inode->i_mode)) |
| 1330 | return inode->i_sb->s_maxbytes; | 1330 | return MAX_LFS_FILESIZE; |
| 1331 | 1331 | ||
| 1332 | if (S_ISBLK(inode->i_mode)) | 1332 | if (S_ISBLK(inode->i_mode)) |
| 1333 | return MAX_LFS_FILESIZE; | 1333 | return MAX_LFS_FILESIZE; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4cafe6a19167..be5817df0a9d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -4576,6 +4576,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
| 4576 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 4576 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
| 4577 | { | 4577 | { |
| 4578 | struct sock *sk = sock->sk; | 4578 | struct sock *sk = sock->sk; |
| 4579 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 4579 | u16 family; | 4580 | u16 family; |
| 4580 | int err; | 4581 | int err; |
| 4581 | 4582 | ||
| @@ -4587,11 +4588,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4587 | family = sk->sk_family; | 4588 | family = sk->sk_family; |
| 4588 | if (family == PF_INET || family == PF_INET6) { | 4589 | if (family == PF_INET || family == PF_INET6) { |
| 4589 | char *addrp; | 4590 | char *addrp; |
| 4590 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 4591 | struct common_audit_data ad; | 4591 | struct common_audit_data ad; |
| 4592 | struct lsm_network_audit net = {0,}; | 4592 | struct lsm_network_audit net = {0,}; |
| 4593 | struct sockaddr_in *addr4 = NULL; | 4593 | struct sockaddr_in *addr4 = NULL; |
| 4594 | struct sockaddr_in6 *addr6 = NULL; | 4594 | struct sockaddr_in6 *addr6 = NULL; |
| 4595 | u16 family_sa = address->sa_family; | ||
| 4595 | unsigned short snum; | 4596 | unsigned short snum; |
| 4596 | u32 sid, node_perm; | 4597 | u32 sid, node_perm; |
| 4597 | 4598 | ||
| @@ -4601,11 +4602,20 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4601 | * need to check address->sa_family as it is possible to have | 4602 | * need to check address->sa_family as it is possible to have |
| 4602 | * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. | 4603 | * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET. |
| 4603 | */ | 4604 | */ |
| 4604 | switch (address->sa_family) { | 4605 | switch (family_sa) { |
| 4606 | case AF_UNSPEC: | ||
| 4605 | case AF_INET: | 4607 | case AF_INET: |
| 4606 | if (addrlen < sizeof(struct sockaddr_in)) | 4608 | if (addrlen < sizeof(struct sockaddr_in)) |
| 4607 | return -EINVAL; | 4609 | return -EINVAL; |
| 4608 | addr4 = (struct sockaddr_in *)address; | 4610 | addr4 = (struct sockaddr_in *)address; |
| 4611 | if (family_sa == AF_UNSPEC) { | ||
| 4612 | /* see __inet_bind(), we only want to allow | ||
| 4613 | * AF_UNSPEC if the address is INADDR_ANY | ||
| 4614 | */ | ||
| 4615 | if (addr4->sin_addr.s_addr != htonl(INADDR_ANY)) | ||
| 4616 | goto err_af; | ||
| 4617 | family_sa = AF_INET; | ||
| 4618 | } | ||
| 4609 | snum = ntohs(addr4->sin_port); | 4619 | snum = ntohs(addr4->sin_port); |
| 4610 | addrp = (char *)&addr4->sin_addr.s_addr; | 4620 | addrp = (char *)&addr4->sin_addr.s_addr; |
| 4611 | break; | 4621 | break; |
| @@ -4617,15 +4627,14 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4617 | addrp = (char *)&addr6->sin6_addr.s6_addr; | 4627 | addrp = (char *)&addr6->sin6_addr.s6_addr; |
| 4618 | break; | 4628 | break; |
| 4619 | default: | 4629 | default: |
| 4620 | /* Note that SCTP services expect -EINVAL, whereas | 4630 | goto err_af; |
| 4621 | * others expect -EAFNOSUPPORT. | ||
| 4622 | */ | ||
| 4623 | if (sksec->sclass == SECCLASS_SCTP_SOCKET) | ||
| 4624 | return -EINVAL; | ||
| 4625 | else | ||
| 4626 | return -EAFNOSUPPORT; | ||
| 4627 | } | 4631 | } |
| 4628 | 4632 | ||
| 4633 | ad.type = LSM_AUDIT_DATA_NET; | ||
| 4634 | ad.u.net = &net; | ||
| 4635 | ad.u.net->sport = htons(snum); | ||
| 4636 | ad.u.net->family = family_sa; | ||
| 4637 | |||
| 4629 | if (snum) { | 4638 | if (snum) { |
| 4630 | int low, high; | 4639 | int low, high; |
| 4631 | 4640 | ||
| @@ -4637,10 +4646,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4637 | snum, &sid); | 4646 | snum, &sid); |
| 4638 | if (err) | 4647 | if (err) |
| 4639 | goto out; | 4648 | goto out; |
| 4640 | ad.type = LSM_AUDIT_DATA_NET; | ||
| 4641 | ad.u.net = &net; | ||
| 4642 | ad.u.net->sport = htons(snum); | ||
| 4643 | ad.u.net->family = family; | ||
| 4644 | err = avc_has_perm(&selinux_state, | 4649 | err = avc_has_perm(&selinux_state, |
| 4645 | sksec->sid, sid, | 4650 | sksec->sid, sid, |
| 4646 | sksec->sclass, | 4651 | sksec->sclass, |
| @@ -4672,16 +4677,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4672 | break; | 4677 | break; |
| 4673 | } | 4678 | } |
| 4674 | 4679 | ||
| 4675 | err = sel_netnode_sid(addrp, family, &sid); | 4680 | err = sel_netnode_sid(addrp, family_sa, &sid); |
| 4676 | if (err) | 4681 | if (err) |
| 4677 | goto out; | 4682 | goto out; |
| 4678 | 4683 | ||
| 4679 | ad.type = LSM_AUDIT_DATA_NET; | 4684 | if (family_sa == AF_INET) |
| 4680 | ad.u.net = &net; | ||
| 4681 | ad.u.net->sport = htons(snum); | ||
| 4682 | ad.u.net->family = family; | ||
| 4683 | |||
| 4684 | if (address->sa_family == AF_INET) | ||
| 4685 | ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; | 4685 | ad.u.net->v4info.saddr = addr4->sin_addr.s_addr; |
| 4686 | else | 4686 | else |
| 4687 | ad.u.net->v6info.saddr = addr6->sin6_addr; | 4687 | ad.u.net->v6info.saddr = addr6->sin6_addr; |
| @@ -4694,6 +4694,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 4694 | } | 4694 | } |
| 4695 | out: | 4695 | out: |
| 4696 | return err; | 4696 | return err; |
| 4697 | err_af: | ||
| 4698 | /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */ | ||
| 4699 | if (sksec->sclass == SECCLASS_SCTP_SOCKET) | ||
| 4700 | return -EINVAL; | ||
| 4701 | return -EAFNOSUPPORT; | ||
| 4697 | } | 4702 | } |
| 4698 | 4703 | ||
| 4699 | /* This supports connect(2) and SCTP connect services such as sctp_connectx(3) | 4704 | /* This supports connect(2) and SCTP connect services such as sctp_connectx(3) |
| @@ -4771,7 +4776,7 @@ static int selinux_socket_connect_helper(struct socket *sock, | |||
| 4771 | ad.type = LSM_AUDIT_DATA_NET; | 4776 | ad.type = LSM_AUDIT_DATA_NET; |
| 4772 | ad.u.net = &net; | 4777 | ad.u.net = &net; |
| 4773 | ad.u.net->dport = htons(snum); | 4778 | ad.u.net->dport = htons(snum); |
| 4774 | ad.u.net->family = sk->sk_family; | 4779 | ad.u.net->family = address->sa_family; |
| 4775 | err = avc_has_perm(&selinux_state, | 4780 | err = avc_has_perm(&selinux_state, |
| 4776 | sksec->sid, sid, sksec->sclass, perm, &ad); | 4781 | sksec->sid, sid, sksec->sclass, perm, &ad); |
| 4777 | if (err) | 4782 | if (err) |
| @@ -5272,6 +5277,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname, | |||
| 5272 | while (walk_size < addrlen) { | 5277 | while (walk_size < addrlen) { |
| 5273 | addr = addr_buf; | 5278 | addr = addr_buf; |
| 5274 | switch (addr->sa_family) { | 5279 | switch (addr->sa_family) { |
| 5280 | case AF_UNSPEC: | ||
| 5275 | case AF_INET: | 5281 | case AF_INET: |
| 5276 | len = sizeof(struct sockaddr_in); | 5282 | len = sizeof(struct sockaddr_in); |
| 5277 | break; | 5283 | break; |
| @@ -5279,7 +5285,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname, | |||
| 5279 | len = sizeof(struct sockaddr_in6); | 5285 | len = sizeof(struct sockaddr_in6); |
| 5280 | break; | 5286 | break; |
| 5281 | default: | 5287 | default: |
| 5282 | return -EAFNOSUPPORT; | 5288 | return -EINVAL; |
| 5283 | } | 5289 | } |
| 5284 | 5290 | ||
| 5285 | err = -EINVAL; | 5291 | err = -EINVAL; |
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index a848836a5de0..507fd5210c1c 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c | |||
| @@ -396,8 +396,7 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, | |||
| 396 | if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || | 396 | if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || |
| 397 | copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) | 397 | copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) |
| 398 | goto error; | 398 | goto error; |
| 399 | if (get_user(data->owner, &data32->owner) || | 399 | if (get_user(data->owner, &data32->owner)) |
| 400 | get_user(data->type, &data32->type)) | ||
| 401 | goto error; | 400 | goto error; |
| 402 | switch (data->type) { | 401 | switch (data->type) { |
| 403 | case SNDRV_CTL_ELEM_TYPE_BOOLEAN: | 402 | case SNDRV_CTL_ELEM_TYPE_BOOLEAN: |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b0c8c79848a9..a0c93b9c9a28 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -2210,6 +2210,8 @@ static struct snd_pci_quirk power_save_blacklist[] = { | |||
| 2210 | SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0), | 2210 | SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0), |
| 2211 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ | 2211 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ |
| 2212 | SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0), | 2212 | SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0), |
| 2213 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */ | ||
| 2214 | SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0), | ||
| 2213 | /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */ | 2215 | /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */ |
| 2214 | SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0), | 2216 | SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0), |
| 2215 | {} | 2217 | {} |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2dd34dd77447..01a6643fc7d4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -2363,6 +2363,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |||
| 2363 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), | 2363 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), |
| 2364 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), | 2364 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), |
| 2365 | SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), | 2365 | SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), |
| 2366 | SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950), | ||
| 2366 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), | 2367 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), |
| 2367 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), | 2368 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), |
| 2368 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530), | 2369 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530), |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 344d7b069d59..bb5ab7a7dfa5 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
| @@ -967,6 +967,14 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, | |||
| 967 | } | 967 | } |
| 968 | break; | 968 | break; |
| 969 | 969 | ||
| 970 | case USB_ID(0x0d8c, 0x0103): | ||
| 971 | if (!strcmp(kctl->id.name, "PCM Playback Volume")) { | ||
| 972 | usb_audio_info(chip, | ||
| 973 | "set volume quirk for CM102-A+/102S+\n"); | ||
| 974 | cval->min = -256; | ||
| 975 | } | ||
| 976 | break; | ||
| 977 | |||
| 970 | case USB_ID(0x0471, 0x0101): | 978 | case USB_ID(0x0471, 0x0101): |
| 971 | case USB_ID(0x0471, 0x0104): | 979 | case USB_ID(0x0471, 0x0104): |
| 972 | case USB_ID(0x0471, 0x0105): | 980 | case USB_ID(0x0471, 0x0105): |
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 956be9f7c72a..5ed334575fc7 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
| @@ -576,7 +576,7 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
| 576 | 576 | ||
| 577 | if (protocol == UAC_VERSION_1) { | 577 | if (protocol == UAC_VERSION_1) { |
| 578 | attributes = csep->bmAttributes; | 578 | attributes = csep->bmAttributes; |
| 579 | } else { | 579 | } else if (protocol == UAC_VERSION_2) { |
| 580 | struct uac2_iso_endpoint_descriptor *csep2 = | 580 | struct uac2_iso_endpoint_descriptor *csep2 = |
| 581 | (struct uac2_iso_endpoint_descriptor *) csep; | 581 | (struct uac2_iso_endpoint_descriptor *) csep; |
| 582 | 582 | ||
| @@ -585,6 +585,13 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
| 585 | /* emulate the endpoint attributes of a v1 device */ | 585 | /* emulate the endpoint attributes of a v1 device */ |
| 586 | if (csep2->bmControls & UAC2_CONTROL_PITCH) | 586 | if (csep2->bmControls & UAC2_CONTROL_PITCH) |
| 587 | attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; | 587 | attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; |
| 588 | } else { /* UAC_VERSION_3 */ | ||
| 589 | struct uac3_iso_endpoint_descriptor *csep3 = | ||
| 590 | (struct uac3_iso_endpoint_descriptor *) csep; | ||
| 591 | |||
| 592 | /* emulate the endpoint attributes of a v1 device */ | ||
| 593 | if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH) | ||
| 594 | attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; | ||
| 588 | } | 595 | } |
| 589 | 596 | ||
| 590 | return attributes; | 597 | return attributes; |
diff --git a/tools/include/linux/spinlock.h b/tools/include/linux/spinlock.h index b21b586b9854..1738c0391da4 100644 --- a/tools/include/linux/spinlock.h +++ b/tools/include/linux/spinlock.h | |||
| @@ -6,8 +6,9 @@ | |||
| 6 | #include <stdbool.h> | 6 | #include <stdbool.h> |
| 7 | 7 | ||
| 8 | #define spinlock_t pthread_mutex_t | 8 | #define spinlock_t pthread_mutex_t |
| 9 | #define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; | 9 | #define DEFINE_SPINLOCK(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER |
| 10 | #define __SPIN_LOCK_UNLOCKED(x) (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER | 10 | #define __SPIN_LOCK_UNLOCKED(x) (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER |
| 11 | #define spin_lock_init(x) pthread_mutex_init(x, NULL) | ||
| 11 | 12 | ||
| 12 | #define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x) | 13 | #define spin_lock_irqsave(x, f) (void)f, pthread_mutex_lock(x) |
| 13 | #define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x) | 14 | #define spin_unlock_irqrestore(x, f) (void)f, pthread_mutex_unlock(x) |
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile index fa7ee369b3c9..db66f8a0d4be 100644 --- a/tools/testing/radix-tree/Makefile +++ b/tools/testing/radix-tree/Makefile | |||
| @@ -17,7 +17,7 @@ ifeq ($(BUILD), 32) | |||
| 17 | LDFLAGS += -m32 | 17 | LDFLAGS += -m32 |
| 18 | endif | 18 | endif |
| 19 | 19 | ||
| 20 | targets: mapshift $(TARGETS) | 20 | targets: generated/map-shift.h $(TARGETS) |
| 21 | 21 | ||
| 22 | main: $(OFILES) | 22 | main: $(OFILES) |
| 23 | 23 | ||
| @@ -42,9 +42,7 @@ radix-tree.c: ../../../lib/radix-tree.c | |||
| 42 | idr.c: ../../../lib/idr.c | 42 | idr.c: ../../../lib/idr.c |
| 43 | sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ | 43 | sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ |
| 44 | 44 | ||
| 45 | .PHONY: mapshift | 45 | generated/map-shift.h: |
| 46 | |||
| 47 | mapshift: | ||
| 48 | @if ! grep -qws $(SHIFT) generated/map-shift.h; then \ | 46 | @if ! grep -qws $(SHIFT) generated/map-shift.h; then \ |
| 49 | echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \ | 47 | echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \ |
| 50 | generated/map-shift.h; \ | 48 | generated/map-shift.h; \ |
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c index 59245b3d587c..7bf405638b0b 100644 --- a/tools/testing/radix-tree/multiorder.c +++ b/tools/testing/radix-tree/multiorder.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/radix-tree.h> | 16 | #include <linux/radix-tree.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
| 19 | #include <pthread.h> | ||
| 19 | 20 | ||
| 20 | #include "test.h" | 21 | #include "test.h" |
| 21 | 22 | ||
| @@ -624,6 +625,67 @@ static void multiorder_account(void) | |||
| 624 | item_kill_tree(&tree); | 625 | item_kill_tree(&tree); |
| 625 | } | 626 | } |
| 626 | 627 | ||
| 628 | bool stop_iteration = false; | ||
| 629 | |||
| 630 | static void *creator_func(void *ptr) | ||
| 631 | { | ||
| 632 | /* 'order' is set up to ensure we have sibling entries */ | ||
| 633 | unsigned int order = RADIX_TREE_MAP_SHIFT - 1; | ||
| 634 | struct radix_tree_root *tree = ptr; | ||
| 635 | int i; | ||
| 636 | |||
| 637 | for (i = 0; i < 10000; i++) { | ||
| 638 | item_insert_order(tree, 0, order); | ||
| 639 | item_delete_rcu(tree, 0); | ||
| 640 | } | ||
| 641 | |||
| 642 | stop_iteration = true; | ||
| 643 | return NULL; | ||
| 644 | } | ||
| 645 | |||
| 646 | static void *iterator_func(void *ptr) | ||
| 647 | { | ||
| 648 | struct radix_tree_root *tree = ptr; | ||
| 649 | struct radix_tree_iter iter; | ||
| 650 | struct item *item; | ||
| 651 | void **slot; | ||
| 652 | |||
| 653 | while (!stop_iteration) { | ||
| 654 | rcu_read_lock(); | ||
| 655 | radix_tree_for_each_slot(slot, tree, &iter, 0) { | ||
| 656 | item = radix_tree_deref_slot(slot); | ||
| 657 | |||
| 658 | if (!item) | ||
| 659 | continue; | ||
| 660 | if (radix_tree_deref_retry(item)) { | ||
| 661 | slot = radix_tree_iter_retry(&iter); | ||
| 662 | continue; | ||
| 663 | } | ||
| 664 | |||
| 665 | item_sanity(item, iter.index); | ||
| 666 | } | ||
| 667 | rcu_read_unlock(); | ||
| 668 | } | ||
| 669 | return NULL; | ||
| 670 | } | ||
| 671 | |||
| 672 | static void multiorder_iteration_race(void) | ||
| 673 | { | ||
| 674 | const int num_threads = sysconf(_SC_NPROCESSORS_ONLN); | ||
| 675 | pthread_t worker_thread[num_threads]; | ||
| 676 | RADIX_TREE(tree, GFP_KERNEL); | ||
| 677 | int i; | ||
| 678 | |||
| 679 | pthread_create(&worker_thread[0], NULL, &creator_func, &tree); | ||
| 680 | for (i = 1; i < num_threads; i++) | ||
| 681 | pthread_create(&worker_thread[i], NULL, &iterator_func, &tree); | ||
| 682 | |||
| 683 | for (i = 0; i < num_threads; i++) | ||
| 684 | pthread_join(worker_thread[i], NULL); | ||
| 685 | |||
| 686 | item_kill_tree(&tree); | ||
| 687 | } | ||
| 688 | |||
| 627 | void multiorder_checks(void) | 689 | void multiorder_checks(void) |
| 628 | { | 690 | { |
| 629 | int i; | 691 | int i; |
| @@ -644,6 +706,7 @@ void multiorder_checks(void) | |||
| 644 | multiorder_join(); | 706 | multiorder_join(); |
| 645 | multiorder_split(); | 707 | multiorder_split(); |
| 646 | multiorder_account(); | 708 | multiorder_account(); |
| 709 | multiorder_iteration_race(); | ||
| 647 | 710 | ||
| 648 | radix_tree_cpu_dead(0); | 711 | radix_tree_cpu_dead(0); |
| 649 | } | 712 | } |
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c index 5978ab1f403d..def6015570b2 100644 --- a/tools/testing/radix-tree/test.c +++ b/tools/testing/radix-tree/test.c | |||
| @@ -75,6 +75,25 @@ int item_delete(struct radix_tree_root *root, unsigned long index) | |||
| 75 | return 0; | 75 | return 0; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | static void item_free_rcu(struct rcu_head *head) | ||
| 79 | { | ||
| 80 | struct item *item = container_of(head, struct item, rcu_head); | ||
| 81 | |||
| 82 | free(item); | ||
| 83 | } | ||
| 84 | |||
| 85 | int item_delete_rcu(struct radix_tree_root *root, unsigned long index) | ||
| 86 | { | ||
| 87 | struct item *item = radix_tree_delete(root, index); | ||
| 88 | |||
| 89 | if (item) { | ||
| 90 | item_sanity(item, index); | ||
| 91 | call_rcu(&item->rcu_head, item_free_rcu); | ||
| 92 | return 1; | ||
| 93 | } | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 78 | void item_check_present(struct radix_tree_root *root, unsigned long index) | 97 | void item_check_present(struct radix_tree_root *root, unsigned long index) |
| 79 | { | 98 | { |
| 80 | struct item *item; | 99 | struct item *item; |
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h index d9c031dbeb1a..31f1d9b6f506 100644 --- a/tools/testing/radix-tree/test.h +++ b/tools/testing/radix-tree/test.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/rcupdate.h> | 5 | #include <linux/rcupdate.h> |
| 6 | 6 | ||
| 7 | struct item { | 7 | struct item { |
| 8 | struct rcu_head rcu_head; | ||
| 8 | unsigned long index; | 9 | unsigned long index; |
| 9 | unsigned int order; | 10 | unsigned int order; |
| 10 | }; | 11 | }; |
| @@ -12,9 +13,11 @@ struct item { | |||
| 12 | struct item *item_create(unsigned long index, unsigned int order); | 13 | struct item *item_create(unsigned long index, unsigned int order); |
| 13 | int __item_insert(struct radix_tree_root *root, struct item *item); | 14 | int __item_insert(struct radix_tree_root *root, struct item *item); |
| 14 | int item_insert(struct radix_tree_root *root, unsigned long index); | 15 | int item_insert(struct radix_tree_root *root, unsigned long index); |
| 16 | void item_sanity(struct item *item, unsigned long index); | ||
| 15 | int item_insert_order(struct radix_tree_root *root, unsigned long index, | 17 | int item_insert_order(struct radix_tree_root *root, unsigned long index, |
| 16 | unsigned order); | 18 | unsigned order); |
| 17 | int item_delete(struct radix_tree_root *root, unsigned long index); | 19 | int item_delete(struct radix_tree_root *root, unsigned long index); |
| 20 | int item_delete_rcu(struct radix_tree_root *root, unsigned long index); | ||
| 18 | struct item *item_lookup(struct radix_tree_root *root, unsigned long index); | 21 | struct item *item_lookup(struct radix_tree_root *root, unsigned long index); |
| 19 | 22 | ||
| 20 | void item_check_present(struct radix_tree_root *root, unsigned long index); | 23 | void item_check_present(struct radix_tree_root *root, unsigned long index); |
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 2ddcc96ae456..d9d00319b07c 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile | |||
| @@ -15,7 +15,7 @@ LIBKVM += $(LIBKVM_$(UNAME_M)) | |||
| 15 | 15 | ||
| 16 | INSTALL_HDR_PATH = $(top_srcdir)/usr | 16 | INSTALL_HDR_PATH = $(top_srcdir)/usr |
| 17 | LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/ | 17 | LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/ |
| 18 | CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) | 18 | CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -I.. |
| 19 | 19 | ||
| 20 | # After inclusion, $(OUTPUT) is defined and | 20 | # After inclusion, $(OUTPUT) is defined and |
| 21 | # $(TEST_GEN_PROGS) starts with $(OUTPUT)/ | 21 | # $(TEST_GEN_PROGS) starts with $(OUTPUT)/ |
diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h index 7ab98e41324f..ac53730b30aa 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <errno.h> | 19 | #include <errno.h> |
| 20 | #include <unistd.h> | 20 | #include <unistd.h> |
| 21 | #include <fcntl.h> | 21 | #include <fcntl.h> |
| 22 | #include "kselftest.h" | ||
| 22 | 23 | ||
| 23 | ssize_t test_write(int fd, const void *buf, size_t count); | 24 | ssize_t test_write(int fd, const void *buf, size_t count); |
| 24 | ssize_t test_read(int fd, void *buf, size_t count); | 25 | ssize_t test_read(int fd, void *buf, size_t count); |
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 2cedfda181d4..37e2a787d2fc 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c | |||
| @@ -50,8 +50,8 @@ int kvm_check_cap(long cap) | |||
| 50 | int kvm_fd; | 50 | int kvm_fd; |
| 51 | 51 | ||
| 52 | kvm_fd = open(KVM_DEV_PATH, O_RDONLY); | 52 | kvm_fd = open(KVM_DEV_PATH, O_RDONLY); |
| 53 | TEST_ASSERT(kvm_fd >= 0, "open %s failed, rc: %i errno: %i", | 53 | if (kvm_fd < 0) |
| 54 | KVM_DEV_PATH, kvm_fd, errno); | 54 | exit(KSFT_SKIP); |
| 55 | 55 | ||
| 56 | ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, cap); | 56 | ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, cap); |
| 57 | TEST_ASSERT(ret != -1, "KVM_CHECK_EXTENSION IOCTL failed,\n" | 57 | TEST_ASSERT(ret != -1, "KVM_CHECK_EXTENSION IOCTL failed,\n" |
| @@ -91,8 +91,8 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) | |||
| 91 | 91 | ||
| 92 | vm->mode = mode; | 92 | vm->mode = mode; |
| 93 | kvm_fd = open(KVM_DEV_PATH, perm); | 93 | kvm_fd = open(KVM_DEV_PATH, perm); |
| 94 | TEST_ASSERT(kvm_fd >= 0, "open %s failed, rc: %i errno: %i", | 94 | if (kvm_fd < 0) |
| 95 | KVM_DEV_PATH, kvm_fd, errno); | 95 | exit(KSFT_SKIP); |
| 96 | 96 | ||
| 97 | /* Create VM. */ | 97 | /* Create VM. */ |
| 98 | vm->fd = ioctl(kvm_fd, KVM_CREATE_VM, NULL); | 98 | vm->fd = ioctl(kvm_fd, KVM_CREATE_VM, NULL); |
| @@ -418,8 +418,8 @@ struct kvm_cpuid2 *kvm_get_supported_cpuid(void) | |||
| 418 | 418 | ||
| 419 | cpuid = allocate_kvm_cpuid2(); | 419 | cpuid = allocate_kvm_cpuid2(); |
| 420 | kvm_fd = open(KVM_DEV_PATH, O_RDONLY); | 420 | kvm_fd = open(KVM_DEV_PATH, O_RDONLY); |
| 421 | TEST_ASSERT(kvm_fd >= 0, "open %s failed, rc: %i errno: %i", | 421 | if (kvm_fd < 0) |
| 422 | KVM_DEV_PATH, kvm_fd, errno); | 422 | exit(KSFT_SKIP); |
| 423 | 423 | ||
| 424 | ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid); | 424 | ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid); |
| 425 | TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n", | 425 | TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n", |
| @@ -675,8 +675,8 @@ static int vcpu_mmap_sz(void) | |||
| 675 | int dev_fd, ret; | 675 | int dev_fd, ret; |
| 676 | 676 | ||
| 677 | dev_fd = open(KVM_DEV_PATH, O_RDONLY); | 677 | dev_fd = open(KVM_DEV_PATH, O_RDONLY); |
| 678 | TEST_ASSERT(dev_fd >= 0, "%s open %s failed, rc: %i errno: %i", | 678 | if (dev_fd < 0) |
| 679 | __func__, KVM_DEV_PATH, dev_fd, errno); | 679 | exit(KSFT_SKIP); |
| 680 | 680 | ||
| 681 | ret = ioctl(dev_fd, KVM_GET_VCPU_MMAP_SIZE, NULL); | 681 | ret = ioctl(dev_fd, KVM_GET_VCPU_MMAP_SIZE, NULL); |
| 682 | TEST_ASSERT(ret >= sizeof(struct kvm_run), | 682 | TEST_ASSERT(ret >= sizeof(struct kvm_run), |
diff --git a/tools/testing/selftests/kvm/sync_regs_test.c b/tools/testing/selftests/kvm/sync_regs_test.c index 428e9473f5e2..eae1ece3c31b 100644 --- a/tools/testing/selftests/kvm/sync_regs_test.c +++ b/tools/testing/selftests/kvm/sync_regs_test.c | |||
| @@ -85,6 +85,9 @@ static void compare_vcpu_events(struct kvm_vcpu_events *left, | |||
| 85 | { | 85 | { |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | #define TEST_SYNC_FIELDS (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS) | ||
| 89 | #define INVALID_SYNC_FIELD 0x80000000 | ||
| 90 | |||
| 88 | int main(int argc, char *argv[]) | 91 | int main(int argc, char *argv[]) |
| 89 | { | 92 | { |
| 90 | struct kvm_vm *vm; | 93 | struct kvm_vm *vm; |
| @@ -98,9 +101,14 @@ int main(int argc, char *argv[]) | |||
| 98 | setbuf(stdout, NULL); | 101 | setbuf(stdout, NULL); |
| 99 | 102 | ||
| 100 | cap = kvm_check_cap(KVM_CAP_SYNC_REGS); | 103 | cap = kvm_check_cap(KVM_CAP_SYNC_REGS); |
| 101 | TEST_ASSERT((unsigned long)cap == KVM_SYNC_X86_VALID_FIELDS, | 104 | if ((cap & TEST_SYNC_FIELDS) != TEST_SYNC_FIELDS) { |
| 102 | "KVM_CAP_SYNC_REGS (0x%x) != KVM_SYNC_X86_VALID_FIELDS (0x%lx)\n", | 105 | fprintf(stderr, "KVM_CAP_SYNC_REGS not supported, skipping test\n"); |
| 103 | cap, KVM_SYNC_X86_VALID_FIELDS); | 106 | exit(KSFT_SKIP); |
| 107 | } | ||
| 108 | if ((cap & INVALID_SYNC_FIELD) != 0) { | ||
| 109 | fprintf(stderr, "The \"invalid\" field is not invalid, skipping test\n"); | ||
| 110 | exit(KSFT_SKIP); | ||
| 111 | } | ||
| 104 | 112 | ||
| 105 | /* Create VM */ | 113 | /* Create VM */ |
| 106 | vm = vm_create_default(VCPU_ID, guest_code); | 114 | vm = vm_create_default(VCPU_ID, guest_code); |
| @@ -108,7 +116,14 @@ int main(int argc, char *argv[]) | |||
| 108 | run = vcpu_state(vm, VCPU_ID); | 116 | run = vcpu_state(vm, VCPU_ID); |
| 109 | 117 | ||
| 110 | /* Request reading invalid register set from VCPU. */ | 118 | /* Request reading invalid register set from VCPU. */ |
| 111 | run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS << 1; | 119 | run->kvm_valid_regs = INVALID_SYNC_FIELD; |
| 120 | rv = _vcpu_run(vm, VCPU_ID); | ||
| 121 | TEST_ASSERT(rv < 0 && errno == EINVAL, | ||
| 122 | "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", | ||
| 123 | rv); | ||
| 124 | vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0; | ||
| 125 | |||
| 126 | run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS; | ||
| 112 | rv = _vcpu_run(vm, VCPU_ID); | 127 | rv = _vcpu_run(vm, VCPU_ID); |
| 113 | TEST_ASSERT(rv < 0 && errno == EINVAL, | 128 | TEST_ASSERT(rv < 0 && errno == EINVAL, |
| 114 | "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", | 129 | "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n", |
| @@ -116,7 +131,14 @@ int main(int argc, char *argv[]) | |||
| 116 | vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0; | 131 | vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0; |
| 117 | 132 | ||
| 118 | /* Request setting invalid register set into VCPU. */ | 133 | /* Request setting invalid register set into VCPU. */ |
| 119 | run->kvm_dirty_regs = KVM_SYNC_X86_VALID_FIELDS << 1; | 134 | run->kvm_dirty_regs = INVALID_SYNC_FIELD; |
| 135 | rv = _vcpu_run(vm, VCPU_ID); | ||
| 136 | TEST_ASSERT(rv < 0 && errno == EINVAL, | ||
| 137 | "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", | ||
| 138 | rv); | ||
| 139 | vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0; | ||
| 140 | |||
| 141 | run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS; | ||
| 120 | rv = _vcpu_run(vm, VCPU_ID); | 142 | rv = _vcpu_run(vm, VCPU_ID); |
| 121 | TEST_ASSERT(rv < 0 && errno == EINVAL, | 143 | TEST_ASSERT(rv < 0 && errno == EINVAL, |
| 122 | "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", | 144 | "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n", |
| @@ -125,7 +147,7 @@ int main(int argc, char *argv[]) | |||
| 125 | 147 | ||
| 126 | /* Request and verify all valid register sets. */ | 148 | /* Request and verify all valid register sets. */ |
| 127 | /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */ | 149 | /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */ |
| 128 | run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS; | 150 | run->kvm_valid_regs = TEST_SYNC_FIELDS; |
| 129 | rv = _vcpu_run(vm, VCPU_ID); | 151 | rv = _vcpu_run(vm, VCPU_ID); |
| 130 | TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, | 152 | TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, |
| 131 | "Unexpected exit reason: %u (%s),\n", | 153 | "Unexpected exit reason: %u (%s),\n", |
| @@ -146,7 +168,7 @@ int main(int argc, char *argv[]) | |||
| 146 | run->s.regs.sregs.apic_base = 1 << 11; | 168 | run->s.regs.sregs.apic_base = 1 << 11; |
| 147 | /* TODO run->s.regs.events.XYZ = ABC; */ | 169 | /* TODO run->s.regs.events.XYZ = ABC; */ |
| 148 | 170 | ||
| 149 | run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS; | 171 | run->kvm_valid_regs = TEST_SYNC_FIELDS; |
| 150 | run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS; | 172 | run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS; |
| 151 | rv = _vcpu_run(vm, VCPU_ID); | 173 | rv = _vcpu_run(vm, VCPU_ID); |
| 152 | TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, | 174 | TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, |
| @@ -172,7 +194,7 @@ int main(int argc, char *argv[]) | |||
| 172 | /* Clear kvm_dirty_regs bits, verify new s.regs values are | 194 | /* Clear kvm_dirty_regs bits, verify new s.regs values are |
| 173 | * overwritten with existing guest values. | 195 | * overwritten with existing guest values. |
| 174 | */ | 196 | */ |
| 175 | run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS; | 197 | run->kvm_valid_regs = TEST_SYNC_FIELDS; |
| 176 | run->kvm_dirty_regs = 0; | 198 | run->kvm_dirty_regs = 0; |
| 177 | run->s.regs.regs.r11 = 0xDEADBEEF; | 199 | run->s.regs.regs.r11 = 0xDEADBEEF; |
| 178 | rv = _vcpu_run(vm, VCPU_ID); | 200 | rv = _vcpu_run(vm, VCPU_ID); |
| @@ -211,7 +233,7 @@ int main(int argc, char *argv[]) | |||
| 211 | * with kvm_sync_regs values. | 233 | * with kvm_sync_regs values. |
| 212 | */ | 234 | */ |
| 213 | run->kvm_valid_regs = 0; | 235 | run->kvm_valid_regs = 0; |
| 214 | run->kvm_dirty_regs = KVM_SYNC_X86_VALID_FIELDS; | 236 | run->kvm_dirty_regs = TEST_SYNC_FIELDS; |
| 215 | run->s.regs.regs.r11 = 0xBBBB; | 237 | run->s.regs.regs.r11 = 0xBBBB; |
| 216 | rv = _vcpu_run(vm, VCPU_ID); | 238 | rv = _vcpu_run(vm, VCPU_ID); |
| 217 | TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, | 239 | TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, |
diff --git a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c index 8f7f62093add..aaa633263b2c 100644 --- a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c +++ b/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c | |||
| @@ -189,8 +189,8 @@ int main(int argc, char *argv[]) | |||
| 189 | struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); | 189 | struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); |
| 190 | 190 | ||
| 191 | if (!(entry->ecx & CPUID_VMX)) { | 191 | if (!(entry->ecx & CPUID_VMX)) { |
| 192 | printf("nested VMX not enabled, skipping test"); | 192 | fprintf(stderr, "nested VMX not enabled, skipping test\n"); |
| 193 | return 0; | 193 | exit(KSFT_SKIP); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | vm = vm_create_default_vmx(VCPU_ID, (void *) l1_guest_code); | 196 | vm = vm_create_default_vmx(VCPU_ID, (void *) l1_guest_code); |
diff --git a/virt/kvm/arm/vgic/vgic-debug.c b/virt/kvm/arm/vgic/vgic-debug.c index 10b38178cff2..4ffc0b5e6105 100644 --- a/virt/kvm/arm/vgic/vgic-debug.c +++ b/virt/kvm/arm/vgic/vgic-debug.c | |||
| @@ -211,6 +211,7 @@ static int vgic_debug_show(struct seq_file *s, void *v) | |||
| 211 | struct vgic_state_iter *iter = (struct vgic_state_iter *)v; | 211 | struct vgic_state_iter *iter = (struct vgic_state_iter *)v; |
| 212 | struct vgic_irq *irq; | 212 | struct vgic_irq *irq; |
| 213 | struct kvm_vcpu *vcpu = NULL; | 213 | struct kvm_vcpu *vcpu = NULL; |
| 214 | unsigned long flags; | ||
| 214 | 215 | ||
| 215 | if (iter->dist_id == 0) { | 216 | if (iter->dist_id == 0) { |
| 216 | print_dist_state(s, &kvm->arch.vgic); | 217 | print_dist_state(s, &kvm->arch.vgic); |
| @@ -227,9 +228,9 @@ static int vgic_debug_show(struct seq_file *s, void *v) | |||
| 227 | irq = &kvm->arch.vgic.spis[iter->intid - VGIC_NR_PRIVATE_IRQS]; | 228 | irq = &kvm->arch.vgic.spis[iter->intid - VGIC_NR_PRIVATE_IRQS]; |
| 228 | } | 229 | } |
| 229 | 230 | ||
| 230 | spin_lock(&irq->irq_lock); | 231 | spin_lock_irqsave(&irq->irq_lock, flags); |
| 231 | print_irq_state(s, irq, vcpu); | 232 | print_irq_state(s, irq, vcpu); |
| 232 | spin_unlock(&irq->irq_lock); | 233 | spin_unlock_irqrestore(&irq->irq_lock, flags); |
| 233 | 234 | ||
| 234 | return 0; | 235 | return 0; |
| 235 | } | 236 | } |
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index a8f07243aa9f..4ed79c939fb4 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c | |||
| @@ -52,6 +52,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, | |||
| 52 | { | 52 | { |
| 53 | struct vgic_dist *dist = &kvm->arch.vgic; | 53 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 54 | struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq; | 54 | struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq; |
| 55 | unsigned long flags; | ||
| 55 | int ret; | 56 | int ret; |
| 56 | 57 | ||
| 57 | /* In this case there is no put, since we keep the reference. */ | 58 | /* In this case there is no put, since we keep the reference. */ |
| @@ -71,7 +72,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, | |||
| 71 | irq->intid = intid; | 72 | irq->intid = intid; |
| 72 | irq->target_vcpu = vcpu; | 73 | irq->target_vcpu = vcpu; |
| 73 | 74 | ||
| 74 | spin_lock(&dist->lpi_list_lock); | 75 | spin_lock_irqsave(&dist->lpi_list_lock, flags); |
| 75 | 76 | ||
| 76 | /* | 77 | /* |
| 77 | * There could be a race with another vgic_add_lpi(), so we need to | 78 | * There could be a race with another vgic_add_lpi(), so we need to |
| @@ -99,7 +100,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, | |||
| 99 | dist->lpi_list_count++; | 100 | dist->lpi_list_count++; |
| 100 | 101 | ||
| 101 | out_unlock: | 102 | out_unlock: |
| 102 | spin_unlock(&dist->lpi_list_lock); | 103 | spin_unlock_irqrestore(&dist->lpi_list_lock, flags); |
| 103 | 104 | ||
| 104 | /* | 105 | /* |
| 105 | * We "cache" the configuration table entries in our struct vgic_irq's. | 106 | * We "cache" the configuration table entries in our struct vgic_irq's. |
| @@ -280,8 +281,8 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq, | |||
| 280 | int ret; | 281 | int ret; |
| 281 | unsigned long flags; | 282 | unsigned long flags; |
| 282 | 283 | ||
| 283 | ret = kvm_read_guest(kvm, propbase + irq->intid - GIC_LPI_OFFSET, | 284 | ret = kvm_read_guest_lock(kvm, propbase + irq->intid - GIC_LPI_OFFSET, |
| 284 | &prop, 1); | 285 | &prop, 1); |
| 285 | 286 | ||
| 286 | if (ret) | 287 | if (ret) |
| 287 | return ret; | 288 | return ret; |
| @@ -315,6 +316,7 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr) | |||
| 315 | { | 316 | { |
| 316 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | 317 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; |
| 317 | struct vgic_irq *irq; | 318 | struct vgic_irq *irq; |
| 319 | unsigned long flags; | ||
| 318 | u32 *intids; | 320 | u32 *intids; |
| 319 | int irq_count, i = 0; | 321 | int irq_count, i = 0; |
| 320 | 322 | ||
| @@ -330,7 +332,7 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr) | |||
| 330 | if (!intids) | 332 | if (!intids) |
| 331 | return -ENOMEM; | 333 | return -ENOMEM; |
| 332 | 334 | ||
| 333 | spin_lock(&dist->lpi_list_lock); | 335 | spin_lock_irqsave(&dist->lpi_list_lock, flags); |
| 334 | list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) { | 336 | list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) { |
| 335 | if (i == irq_count) | 337 | if (i == irq_count) |
| 336 | break; | 338 | break; |
| @@ -339,7 +341,7 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr) | |||
| 339 | continue; | 341 | continue; |
| 340 | intids[i++] = irq->intid; | 342 | intids[i++] = irq->intid; |
| 341 | } | 343 | } |
| 342 | spin_unlock(&dist->lpi_list_lock); | 344 | spin_unlock_irqrestore(&dist->lpi_list_lock, flags); |
| 343 | 345 | ||
| 344 | *intid_ptr = intids; | 346 | *intid_ptr = intids; |
| 345 | return i; | 347 | return i; |
| @@ -348,10 +350,11 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr) | |||
| 348 | static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu) | 350 | static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu) |
| 349 | { | 351 | { |
| 350 | int ret = 0; | 352 | int ret = 0; |
| 353 | unsigned long flags; | ||
| 351 | 354 | ||
| 352 | spin_lock(&irq->irq_lock); | 355 | spin_lock_irqsave(&irq->irq_lock, flags); |
| 353 | irq->target_vcpu = vcpu; | 356 | irq->target_vcpu = vcpu; |
| 354 | spin_unlock(&irq->irq_lock); | 357 | spin_unlock_irqrestore(&irq->irq_lock, flags); |
| 355 | 358 | ||
| 356 | if (irq->hw) { | 359 | if (irq->hw) { |
| 357 | struct its_vlpi_map map; | 360 | struct its_vlpi_map map; |
| @@ -441,8 +444,9 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu) | |||
| 441 | * this very same byte in the last iteration. Reuse that. | 444 | * this very same byte in the last iteration. Reuse that. |
| 442 | */ | 445 | */ |
| 443 | if (byte_offset != last_byte_offset) { | 446 | if (byte_offset != last_byte_offset) { |
| 444 | ret = kvm_read_guest(vcpu->kvm, pendbase + byte_offset, | 447 | ret = kvm_read_guest_lock(vcpu->kvm, |
| 445 | &pendmask, 1); | 448 | pendbase + byte_offset, |
| 449 | &pendmask, 1); | ||
| 446 | if (ret) { | 450 | if (ret) { |
| 447 | kfree(intids); | 451 | kfree(intids); |
| 448 | return ret; | 452 | return ret; |
| @@ -786,7 +790,7 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id, | |||
| 786 | return false; | 790 | return false; |
| 787 | 791 | ||
| 788 | /* Each 1st level entry is represented by a 64-bit value. */ | 792 | /* Each 1st level entry is represented by a 64-bit value. */ |
| 789 | if (kvm_read_guest(its->dev->kvm, | 793 | if (kvm_read_guest_lock(its->dev->kvm, |
| 790 | BASER_ADDRESS(baser) + index * sizeof(indirect_ptr), | 794 | BASER_ADDRESS(baser) + index * sizeof(indirect_ptr), |
| 791 | &indirect_ptr, sizeof(indirect_ptr))) | 795 | &indirect_ptr, sizeof(indirect_ptr))) |
| 792 | return false; | 796 | return false; |
| @@ -1367,8 +1371,8 @@ static void vgic_its_process_commands(struct kvm *kvm, struct vgic_its *its) | |||
| 1367 | cbaser = CBASER_ADDRESS(its->cbaser); | 1371 | cbaser = CBASER_ADDRESS(its->cbaser); |
| 1368 | 1372 | ||
| 1369 | while (its->cwriter != its->creadr) { | 1373 | while (its->cwriter != its->creadr) { |
| 1370 | int ret = kvm_read_guest(kvm, cbaser + its->creadr, | 1374 | int ret = kvm_read_guest_lock(kvm, cbaser + its->creadr, |
| 1371 | cmd_buf, ITS_CMD_SIZE); | 1375 | cmd_buf, ITS_CMD_SIZE); |
| 1372 | /* | 1376 | /* |
| 1373 | * If kvm_read_guest() fails, this could be due to the guest | 1377 | * If kvm_read_guest() fails, this could be due to the guest |
| 1374 | * programming a bogus value in CBASER or something else going | 1378 | * programming a bogus value in CBASER or something else going |
| @@ -1893,7 +1897,7 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz, | |||
| 1893 | int next_offset; | 1897 | int next_offset; |
| 1894 | size_t byte_offset; | 1898 | size_t byte_offset; |
| 1895 | 1899 | ||
| 1896 | ret = kvm_read_guest(kvm, gpa, entry, esz); | 1900 | ret = kvm_read_guest_lock(kvm, gpa, entry, esz); |
| 1897 | if (ret) | 1901 | if (ret) |
| 1898 | return ret; | 1902 | return ret; |
| 1899 | 1903 | ||
| @@ -2263,7 +2267,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz) | |||
| 2263 | int ret; | 2267 | int ret; |
| 2264 | 2268 | ||
| 2265 | BUG_ON(esz > sizeof(val)); | 2269 | BUG_ON(esz > sizeof(val)); |
| 2266 | ret = kvm_read_guest(kvm, gpa, &val, esz); | 2270 | ret = kvm_read_guest_lock(kvm, gpa, &val, esz); |
| 2267 | if (ret) | 2271 | if (ret) |
| 2268 | return ret; | 2272 | return ret; |
| 2269 | val = le64_to_cpu(val); | 2273 | val = le64_to_cpu(val); |
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index c7423f3768e5..bdcf8e7a6161 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c | |||
| @@ -344,7 +344,7 @@ retry: | |||
| 344 | bit_nr = irq->intid % BITS_PER_BYTE; | 344 | bit_nr = irq->intid % BITS_PER_BYTE; |
| 345 | ptr = pendbase + byte_offset; | 345 | ptr = pendbase + byte_offset; |
| 346 | 346 | ||
| 347 | ret = kvm_read_guest(kvm, ptr, &val, 1); | 347 | ret = kvm_read_guest_lock(kvm, ptr, &val, 1); |
| 348 | if (ret) | 348 | if (ret) |
| 349 | return ret; | 349 | return ret; |
| 350 | 350 | ||
| @@ -397,7 +397,7 @@ int vgic_v3_save_pending_tables(struct kvm *kvm) | |||
| 397 | ptr = pendbase + byte_offset; | 397 | ptr = pendbase + byte_offset; |
| 398 | 398 | ||
| 399 | if (byte_offset != last_byte_offset) { | 399 | if (byte_offset != last_byte_offset) { |
| 400 | ret = kvm_read_guest(kvm, ptr, &val, 1); | 400 | ret = kvm_read_guest_lock(kvm, ptr, &val, 1); |
| 401 | if (ret) | 401 | if (ret) |
| 402 | return ret; | 402 | return ret; |
| 403 | last_byte_offset = byte_offset; | 403 | last_byte_offset = byte_offset; |
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index 97bfba8d9a59..33c8325c8f35 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c | |||
| @@ -43,9 +43,13 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = { | |||
| 43 | * kvm->lock (mutex) | 43 | * kvm->lock (mutex) |
| 44 | * its->cmd_lock (mutex) | 44 | * its->cmd_lock (mutex) |
| 45 | * its->its_lock (mutex) | 45 | * its->its_lock (mutex) |
| 46 | * vgic_cpu->ap_list_lock | 46 | * vgic_cpu->ap_list_lock must be taken with IRQs disabled |
| 47 | * kvm->lpi_list_lock | 47 | * kvm->lpi_list_lock must be taken with IRQs disabled |
| 48 | * vgic_irq->irq_lock | 48 | * vgic_irq->irq_lock must be taken with IRQs disabled |
| 49 | * | ||
| 50 | * As the ap_list_lock might be taken from the timer interrupt handler, | ||
| 51 | * we have to disable IRQs before taking this lock and everything lower | ||
| 52 | * than it. | ||
| 49 | * | 53 | * |
| 50 | * If you need to take multiple locks, always take the upper lock first, | 54 | * If you need to take multiple locks, always take the upper lock first, |
| 51 | * then the lower ones, e.g. first take the its_lock, then the irq_lock. | 55 | * then the lower ones, e.g. first take the its_lock, then the irq_lock. |
| @@ -72,8 +76,9 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid) | |||
| 72 | { | 76 | { |
| 73 | struct vgic_dist *dist = &kvm->arch.vgic; | 77 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 74 | struct vgic_irq *irq = NULL; | 78 | struct vgic_irq *irq = NULL; |
| 79 | unsigned long flags; | ||
| 75 | 80 | ||
| 76 | spin_lock(&dist->lpi_list_lock); | 81 | spin_lock_irqsave(&dist->lpi_list_lock, flags); |
| 77 | 82 | ||
| 78 | list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) { | 83 | list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) { |
| 79 | if (irq->intid != intid) | 84 | if (irq->intid != intid) |
| @@ -89,7 +94,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid) | |||
| 89 | irq = NULL; | 94 | irq = NULL; |
| 90 | 95 | ||
| 91 | out_unlock: | 96 | out_unlock: |
| 92 | spin_unlock(&dist->lpi_list_lock); | 97 | spin_unlock_irqrestore(&dist->lpi_list_lock, flags); |
| 93 | 98 | ||
| 94 | return irq; | 99 | return irq; |
| 95 | } | 100 | } |
| @@ -134,19 +139,20 @@ static void vgic_irq_release(struct kref *ref) | |||
| 134 | void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) | 139 | void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) |
| 135 | { | 140 | { |
| 136 | struct vgic_dist *dist = &kvm->arch.vgic; | 141 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 142 | unsigned long flags; | ||
| 137 | 143 | ||
| 138 | if (irq->intid < VGIC_MIN_LPI) | 144 | if (irq->intid < VGIC_MIN_LPI) |
| 139 | return; | 145 | return; |
| 140 | 146 | ||
| 141 | spin_lock(&dist->lpi_list_lock); | 147 | spin_lock_irqsave(&dist->lpi_list_lock, flags); |
| 142 | if (!kref_put(&irq->refcount, vgic_irq_release)) { | 148 | if (!kref_put(&irq->refcount, vgic_irq_release)) { |
| 143 | spin_unlock(&dist->lpi_list_lock); | 149 | spin_unlock_irqrestore(&dist->lpi_list_lock, flags); |
| 144 | return; | 150 | return; |
| 145 | }; | 151 | }; |
| 146 | 152 | ||
| 147 | list_del(&irq->lpi_list); | 153 | list_del(&irq->lpi_list); |
| 148 | dist->lpi_list_count--; | 154 | dist->lpi_list_count--; |
| 149 | spin_unlock(&dist->lpi_list_lock); | 155 | spin_unlock_irqrestore(&dist->lpi_list_lock, flags); |
| 150 | 156 | ||
| 151 | kfree(irq); | 157 | kfree(irq); |
| 152 | } | 158 | } |
