diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-17 13:11:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-17 13:11:44 -0400 |
| commit | 3e9245c5fa3092de19b95f03817b02469bcf146c (patch) | |
| tree | a388e64d6cd075d20b355e9e5810ea7f4c361556 | |
| parent | 305bb55212822f13ddbfcb7518d999c6369942ba (diff) | |
| parent | 2e68adcd2fb21b7188ba449f0fab3bee2910e500 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 fixes from Martin Schwidefsky:
- a fix for the vfio ccw translation code
- update an incorrect email address in the MAINTAINERS file
- fix a division by zero oops in the cpum_sf code found by trinity
- two fixes for the error handling of the qdio code
- several spectre related patches to convert all left-over indirect
branches in the kernel to expoline branches
- update defconfigs to avoid warnings due to the netfilter Kconfig
changes
- avoid several compiler warnings in the kexec_file code for s390
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/qdio: don't release memory in qdio_setup_irq()
s390/qdio: fix access to uninitialized qdio_q fields
s390/cpum_sf: ensure sample frequency of perf event attributes is non-zero
s390: use expoline thunks in the BPF JIT
s390: extend expoline to BC instructions
s390: remove indirect branch from do_softirq_own_stack
s390: move spectre sysfs attribute code
s390/kernel: use expoline for indirect branches
s390/ftrace: use expoline for indirect branches
s390/lib: use expoline for indirect branches
s390/crc32-vx: use expoline for indirect branches
s390: move expoline assembler macros to a header
vfio: ccw: fix cleanup if cp_prefetch fails
s390/kexec_file: add declaration of purgatory related globals
s390: update defconfigs
MAINTAINERS: update s390 zcrypt maintainers email address
| -rw-r--r-- | MAINTAINERS | 2 | ||||
| -rw-r--r-- | arch/s390/configs/debug_defconfig | 9 | ||||
| -rw-r--r-- | arch/s390/configs/performance_defconfig | 8 | ||||
| -rw-r--r-- | arch/s390/crypto/crc32be-vx.S | 5 | ||||
| -rw-r--r-- | arch/s390/crypto/crc32le-vx.S | 4 | ||||
| -rw-r--r-- | arch/s390/include/asm/nospec-insn.h | 196 | ||||
| -rw-r--r-- | arch/s390/include/asm/purgatory.h | 6 | ||||
| -rw-r--r-- | arch/s390/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/asm-offsets.c | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/base.S | 24 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.S | 105 | ||||
| -rw-r--r-- | arch/s390/kernel/irq.c | 5 | ||||
| -rw-r--r-- | arch/s390/kernel/mcount.S | 14 | ||||
| -rw-r--r-- | arch/s390/kernel/nospec-branch.c | 44 | ||||
| -rw-r--r-- | arch/s390/kernel/nospec-sysfs.c | 21 | ||||
| -rw-r--r-- | arch/s390/kernel/perf_cpum_sf.c | 4 | ||||
| -rw-r--r-- | arch/s390/kernel/reipl.S | 7 | ||||
| -rw-r--r-- | arch/s390/kernel/swsusp.S | 10 | ||||
| -rw-r--r-- | arch/s390/lib/mem.S | 19 | ||||
| -rw-r--r-- | arch/s390/net/bpf_jit.S | 16 | ||||
| -rw-r--r-- | arch/s390/net/bpf_jit_comp.c | 63 | ||||
| -rw-r--r-- | drivers/s390/cio/qdio_setup.c | 12 | ||||
| -rw-r--r-- | drivers/s390/cio/vfio_ccw_cp.c | 13 |
23 files changed, 422 insertions, 167 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 58b9861ccf99..92e47b5b0480 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -12220,7 +12220,7 @@ F: Documentation/s390/vfio-ccw.txt | |||
| 12220 | F: include/uapi/linux/vfio_ccw.h | 12220 | F: include/uapi/linux/vfio_ccw.h |
| 12221 | 12221 | ||
| 12222 | S390 ZCRYPT DRIVER | 12222 | S390 ZCRYPT DRIVER |
| 12223 | M: Harald Freudenberger <freude@de.ibm.com> | 12223 | M: Harald Freudenberger <freude@linux.ibm.com> |
| 12224 | L: linux-s390@vger.kernel.org | 12224 | L: linux-s390@vger.kernel.org |
| 12225 | W: http://www.ibm.com/developerworks/linux/linux390/ | 12225 | W: http://www.ibm.com/developerworks/linux/linux390/ |
| 12226 | S: Supported | 12226 | S: Supported |
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/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 | /** |
