Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 's390-6.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull more s390 updates from Vasily Gorbik:

- Fix KMSAN build breakage caused by the conflict between s390 and
mm-stable trees

- Add KMSAN page markers for ptdump

- Add runtime constant support

- Fix __pa/__va for modules under non-GPL licenses by exporting
necessary vm_layout struct with EXPORT_SYMBOL to prevent linkage
problems

- Fix an endless loop in the CF_DIAG event stop in the CPU Measurement
Counter Facility code when the counter set size is zero

- Remove the PROTECTED_VIRTUALIZATION_GUEST config option and enable
its functionality by default

- Support allocation of multiple MSI interrupts per device and improve
logging of architecture-specific limitations

- Add support for lowcore relocation as a debugging feature to catch
all null ptr dereferences in the kernel address space, improving
detection beyond the current implementation's limited write access
protection

- Clean up and rework CPU alternatives to allow for callbacks and early
patching for the lowcore relocation

* tag 's390-6.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (39 commits)
s390: Remove protvirt and kvm config guards for uv code
s390/boot: Add cmdline option to relocate lowcore
s390/kdump: Make kdump ready for lowcore relocation
s390/entry: Make system_call() ready for lowcore relocation
s390/entry: Make ret_from_fork() ready for lowcore relocation
s390/entry: Make __switch_to() ready for lowcore relocation
s390/entry: Make restart_int_handler() ready for lowcore relocation
s390/entry: Make mchk_int_handler() ready for lowcore relocation
s390/entry: Make int handlers ready for lowcore relocation
s390/entry: Make pgm_check_handler() ready for lowcore relocation
s390/entry: Add base register to CHECK_VMAP_STACK/CHECK_STACK macro
s390/entry: Add base register to SIEEXIT macro
s390/entry: Add base register to MBEAR macro
s390/entry: Make __sie64a() ready for lowcore relocation
s390/head64: Make startup code ready for lowcore relocation
s390: Add infrastructure to patch lowcore accesses
s390/atomic_ops: Disable flag outputs constraint for GCC versions below 14.2.0
s390/entry: Move SIE indicator flag to thread info
s390/nmi: Simplify ptregs setup
s390/alternatives: Remove alternative facility list
...

+746 -525
-3
Documentation/admin-guide/kernel-parameters.txt
··· 3830 3830 3831 3831 noalign [KNL,ARM] 3832 3832 3833 - noaltinstr [S390,EARLY] Disables alternative instructions 3834 - patching (CPU alternatives feature). 3835 - 3836 3833 noapic [SMP,APIC,EARLY] Tells the kernel to not make use of any 3837 3834 IOAPICs that may be present in the system. 3838 3835
-11
arch/s390/Kconfig
··· 799 799 800 800 menu "Virtualization" 801 801 802 - config PROTECTED_VIRTUALIZATION_GUEST 803 - def_bool n 804 - prompt "Protected virtualization guest support" 805 - help 806 - Select this option, if you want to be able to run this 807 - kernel as a protected virtualization KVM guest. 808 - Protected virtualization capable machines have a mini hypervisor 809 - located at machine level (an ultravisor). With help of the 810 - Ultravisor, KVM will be able to run "protected" VMs, special 811 - VMs whose memory and management data are unavailable to KVM. 812 - 813 802 config PFAULT 814 803 def_bool y 815 804 prompt "Pseudo page fault support"
+1 -2
arch/s390/boot/Makefile
··· 39 39 40 40 obj-y := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o 41 41 obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o 42 - obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o 43 - obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o 42 + obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o alternative.o uv.o 44 43 obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o 45 44 obj-y += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o 46 45 obj-$(CONFIG_KERNEL_ZSTD) += clz_ctz.o
+3
arch/s390/boot/alternative.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include "../kernel/alternative.c"
+4
arch/s390/boot/boot.h
··· 30 30 unsigned long init_mm_off; 31 31 unsigned long swapper_pg_dir_off; 32 32 unsigned long invalid_pg_dir_off; 33 + unsigned long alt_instructions; 34 + unsigned long alt_instructions_end; 33 35 #ifdef CONFIG_KASAN 34 36 unsigned long kasan_early_shadow_page_off; 35 37 unsigned long kasan_early_shadow_pte_off; ··· 91 89 extern unsigned char _compressed_start[]; 92 90 extern unsigned char _compressed_end[]; 93 91 extern struct vmlinux_info _vmlinux_info; 92 + 94 93 #define vmlinux _vmlinux_info 95 94 95 + #define __lowcore_pa(x) ((unsigned long)(x) % sizeof(struct lowcore)) 96 96 #define __abs_lowcore_pa(x) (((unsigned long)(x) - __abs_lowcore) % sizeof(struct lowcore)) 97 97 #define __kernel_va(x) ((void *)((unsigned long)(x) - __kaslr_offset_phys + __kaslr_offset)) 98 98 #define __kernel_pa(x) ((unsigned long)(x) - __kaslr_offset + __kaslr_offset_phys)
+3
arch/s390/boot/ipl_parm.c
··· 3 3 #include <linux/init.h> 4 4 #include <linux/ctype.h> 5 5 #include <linux/pgtable.h> 6 + #include <asm/abs_lowcore.h> 6 7 #include <asm/page-states.h> 7 8 #include <asm/ebcdic.h> 8 9 #include <asm/sclp.h> ··· 311 310 prot_virt_host = 1; 312 311 } 313 312 #endif 313 + if (!strcmp(param, "relocate_lowcore") && test_facility(193)) 314 + relocate_lowcore = 1; 314 315 } 315 316 }
+12 -2
arch/s390/boot/startup.c
··· 30 30 unsigned long __bootdata_preserved(MODULES_VADDR); 31 31 unsigned long __bootdata_preserved(MODULES_END); 32 32 unsigned long __bootdata_preserved(max_mappable); 33 + int __bootdata_preserved(relocate_lowcore); 33 34 34 35 u64 __bootdata_preserved(stfle_fac_list[16]); 35 36 struct oldmem_data __bootdata_preserved(oldmem_data); ··· 377 376 vmlinux.init_mm_off += offset; 378 377 vmlinux.swapper_pg_dir_off += offset; 379 378 vmlinux.invalid_pg_dir_off += offset; 379 + vmlinux.alt_instructions += offset; 380 + vmlinux.alt_instructions_end += offset; 380 381 #ifdef CONFIG_KASAN 381 382 vmlinux.kasan_early_shadow_page_off += offset; 382 383 vmlinux.kasan_early_shadow_pte_off += offset; ··· 481 478 * before the kernel started. Therefore, in case the two sections 482 479 * overlap there is no risk of corrupting any data. 483 480 */ 484 - if (kaslr_enabled()) 485 - amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, 0, SZ_2G); 481 + if (kaslr_enabled()) { 482 + unsigned long amode31_min; 483 + 484 + amode31_min = (unsigned long)_decompressor_end; 485 + amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, amode31_min, SZ_2G); 486 + } 486 487 if (!amode31_lma) 487 488 amode31_lma = __kaslr_offset_phys - vmlinux.amode31_size; 488 489 physmem_reserve(RR_AMODE31, amode31_lma, vmlinux.amode31_size); ··· 510 503 kaslr_adjust_got(__kaslr_offset); 511 504 setup_vmem(__kaslr_offset, __kaslr_offset + kernel_size, asce_limit); 512 505 copy_bootdata(); 506 + __apply_alternatives((struct alt_instr *)_vmlinux_info.alt_instructions, 507 + (struct alt_instr *)_vmlinux_info.alt_instructions_end, 508 + ALT_CTX_EARLY); 513 509 514 510 /* 515 511 * Save KASLR offset for early dumps, before vmcore_info is set.
-8
arch/s390/boot/uv.c
··· 8 8 #include "uv.h" 9 9 10 10 /* will be used in arch/s390/kernel/uv.c */ 11 - #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST 12 11 int __bootdata_preserved(prot_virt_guest); 13 - #endif 14 - #if IS_ENABLED(CONFIG_KVM) 15 12 int __bootdata_preserved(prot_virt_host); 16 - #endif 17 13 struct uv_info __bootdata_preserved(uv_info); 18 14 19 15 void uv_query_info(void) ··· 49 53 uv_info.max_secrets = uvcb.max_secrets; 50 54 } 51 55 52 - #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST 53 56 if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) && 54 57 test_bit_inv(BIT_UVC_CMD_REMOVE_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list)) 55 58 prot_virt_guest = 1; 56 - #endif 57 59 } 58 60 59 - #if IS_ENABLED(CONFIG_KVM) 60 61 unsigned long adjust_to_uv_max(unsigned long limit) 61 62 { 62 63 if (is_prot_virt_host() && uv_info.max_sec_stor_addr) ··· 85 92 { 86 93 prot_virt_host = is_prot_virt_host_capable(); 87 94 } 88 - #endif
-13
arch/s390/boot/uv.h
··· 2 2 #ifndef BOOT_UV_H 3 3 #define BOOT_UV_H 4 4 5 - #if IS_ENABLED(CONFIG_KVM) 6 5 unsigned long adjust_to_uv_max(unsigned long limit); 7 6 void sanitize_prot_virt_host(void); 8 - #else 9 - static inline unsigned long adjust_to_uv_max(unsigned long limit) 10 - { 11 - return limit; 12 - } 13 - static inline void sanitize_prot_virt_host(void) {} 14 - #endif 15 - 16 - #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM) 17 7 void uv_query_info(void); 18 - #else 19 - static inline void uv_query_info(void) {} 20 - #endif 21 8 22 9 #endif /* BOOT_UV_H */
+10 -1
arch/s390/boot/vmem.c
··· 26 26 enum populate_mode { 27 27 POPULATE_NONE, 28 28 POPULATE_DIRECT, 29 + POPULATE_LOWCORE, 29 30 POPULATE_ABS_LOWCORE, 30 31 POPULATE_IDENTITY, 31 32 POPULATE_KERNEL, ··· 243 242 return -1; 244 243 case POPULATE_DIRECT: 245 244 return addr; 245 + case POPULATE_LOWCORE: 246 + return __lowcore_pa(addr); 246 247 case POPULATE_ABS_LOWCORE: 247 248 return __abs_lowcore_pa(addr); 248 249 case POPULATE_KERNEL: ··· 421 418 422 419 void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned long asce_limit) 423 420 { 421 + unsigned long lowcore_address = 0; 424 422 unsigned long start, end; 425 423 unsigned long asce_type; 426 424 unsigned long asce_bits; ··· 459 455 __arch_set_page_dat((void *)swapper_pg_dir, 1UL << CRST_ALLOC_ORDER); 460 456 __arch_set_page_dat((void *)invalid_pg_dir, 1UL << CRST_ALLOC_ORDER); 461 457 458 + if (relocate_lowcore) 459 + lowcore_address = LOWCORE_ALT_ADDRESS; 460 + 462 461 /* 463 462 * To allow prefixing the lowcore must be mapped with 4KB pages. 464 463 * To prevent creation of a large page at address 0 first map 465 464 * the lowcore and create the identity mapping only afterwards. 466 465 */ 467 - pgtable_populate(0, sizeof(struct lowcore), POPULATE_DIRECT); 466 + pgtable_populate(lowcore_address, 467 + lowcore_address + sizeof(struct lowcore), 468 + POPULATE_LOWCORE); 468 469 for_each_physmem_usable_range(i, &start, &end) { 469 470 pgtable_populate((unsigned long)__identity_va(start), 470 471 (unsigned long)__identity_va(end),
-1
arch/s390/configs/debug_defconfig
··· 55 55 CONFIG_CHSC_SCH=y 56 56 CONFIG_VFIO_CCW=m 57 57 CONFIG_VFIO_AP=m 58 - CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y 59 58 CONFIG_CMM=m 60 59 CONFIG_APPLDATA_BASE=y 61 60 CONFIG_S390_HYPFS_FS=y
-1
arch/s390/configs/defconfig
··· 53 53 CONFIG_CHSC_SCH=y 54 54 CONFIG_VFIO_CCW=m 55 55 CONFIG_VFIO_AP=m 56 - CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y 57 56 CONFIG_CMM=m 58 57 CONFIG_APPLDATA_BASE=y 59 58 CONFIG_S390_HYPFS_FS=y
+8
arch/s390/include/asm/abs_lowcore.h
··· 2 2 #ifndef _ASM_S390_ABS_LOWCORE_H 3 3 #define _ASM_S390_ABS_LOWCORE_H 4 4 5 + #include <asm/sections.h> 5 6 #include <asm/lowcore.h> 6 7 7 8 #define ABS_LOWCORE_MAP_SIZE (NR_CPUS * sizeof(struct lowcore)) ··· 23 22 static inline void put_abs_lowcore(struct lowcore *lc) 24 23 { 25 24 put_cpu(); 25 + } 26 + 27 + extern int __bootdata_preserved(relocate_lowcore); 28 + 29 + static inline int have_relocated_lowcore(void) 30 + { 31 + return relocate_lowcore; 26 32 } 27 33 28 34 #endif /* _ASM_S390_ABS_LOWCORE_H */
-57
arch/s390/include/asm/alternative-asm.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _ASM_S390_ALTERNATIVE_ASM_H 3 - #define _ASM_S390_ALTERNATIVE_ASM_H 4 - 5 - #ifdef __ASSEMBLY__ 6 - 7 - /* 8 - * Issue one struct alt_instr descriptor entry (need to put it into 9 - * the section .altinstructions, see below). This entry contains 10 - * enough information for the alternatives patching code to patch an 11 - * instruction. See apply_alternatives(). 12 - */ 13 - .macro alt_entry orig_start, orig_end, alt_start, alt_end, feature 14 - .long \orig_start - . 15 - .long \alt_start - . 16 - .word \feature 17 - .byte \orig_end - \orig_start 18 - .org . - ( \orig_end - \orig_start ) & 1 19 - .org . - ( \orig_end - \orig_start ) + ( \alt_end - \alt_start ) 20 - .org . - ( \alt_end - \alt_start ) + ( \orig_end - \orig_start ) 21 - .endm 22 - 23 - /* 24 - * Define an alternative between two instructions. If @feature is 25 - * present, early code in apply_alternatives() replaces @oldinstr with 26 - * @newinstr. 27 - */ 28 - .macro ALTERNATIVE oldinstr, newinstr, feature 29 - .pushsection .altinstr_replacement,"ax" 30 - 770: \newinstr 31 - 771: .popsection 32 - 772: \oldinstr 33 - 773: .pushsection .altinstructions,"a" 34 - alt_entry 772b, 773b, 770b, 771b, \feature 35 - .popsection 36 - .endm 37 - 38 - /* 39 - * Define an alternative between two instructions. If @feature is 40 - * present, early code in apply_alternatives() replaces @oldinstr with 41 - * @newinstr. 42 - */ 43 - .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2 44 - .pushsection .altinstr_replacement,"ax" 45 - 770: \newinstr1 46 - 771: \newinstr2 47 - 772: .popsection 48 - 773: \oldinstr 49 - 774: .pushsection .altinstructions,"a" 50 - alt_entry 773b, 774b, 770b, 771b,\feature1 51 - alt_entry 773b, 774b, 771b, 772b,\feature2 52 - .popsection 53 - .endm 54 - 55 - #endif /* __ASSEMBLY__ */ 56 - 57 - #endif /* _ASM_S390_ALTERNATIVE_ASM_H */
+137 -17
arch/s390/include/asm/alternative.h
··· 2 2 #ifndef _ASM_S390_ALTERNATIVE_H 3 3 #define _ASM_S390_ALTERNATIVE_H 4 4 5 + /* 6 + * Each alternative comes with a 32 bit feature field: 7 + * union { 8 + * u32 feature; 9 + * struct { 10 + * u32 ctx : 4; 11 + * u32 type : 8; 12 + * u32 data : 20; 13 + * }; 14 + * } 15 + * 16 + * @ctx is a bitfield, where only one bit must be set. Each bit defines 17 + * in which context an alternative is supposed to be applied to the 18 + * kernel image: 19 + * 20 + * - from the decompressor before the kernel itself is executed 21 + * - from early kernel code from within the kernel 22 + * 23 + * @type is a number which defines the type and with that the type 24 + * specific alternative patching. 25 + * 26 + * @data is additional type specific information which defines if an 27 + * alternative should be applied. 28 + */ 29 + 30 + #define ALT_CTX_EARLY 1 31 + #define ALT_CTX_LATE 2 32 + #define ALT_CTX_ALL (ALT_CTX_EARLY | ALT_CTX_LATE) 33 + 34 + #define ALT_TYPE_FACILITY 0 35 + #define ALT_TYPE_SPEC 1 36 + #define ALT_TYPE_LOWCORE 2 37 + 38 + #define ALT_DATA_SHIFT 0 39 + #define ALT_TYPE_SHIFT 20 40 + #define ALT_CTX_SHIFT 28 41 + 42 + #define ALT_FACILITY_EARLY(facility) (ALT_CTX_EARLY << ALT_CTX_SHIFT | \ 43 + ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \ 44 + (facility) << ALT_DATA_SHIFT) 45 + 46 + #define ALT_FACILITY(facility) (ALT_CTX_LATE << ALT_CTX_SHIFT | \ 47 + ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \ 48 + (facility) << ALT_DATA_SHIFT) 49 + 50 + #define ALT_SPEC(facility) (ALT_CTX_LATE << ALT_CTX_SHIFT | \ 51 + ALT_TYPE_SPEC << ALT_TYPE_SHIFT | \ 52 + (facility) << ALT_DATA_SHIFT) 53 + 54 + #define ALT_LOWCORE (ALT_CTX_EARLY << ALT_CTX_SHIFT | \ 55 + ALT_TYPE_LOWCORE << ALT_TYPE_SHIFT) 56 + 5 57 #ifndef __ASSEMBLY__ 6 58 7 59 #include <linux/types.h> ··· 63 11 struct alt_instr { 64 12 s32 instr_offset; /* original instruction */ 65 13 s32 repl_offset; /* offset to replacement instruction */ 66 - u16 facility; /* facility bit set for replacement */ 14 + union { 15 + u32 feature; /* feature required for replacement */ 16 + struct { 17 + u32 ctx : 4; /* context */ 18 + u32 type : 8; /* type of alternative */ 19 + u32 data : 20; /* patching information */ 20 + }; 21 + }; 67 22 u8 instrlen; /* length of original instruction */ 68 23 } __packed; 69 24 70 - void apply_alternative_instructions(void); 71 - void apply_alternatives(struct alt_instr *start, struct alt_instr *end); 25 + extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; 26 + 27 + void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx); 28 + 29 + static inline void apply_alternative_instructions(void) 30 + { 31 + __apply_alternatives(__alt_instructions, __alt_instructions_end, ALT_CTX_LATE); 32 + } 33 + 34 + static inline void apply_alternatives(struct alt_instr *start, struct alt_instr *end) 35 + { 36 + __apply_alternatives(start, end, ALT_CTX_ALL); 37 + } 72 38 73 39 /* 74 40 * +---------------------------------+ ··· 118 48 #define OLDINSTR(oldinstr) \ 119 49 "661:\n\t" oldinstr "\n662:\n" 120 50 121 - #define ALTINSTR_ENTRY(facility, num) \ 51 + #define ALTINSTR_ENTRY(feature, num) \ 122 52 "\t.long 661b - .\n" /* old instruction */ \ 123 53 "\t.long " b_altinstr(num)"b - .\n" /* alt instruction */ \ 124 - "\t.word " __stringify(facility) "\n" /* facility bit */ \ 54 + "\t.long " __stringify(feature) "\n" /* feature */ \ 125 55 "\t.byte " oldinstr_len "\n" /* instruction len */ \ 126 56 "\t.org . - (" oldinstr_len ") & 1\n" \ 127 57 "\t.org . - (" oldinstr_len ") + (" altinstr_len(num) ")\n" \ ··· 131 61 b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n" 132 62 133 63 /* alternative assembly primitive: */ 134 - #define ALTERNATIVE(oldinstr, altinstr, facility) \ 64 + #define ALTERNATIVE(oldinstr, altinstr, feature) \ 135 65 ".pushsection .altinstr_replacement, \"ax\"\n" \ 136 66 ALTINSTR_REPLACEMENT(altinstr, 1) \ 137 67 ".popsection\n" \ 138 68 OLDINSTR(oldinstr) \ 139 69 ".pushsection .altinstructions,\"a\"\n" \ 140 - ALTINSTR_ENTRY(facility, 1) \ 70 + ALTINSTR_ENTRY(feature, 1) \ 141 71 ".popsection\n" 142 72 143 - #define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2)\ 73 + #define ALTERNATIVE_2(oldinstr, altinstr1, feature1, altinstr2, feature2)\ 144 74 ".pushsection .altinstr_replacement, \"ax\"\n" \ 145 75 ALTINSTR_REPLACEMENT(altinstr1, 1) \ 146 76 ALTINSTR_REPLACEMENT(altinstr2, 2) \ 147 77 ".popsection\n" \ 148 78 OLDINSTR(oldinstr) \ 149 79 ".pushsection .altinstructions,\"a\"\n" \ 150 - ALTINSTR_ENTRY(facility1, 1) \ 151 - ALTINSTR_ENTRY(facility2, 2) \ 80 + ALTINSTR_ENTRY(feature1, 1) \ 81 + ALTINSTR_ENTRY(feature2, 2) \ 152 82 ".popsection\n" 153 83 154 84 /* ··· 163 93 * For non barrier like inlines please define new variants 164 94 * without volatile and memory clobber. 165 95 */ 166 - #define alternative(oldinstr, altinstr, facility) \ 167 - asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) : : : "memory") 96 + #define alternative(oldinstr, altinstr, feature) \ 97 + asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature) : : : "memory") 168 98 169 - #define alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \ 170 - asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, facility1, \ 171 - altinstr2, facility2) ::: "memory") 99 + #define alternative_2(oldinstr, altinstr1, feature1, altinstr2, feature2) \ 100 + asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, feature1, \ 101 + altinstr2, feature2) ::: "memory") 172 102 173 103 /* Alternative inline assembly with input. */ 174 104 #define alternative_input(oldinstr, newinstr, feature, input...) \ ··· 176 106 : : input) 177 107 178 108 /* Like alternative_input, but with a single output argument */ 179 - #define alternative_io(oldinstr, altinstr, facility, output, input...) \ 180 - asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) \ 109 + #define alternative_io(oldinstr, altinstr, feature, output, input...) \ 110 + asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature) \ 181 111 : output : input) 182 112 183 113 /* Use this macro if more than one output parameter is needed. */ ··· 185 115 186 116 /* Use this macro if clobbers are needed without inputs. */ 187 117 #define ASM_NO_INPUT_CLOBBER(clobber...) : clobber 118 + 119 + #else /* __ASSEMBLY__ */ 120 + 121 + /* 122 + * Issue one struct alt_instr descriptor entry (need to put it into 123 + * the section .altinstructions, see below). This entry contains 124 + * enough information for the alternatives patching code to patch an 125 + * instruction. See apply_alternatives(). 126 + */ 127 + .macro alt_entry orig_start, orig_end, alt_start, alt_end, feature 128 + .long \orig_start - . 129 + .long \alt_start - . 130 + .long \feature 131 + .byte \orig_end - \orig_start 132 + .org . - ( \orig_end - \orig_start ) & 1 133 + .org . - ( \orig_end - \orig_start ) + ( \alt_end - \alt_start ) 134 + .org . - ( \alt_end - \alt_start ) + ( \orig_end - \orig_start ) 135 + .endm 136 + 137 + /* 138 + * Define an alternative between two instructions. If @feature is 139 + * present, early code in apply_alternatives() replaces @oldinstr with 140 + * @newinstr. 141 + */ 142 + .macro ALTERNATIVE oldinstr, newinstr, feature 143 + .pushsection .altinstr_replacement,"ax" 144 + 770: \newinstr 145 + 771: .popsection 146 + 772: \oldinstr 147 + 773: .pushsection .altinstructions,"a" 148 + alt_entry 772b, 773b, 770b, 771b, \feature 149 + .popsection 150 + .endm 151 + 152 + /* 153 + * Define an alternative between two instructions. If @feature is 154 + * present, early code in apply_alternatives() replaces @oldinstr with 155 + * @newinstr. 156 + */ 157 + .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2 158 + .pushsection .altinstr_replacement,"ax" 159 + 770: \newinstr1 160 + 771: \newinstr2 161 + 772: .popsection 162 + 773: \oldinstr 163 + 774: .pushsection .altinstructions,"a" 164 + alt_entry 773b, 774b, 770b, 771b,\feature1 165 + alt_entry 773b, 774b, 771b, 772b,\feature2 166 + .popsection 167 + .endm 188 168 189 169 #endif /* __ASSEMBLY__ */ 190 170
+2 -1
arch/s390/include/asm/atomic_ops.h
··· 188 188 return old; 189 189 } 190 190 191 - #ifdef __GCC_ASM_FLAG_OUTPUTS__ 191 + /* GCC versions before 14.2.0 may die with an ICE in some configurations. */ 192 + #if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_IS_GCC) && (GCC_VERSION < 140200)) 192 193 193 194 static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) 194 195 {
-1
arch/s390/include/asm/facility.h
··· 20 20 #define MAX_FACILITY_BIT (sizeof(stfle_fac_list) * 8) 21 21 22 22 extern u64 stfle_fac_list[16]; 23 - extern u64 alt_stfle_fac_list[16]; 24 23 25 24 static inline void __set_facility(unsigned long nr, void *facilities) 26 25 {
+3 -3
arch/s390/include/asm/kmsan.h
··· 12 12 13 13 static inline bool is_lowcore_addr(void *addr) 14 14 { 15 - return addr >= (void *)&S390_lowcore && 16 - addr < (void *)(&S390_lowcore + 1); 15 + return addr >= (void *)get_lowcore() && 16 + addr < (void *)(get_lowcore() + 1); 17 17 } 18 18 19 19 static inline void *arch_kmsan_get_meta_or_null(void *addr, bool is_origin) ··· 25 25 * order to get a distinct struct page. 26 26 */ 27 27 addr += (void *)lowcore_ptr[raw_smp_processor_id()] - 28 - (void *)&S390_lowcore; 28 + (void *)get_lowcore(); 29 29 if (KMSAN_WARN_ON(is_lowcore_addr(addr))) 30 30 return NULL; 31 31 return kmsan_get_metadata(addr, is_origin);
+29 -3
arch/s390/include/asm/lowcore.h
··· 14 14 #include <asm/ctlreg.h> 15 15 #include <asm/cpu.h> 16 16 #include <asm/types.h> 17 + #include <asm/alternative.h> 17 18 18 19 #define LC_ORDER 1 19 20 #define LC_PAGES 2 21 + 22 + #define LOWCORE_ALT_ADDRESS _AC(0x70000, UL) 23 + 24 + #ifndef __ASSEMBLY__ 20 25 21 26 struct pgm_tdb { 22 27 u64 data[32]; ··· 102 97 __u64 save_area_async[8]; /* 0x0240 */ 103 98 __u64 save_area_restart[1]; /* 0x0280 */ 104 99 105 - /* CPU flags. */ 106 - __u64 cpu_flags; /* 0x0288 */ 100 + __u64 pcpu; /* 0x0288 */ 107 101 108 102 /* Return psws. */ 109 103 psw_t return_psw; /* 0x0290 */ ··· 219 215 220 216 static __always_inline struct lowcore *get_lowcore(void) 221 217 { 222 - return NULL; 218 + struct lowcore *lc; 219 + 220 + if (__is_defined(__DECOMPRESSOR)) 221 + return NULL; 222 + asm(ALTERNATIVE("llilh %[lc],0", "llilh %[lc],%[alt]", ALT_LOWCORE) 223 + : [lc] "=d" (lc) 224 + : [alt] "i" (LOWCORE_ALT_ADDRESS >> 16)); 225 + return lc; 223 226 } 224 227 225 228 extern struct lowcore *lowcore_ptr[]; ··· 236 225 asm volatile("spx %0" : : "Q" (address) : "memory"); 237 226 } 238 227 228 + #else /* __ASSEMBLY__ */ 229 + 230 + .macro GET_LC reg 231 + ALTERNATIVE "llilh \reg,0", \ 232 + __stringify(llilh \reg, LOWCORE_ALT_ADDRESS >> 16), \ 233 + ALT_LOWCORE 234 + .endm 235 + 236 + .macro STMG_LC start, end, savearea 237 + ALTERNATIVE "stmg \start, \end, \savearea", \ 238 + __stringify(stmg \start, \end, LOWCORE_ALT_ADDRESS + \savearea), \ 239 + ALT_LOWCORE 240 + .endm 241 + 242 + #endif /* __ASSEMBLY__ */ 239 243 #endif /* _ASM_S390_LOWCORE_H */
+9
arch/s390/include/asm/nospec-branch.h
··· 5 5 #ifndef __ASSEMBLY__ 6 6 7 7 #include <linux/types.h> 8 + #include <asm/facility.h> 8 9 9 10 extern int nospec_disable; 11 + extern int nobp; 12 + 13 + static inline bool nobp_enabled(void) 14 + { 15 + if (__is_defined(__DECOMPRESSOR)) 16 + return false; 17 + return nobp && test_facility(82); 18 + } 10 19 11 20 void nospec_init_branches(void); 12 21 void nospec_auto_detect(void);
-2
arch/s390/include/asm/page.h
··· 174 174 #define HAVE_ARCH_FREE_PAGE 175 175 #define HAVE_ARCH_ALLOC_PAGE 176 176 177 - #if IS_ENABLED(CONFIG_PGSTE) 178 177 int arch_make_folio_accessible(struct folio *folio); 179 178 #define HAVE_ARCH_MAKE_FOLIO_ACCESSIBLE 180 179 int arch_make_page_accessible(struct page *page); 181 180 #define HAVE_ARCH_MAKE_PAGE_ACCESSIBLE 182 - #endif 183 181 184 182 struct vm_layout { 185 183 unsigned long kaslr_offset;
+21 -9
arch/s390/include/asm/processor.h
··· 14 14 15 15 #include <linux/bits.h> 16 16 17 - #define CIF_SIE 0 /* CPU needs SIE exit cleanup */ 18 17 #define CIF_NOHZ_DELAY 2 /* delay HZ disable for a tick */ 19 18 #define CIF_ENABLED_WAIT 5 /* in enabled wait state */ 20 19 #define CIF_MCCK_GUEST 6 /* machine check happening in guest */ 21 20 #define CIF_DEDICATED_CPU 7 /* this CPU is dedicated */ 22 21 23 - #define _CIF_SIE BIT(CIF_SIE) 24 22 #define _CIF_NOHZ_DELAY BIT(CIF_NOHZ_DELAY) 25 23 #define _CIF_ENABLED_WAIT BIT(CIF_ENABLED_WAIT) 26 24 #define _CIF_MCCK_GUEST BIT(CIF_MCCK_GUEST) ··· 40 42 #include <asm/irqflags.h> 41 43 #include <asm/alternative.h> 42 44 45 + struct pcpu { 46 + unsigned long ec_mask; /* bit mask for ec_xxx functions */ 47 + unsigned long ec_clk; /* sigp timestamp for ec_xxx */ 48 + unsigned long flags; /* per CPU flags */ 49 + signed char state; /* physical cpu state */ 50 + signed char polarization; /* physical polarization */ 51 + u16 address; /* physical cpu address */ 52 + }; 53 + 54 + DECLARE_PER_CPU(struct pcpu, pcpu_devices); 55 + 43 56 typedef long (*sys_call_ptr_t)(struct pt_regs *regs); 57 + 58 + static __always_inline struct pcpu *this_pcpu(void) 59 + { 60 + return (struct pcpu *)(get_lowcore()->pcpu); 61 + } 44 62 45 63 static __always_inline void set_cpu_flag(int flag) 46 64 { 47 - get_lowcore()->cpu_flags |= (1UL << flag); 65 + this_pcpu()->flags |= (1UL << flag); 48 66 } 49 67 50 68 static __always_inline void clear_cpu_flag(int flag) 51 69 { 52 - get_lowcore()->cpu_flags &= ~(1UL << flag); 70 + this_pcpu()->flags &= ~(1UL << flag); 53 71 } 54 72 55 73 static __always_inline bool test_cpu_flag(int flag) 56 74 { 57 - return get_lowcore()->cpu_flags & (1UL << flag); 75 + return this_pcpu()->flags & (1UL << flag); 58 76 } 59 77 60 78 static __always_inline bool test_and_set_cpu_flag(int flag) ··· 95 81 */ 96 82 static __always_inline bool test_cpu_flag_of(int flag, int cpu) 97 83 { 98 - struct lowcore *lc = lowcore_ptr[cpu]; 99 - 100 - return lc->cpu_flags & (1UL << flag); 84 + return per_cpu(pcpu_devices, cpu).flags & (1UL << flag); 101 85 } 102 86 103 87 #define arch_needs_cpu() test_cpu_flag(CIF_NOHZ_DELAY) ··· 417 405 418 406 static __always_inline void bpon(void) 419 407 { 420 - asm volatile(ALTERNATIVE("nop", ".insn rrf,0xb2e80000,0,0,13,0", 82)); 408 + asm volatile(ALTERNATIVE("nop", ".insn rrf,0xb2e80000,0,0,13,0", ALT_SPEC(82))); 421 409 } 422 410 423 411 #endif /* __ASSEMBLY__ */
+77
arch/s390/include/asm/runtime-const.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _ASM_S390_RUNTIME_CONST_H 3 + #define _ASM_S390_RUNTIME_CONST_H 4 + 5 + #include <linux/uaccess.h> 6 + 7 + #define runtime_const_ptr(sym) \ 8 + ({ \ 9 + typeof(sym) __ret; \ 10 + \ 11 + asm_inline( \ 12 + "0: iihf %[__ret],%[c1]\n" \ 13 + " iilf %[__ret],%[c2]\n" \ 14 + ".pushsection runtime_ptr_" #sym ",\"a\"\n" \ 15 + ".long 0b - .\n" \ 16 + ".popsection" \ 17 + : [__ret] "=d" (__ret) \ 18 + : [c1] "i" (0x01234567UL), \ 19 + [c2] "i" (0x89abcdefUL)); \ 20 + __ret; \ 21 + }) 22 + 23 + #define runtime_const_shift_right_32(val, sym) \ 24 + ({ \ 25 + unsigned int __ret = (val); \ 26 + \ 27 + asm_inline( \ 28 + "0: srl %[__ret],12\n" \ 29 + ".pushsection runtime_shift_" #sym ",\"a\"\n" \ 30 + ".long 0b - .\n" \ 31 + ".popsection" \ 32 + : [__ret] "+d" (__ret)); \ 33 + __ret; \ 34 + }) 35 + 36 + #define runtime_const_init(type, sym) do { \ 37 + extern s32 __start_runtime_##type##_##sym[]; \ 38 + extern s32 __stop_runtime_##type##_##sym[]; \ 39 + \ 40 + runtime_const_fixup(__runtime_fixup_##type, \ 41 + (unsigned long)(sym), \ 42 + __start_runtime_##type##_##sym, \ 43 + __stop_runtime_##type##_##sym); \ 44 + } while (0) 45 + 46 + /* 32-bit immediate for iihf and iilf in bits in I2 field */ 47 + static inline void __runtime_fixup_32(u32 *p, unsigned int val) 48 + { 49 + s390_kernel_write(p, &val, sizeof(val)); 50 + } 51 + 52 + static inline void __runtime_fixup_ptr(void *where, unsigned long val) 53 + { 54 + __runtime_fixup_32(where + 2, val >> 32); 55 + __runtime_fixup_32(where + 8, val); 56 + } 57 + 58 + /* Immediate value is lower 12 bits of D2 field of srl */ 59 + static inline void __runtime_fixup_shift(void *where, unsigned long val) 60 + { 61 + u32 insn = *(u32 *)where; 62 + 63 + insn &= 0xfffff000; 64 + insn |= (val & 63); 65 + s390_kernel_write(where, &insn, sizeof(insn)); 66 + } 67 + 68 + static inline void runtime_const_fixup(void (*fn)(void *, unsigned long), 69 + unsigned long val, s32 *start, s32 *end) 70 + { 71 + while (start < end) { 72 + fn(*start + (void *)start, val); 73 + start++; 74 + } 75 + } 76 + 77 + #endif /* _ASM_S390_RUNTIME_CONST_H */
-1
arch/s390/include/asm/smp.h
··· 24 24 extern void arch_send_call_function_single_ipi(int cpu); 25 25 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); 26 26 27 - extern void smp_call_online_cpu(void (*func)(void *), void *); 28 27 extern void smp_call_ipl_cpu(void (*func)(void *), void *); 29 28 extern void smp_emergency_stop(void); 30 29
+1 -1
arch/s390/include/asm/spinlock.h
··· 79 79 typecheck(int, lp->lock); 80 80 kcsan_release(); 81 81 asm_inline volatile( 82 - ALTERNATIVE("nop", ".insn rre,0xb2fa0000,7,0", 49) /* NIAI 7 */ 82 + ALTERNATIVE("nop", ".insn rre,0xb2fa0000,7,0", ALT_FACILITY(49)) /* NIAI 7 */ 83 83 " sth %1,%0\n" 84 84 : "=R" (((unsigned short *) &lp->lock)[1]) 85 85 : "d" (0) : "cc", "memory");
+1
arch/s390/include/asm/thread_info.h
··· 40 40 unsigned long flags; /* low level flags */ 41 41 unsigned long syscall_work; /* SYSCALL_WORK_ flags */ 42 42 unsigned int cpu; /* current CPU */ 43 + unsigned char sie; /* running in SIE context */ 43 44 }; 44 45 45 46 /*
+8 -1
arch/s390/include/asm/uaccess.h
··· 332 332 return __clear_user(to, n); 333 333 } 334 334 335 - void *s390_kernel_write(void *dst, const void *src, size_t size); 335 + void *__s390_kernel_write(void *dst, const void *src, size_t size); 336 + 337 + static inline void *s390_kernel_write(void *dst, const void *src, size_t size) 338 + { 339 + if (__is_defined(__DECOMPRESSOR)) 340 + return memcpy(dst, src, size); 341 + return __s390_kernel_write(dst, src, size); 342 + } 336 343 337 344 int __noreturn __put_kernel_bad(void); 338 345
-32
arch/s390/include/asm/uv.h
··· 414 414 return test_bit_inv(feature_bit, &uv_info.uv_feature_indications); 415 415 } 416 416 417 - #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST 418 417 extern int prot_virt_guest; 419 418 420 419 static inline int is_prot_virt_guest(void) ··· 465 466 return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS); 466 467 } 467 468 468 - #else 469 - #define is_prot_virt_guest() 0 470 - static inline int uv_set_shared(unsigned long addr) { return 0; } 471 - static inline int uv_remove_shared(unsigned long addr) { return 0; } 472 - #endif 473 - 474 - #if IS_ENABLED(CONFIG_KVM) 475 469 extern int prot_virt_host; 476 470 477 471 static inline int is_prot_virt_host(void) ··· 481 489 int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr); 482 490 483 491 void setup_uv(void); 484 - #else 485 - #define is_prot_virt_host() 0 486 - static inline void setup_uv(void) {} 487 - 488 - static inline int uv_pin_shared(unsigned long paddr) 489 - { 490 - return 0; 491 - } 492 - 493 - static inline int uv_destroy_folio(struct folio *folio) 494 - { 495 - return 0; 496 - } 497 - 498 - static inline int uv_destroy_pte(pte_t pte) 499 - { 500 - return 0; 501 - } 502 - 503 - static inline int uv_convert_from_secure_pte(pte_t pte) 504 - { 505 - return 0; 506 - } 507 - #endif 508 492 509 493 #endif /* _ASM_S390_UV_H */
+1 -2
arch/s390/kernel/Makefile
··· 43 43 obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o 44 44 obj-y += entry.o reipl.o kdebugfs.o alternative.o 45 45 obj-y += nospec-branch.o ipl_vmparm.o machine_kexec_reloc.o unwind_bc.o 46 - obj-y += smp.o text_amode31.o stacktrace.o abs_lowcore.o facility.o 46 + obj-y += smp.o text_amode31.o stacktrace.o abs_lowcore.o facility.o uv.o 47 47 48 48 extra-y += vmlinux.lds 49 49 ··· 80 80 obj-$(CONFIG_PERF_EVENTS) += perf_pai_crypto.o perf_pai_ext.o 81 81 82 82 obj-$(CONFIG_TRACEPOINTS) += trace.o 83 - obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o 84 83 85 84 # vdso 86 85 obj-y += vdso64/
+1
arch/s390/kernel/abs_lowcore.c
··· 4 4 #include <asm/abs_lowcore.h> 5 5 6 6 unsigned long __bootdata_preserved(__abs_lowcore); 7 + int __bootdata_preserved(relocate_lowcore); 7 8 8 9 int abs_lowcore_map(int cpu, struct lowcore *lc, bool alloc) 9 10 {
+24 -51
arch/s390/kernel/alternative.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/module.h> 3 - #include <linux/cpu.h> 4 - #include <linux/smp.h> 5 - #include <asm/text-patching.h> 2 + 3 + #include <linux/uaccess.h> 4 + #include <asm/nospec-branch.h> 5 + #include <asm/abs_lowcore.h> 6 6 #include <asm/alternative.h> 7 7 #include <asm/facility.h> 8 - #include <asm/nospec-branch.h> 9 8 10 - static int __initdata_or_module alt_instr_disabled; 11 - 12 - static int __init disable_alternative_instructions(char *str) 9 + void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx) 13 10 { 14 - alt_instr_disabled = 1; 15 - return 0; 16 - } 17 - 18 - early_param("noaltinstr", disable_alternative_instructions); 19 - 20 - static void __init_or_module __apply_alternatives(struct alt_instr *start, 21 - struct alt_instr *end) 22 - { 23 - struct alt_instr *a; 24 11 u8 *instr, *replacement; 12 + struct alt_instr *a; 13 + bool replace; 25 14 26 15 /* 27 16 * The scan order should be from start to end. A later scanned 28 17 * alternative code can overwrite previously scanned alternative code. 29 18 */ 30 19 for (a = start; a < end; a++) { 20 + if (!(a->ctx & ctx)) 21 + continue; 22 + switch (a->type) { 23 + case ALT_TYPE_FACILITY: 24 + replace = test_facility(a->data); 25 + break; 26 + case ALT_TYPE_SPEC: 27 + replace = nobp_enabled(); 28 + break; 29 + case ALT_TYPE_LOWCORE: 30 + replace = have_relocated_lowcore(); 31 + break; 32 + default: 33 + replace = false; 34 + } 35 + if (!replace) 36 + continue; 31 37 instr = (u8 *)&a->instr_offset + a->instr_offset; 32 38 replacement = (u8 *)&a->repl_offset + a->repl_offset; 33 - 34 - if (!__test_facility(a->facility, alt_stfle_fac_list)) 35 - continue; 36 39 s390_kernel_write(instr, replacement, a->instrlen); 37 40 } 38 - } 39 - 40 - void __init_or_module apply_alternatives(struct alt_instr *start, 41 - struct alt_instr *end) 42 - { 43 - if (!alt_instr_disabled) 44 - __apply_alternatives(start, end); 45 - } 46 - 47 - extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; 48 - void __init apply_alternative_instructions(void) 49 - { 50 - apply_alternatives(__alt_instructions, __alt_instructions_end); 51 - } 52 - 53 - static void do_sync_core(void *info) 54 - { 55 - sync_core(); 56 - } 57 - 58 - void text_poke_sync(void) 59 - { 60 - on_each_cpu(do_sync_core, NULL, 1); 61 - } 62 - 63 - void text_poke_sync_lock(void) 64 - { 65 - cpus_read_lock(); 66 - text_poke_sync(); 67 - cpus_read_unlock(); 68 41 }
arch/s390/kernel/alternative.h
+4 -1
arch/s390/kernel/asm-offsets.c
··· 28 28 BLANK(); 29 29 /* thread info offsets */ 30 30 OFFSET(__TI_flags, task_struct, thread_info.flags); 31 + OFFSET(__TI_sie, task_struct, thread_info.sie); 31 32 BLANK(); 32 33 /* pt_regs offsets */ 33 34 OFFSET(__PT_PSW, pt_regs, psw); ··· 115 114 OFFSET(__LC_SAVE_AREA_SYNC, lowcore, save_area_sync); 116 115 OFFSET(__LC_SAVE_AREA_ASYNC, lowcore, save_area_async); 117 116 OFFSET(__LC_SAVE_AREA_RESTART, lowcore, save_area_restart); 118 - OFFSET(__LC_CPU_FLAGS, lowcore, cpu_flags); 117 + OFFSET(__LC_PCPU, lowcore, pcpu); 119 118 OFFSET(__LC_RETURN_PSW, lowcore, return_psw); 120 119 OFFSET(__LC_RETURN_MCCK_PSW, lowcore, return_mcck_psw); 121 120 OFFSET(__LC_SYS_ENTER_TIMER, lowcore, sys_enter_timer); ··· 187 186 #endif 188 187 OFFSET(__FTRACE_REGS_PT_REGS, ftrace_regs, regs); 189 188 DEFINE(__FTRACE_REGS_SIZE, sizeof(struct ftrace_regs)); 189 + 190 + OFFSET(__PCPU_FLAGS, pcpu, flags); 190 191 return 0; 191 192 }
+1 -8
arch/s390/kernel/early.c
··· 48 48 decompressor_handled_param(facilities); 49 49 decompressor_handled_param(nokaslr); 50 50 decompressor_handled_param(cmma); 51 + decompressor_handled_param(relocate_lowcore); 51 52 #if IS_ENABLED(CONFIG_KVM) 52 53 decompressor_handled_param(prot_virt); 53 54 #endif ··· 191 190 get_lowcore()->preempt_count = INIT_PREEMPT_COUNT; 192 191 } 193 192 194 - static noinline __init void setup_facility_list(void) 195 - { 196 - memcpy(alt_stfle_fac_list, stfle_fac_list, sizeof(alt_stfle_fac_list)); 197 - if (!IS_ENABLED(CONFIG_KERNEL_NOBP)) 198 - __clear_facility(82, alt_stfle_fac_list); 199 - } 200 - 201 193 static __init void detect_diag9c(void) 202 194 { 203 195 unsigned int cpu_address; ··· 285 291 lockdep_off(); 286 292 sort_amode31_extable(); 287 293 setup_lowcore_early(); 288 - setup_facility_list(); 289 294 detect_machine_type(); 290 295 setup_arch_string(); 291 296 setup_boot_command_line();
+136 -115
arch/s390/kernel/entry.S
··· 12 12 #include <linux/init.h> 13 13 #include <linux/linkage.h> 14 14 #include <asm/asm-extable.h> 15 - #include <asm/alternative-asm.h> 15 + #include <asm/alternative.h> 16 16 #include <asm/processor.h> 17 17 #include <asm/cache.h> 18 18 #include <asm/dwarf.h> ··· 28 28 #include <asm/setup.h> 29 29 #include <asm/nmi.h> 30 30 #include <asm/nospec-insn.h> 31 + #include <asm/lowcore.h> 31 32 32 33 _LPP_OFFSET = __LC_LPP 33 34 34 35 .macro STBEAR address 35 - ALTERNATIVE "nop", ".insn s,0xb2010000,\address", 193 36 + ALTERNATIVE "nop", ".insn s,0xb2010000,\address", ALT_FACILITY(193) 36 37 .endm 37 38 38 39 .macro LBEAR address 39 - ALTERNATIVE "nop", ".insn s,0xb2000000,\address", 193 40 + ALTERNATIVE "nop", ".insn s,0xb2000000,\address", ALT_FACILITY(193) 40 41 .endm 41 42 42 - .macro LPSWEY address,lpswe 43 - ALTERNATIVE "b \lpswe; nopr", ".insn siy,0xeb0000000071,\address,0", 193 43 + .macro LPSWEY address, lpswe 44 + ALTERNATIVE_2 "b \lpswe;nopr", \ 45 + ".insn siy,0xeb0000000071,\address,0", ALT_FACILITY_EARLY(193), \ 46 + __stringify(.insn siy,0xeb0000000071,LOWCORE_ALT_ADDRESS+\address,0), \ 47 + ALT_LOWCORE 44 48 .endm 45 49 46 - .macro MBEAR reg 47 - ALTERNATIVE "brcl 0,0", __stringify(mvc __PT_LAST_BREAK(8,\reg),__LC_LAST_BREAK), 193 50 + .macro MBEAR reg, lowcore 51 + ALTERNATIVE "brcl 0,0", __stringify(mvc __PT_LAST_BREAK(8,\reg),__LC_LAST_BREAK(\lowcore)),\ 52 + ALT_FACILITY(193) 48 53 .endm 49 54 50 - .macro CHECK_STACK savearea 55 + .macro CHECK_STACK savearea, lowcore 51 56 #ifdef CONFIG_CHECK_STACK 52 57 tml %r15,THREAD_SIZE - CONFIG_STACK_GUARD 53 - lghi %r14,\savearea 58 + la %r14,\savearea(\lowcore) 54 59 jz stack_overflow 55 60 #endif 56 61 .endm 57 62 58 - .macro CHECK_VMAP_STACK savearea,oklabel 63 + .macro CHECK_VMAP_STACK savearea, lowcore, oklabel 59 64 #ifdef CONFIG_VMAP_STACK 60 65 lgr %r14,%r15 61 66 nill %r14,0x10000 - THREAD_SIZE 62 67 oill %r14,STACK_INIT_OFFSET 63 - clg %r14,__LC_KERNEL_STACK 68 + clg %r14,__LC_KERNEL_STACK(\lowcore) 64 69 je \oklabel 65 - clg %r14,__LC_ASYNC_STACK 70 + clg %r14,__LC_ASYNC_STACK(\lowcore) 66 71 je \oklabel 67 - clg %r14,__LC_MCCK_STACK 72 + clg %r14,__LC_MCCK_STACK(\lowcore) 68 73 je \oklabel 69 - clg %r14,__LC_NODAT_STACK 74 + clg %r14,__LC_NODAT_STACK(\lowcore) 70 75 je \oklabel 71 - clg %r14,__LC_RESTART_STACK 76 + clg %r14,__LC_RESTART_STACK(\lowcore) 72 77 je \oklabel 73 - lghi %r14,\savearea 78 + la %r14,\savearea(\lowcore) 74 79 j stack_overflow 75 80 #else 76 81 j \oklabel ··· 105 100 .endm 106 101 107 102 .macro BPOFF 108 - ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,12,0", 82 103 + ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,12,0", ALT_SPEC(82) 109 104 .endm 110 105 111 106 .macro BPON 112 - ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,13,0", 82 107 + ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,13,0", ALT_SPEC(82) 113 108 .endm 114 109 115 110 .macro BPENTER tif_ptr,tif_mask 116 111 ALTERNATIVE "TSTMSK \tif_ptr,\tif_mask; jz .+8; .insn rrf,0xb2e80000,0,0,13,0", \ 117 - "j .+12; nop; nop", 82 112 + "j .+12; nop; nop", ALT_SPEC(82) 118 113 .endm 119 114 120 115 .macro BPEXIT tif_ptr,tif_mask 121 116 TSTMSK \tif_ptr,\tif_mask 122 117 ALTERNATIVE "jz .+8; .insn rrf,0xb2e80000,0,0,12,0", \ 123 - "jnz .+8; .insn rrf,0xb2e80000,0,0,13,0", 82 118 + "jnz .+8; .insn rrf,0xb2e80000,0,0,13,0", ALT_SPEC(82) 124 119 .endm 125 120 126 121 #if IS_ENABLED(CONFIG_KVM) 127 - .macro SIEEXIT sie_control 128 - lg %r9,\sie_control # get control block pointer 129 - ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE 130 - lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce 131 - ni __LC_CPU_FLAGS+7,255-_CIF_SIE 122 + .macro SIEEXIT sie_control,lowcore 123 + lg %r9,\sie_control # get control block pointer 124 + ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE 125 + lctlg %c1,%c1,__LC_KERNEL_ASCE(\lowcore) # load primary asce 126 + lg %r9,__LC_CURRENT(\lowcore) 127 + mvi __TI_sie(%r9),0 132 128 larl %r9,sie_exit # skip forward to sie_exit 133 129 .endm 134 130 #endif ··· 169 163 stg %r15,__THREAD_ksp(%r1,%r2) # store kernel stack of prev 170 164 lg %r15,0(%r4,%r3) # start of kernel stack of next 171 165 agr %r15,%r5 # end of kernel stack of next 172 - stg %r3,__LC_CURRENT # store task struct of next 173 - stg %r15,__LC_KERNEL_STACK # store end of kernel stack 166 + GET_LC %r13 167 + stg %r3,__LC_CURRENT(%r13) # store task struct of next 168 + stg %r15,__LC_KERNEL_STACK(%r13) # store end of kernel stack 174 169 lg %r15,__THREAD_ksp(%r1,%r3) # load kernel stack of next 175 170 aghi %r3,__TASK_pid 176 - mvc __LC_CURRENT_PID(4,%r0),0(%r3) # store pid of next 171 + mvc __LC_CURRENT_PID(4,%r13),0(%r3) # store pid of next 172 + ALTERNATIVE "nop", "lpp _LPP_OFFSET(%r13)", ALT_FACILITY(40) 177 173 lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task 178 - ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40 179 174 BR_EX %r14 180 175 SYM_FUNC_END(__switch_to_asm) 181 176 ··· 190 183 */ 191 184 SYM_FUNC_START(__sie64a) 192 185 stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers 193 - lg %r12,__LC_CURRENT 186 + GET_LC %r13 187 + lg %r14,__LC_CURRENT(%r13) 194 188 stg %r2,__SF_SIE_CONTROL_PHYS(%r15) # save sie block physical.. 195 189 stg %r3,__SF_SIE_CONTROL(%r15) # ...and virtual addresses 196 190 stg %r4,__SF_SIE_SAVEAREA(%r15) # save guest register save area 197 191 stg %r5,__SF_SIE_GUEST_ASCE(%r15) # save guest asce 198 192 xc __SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0 199 - mvc __SF_SIE_FLAGS(8,%r15),__TI_flags(%r12) # copy thread flags 193 + mvc __SF_SIE_FLAGS(8,%r15),__TI_flags(%r14) # copy thread flags 200 194 lmg %r0,%r13,0(%r4) # load guest gprs 0-13 201 - oi __LC_CPU_FLAGS+7,_CIF_SIE 195 + mvi __TI_sie(%r14),1 202 196 lctlg %c1,%c1,__SF_SIE_GUEST_ASCE(%r15) # load primary asce 203 197 lg %r14,__SF_SIE_CONTROL(%r15) # get control block pointer 204 198 oi __SIE_PROG0C+3(%r14),1 # we are going into SIE now ··· 218 210 .Lsie_skip: 219 211 lg %r14,__SF_SIE_CONTROL(%r15) # get control block pointer 220 212 ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE 221 - lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce 222 - ni __LC_CPU_FLAGS+7,255-_CIF_SIE 213 + GET_LC %r14 214 + lctlg %c1,%c1,__LC_KERNEL_ASCE(%r14) # load primary asce 215 + lg %r14,__LC_CURRENT(%r14) 216 + mvi __TI_sie(%r14),0 223 217 # some program checks are suppressing. C code (e.g. do_protection_exception) 224 218 # will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There 225 219 # are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable. ··· 264 254 */ 265 255 266 256 SYM_CODE_START(system_call) 267 - stpt __LC_SYS_ENTER_TIMER 268 - stmg %r8,%r15,__LC_SAVE_AREA_SYNC 257 + STMG_LC %r8,%r15,__LC_SAVE_AREA_SYNC 258 + GET_LC %r13 259 + stpt __LC_SYS_ENTER_TIMER(%r13) 269 260 BPOFF 270 261 lghi %r14,0 271 262 .Lsysc_per: 272 - STBEAR __LC_LAST_BREAK 273 - lctlg %c1,%c1,__LC_KERNEL_ASCE 274 - lg %r15,__LC_KERNEL_STACK 263 + STBEAR __LC_LAST_BREAK(%r13) 264 + lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) 265 + lg %r15,__LC_KERNEL_STACK(%r13) 275 266 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 276 267 stmg %r0,%r7,STACK_FRAME_OVERHEAD+__PT_R0(%r15) 277 268 # clear user controlled register to prevent speculative use ··· 287 276 xgr %r10,%r10 288 277 xgr %r11,%r11 289 278 la %r2,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs 290 - mvc __PT_R8(64,%r2),__LC_SAVE_AREA_SYNC 291 - MBEAR %r2 279 + mvc __PT_R8(64,%r2),__LC_SAVE_AREA_SYNC(%r13) 280 + MBEAR %r2,%r13 292 281 lgr %r3,%r14 293 282 brasl %r14,__do_syscall 294 283 STACKLEAK_ERASE 295 - lctlg %c1,%c1,__LC_USER_ASCE 296 - mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) 284 + lctlg %c1,%c1,__LC_USER_ASCE(%r13) 285 + mvc __LC_RETURN_PSW(16,%r13),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) 297 286 BPON 298 287 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15) 288 + stpt __LC_EXIT_TIMER(%r13) 299 289 lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15) 300 - stpt __LC_EXIT_TIMER 301 290 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE 302 291 SYM_CODE_END(system_call) 303 292 ··· 308 297 lgr %r3,%r11 309 298 brasl %r14,__ret_from_fork 310 299 STACKLEAK_ERASE 311 - lctlg %c1,%c1,__LC_USER_ASCE 312 - mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) 300 + GET_LC %r13 301 + lctlg %c1,%c1,__LC_USER_ASCE(%r13) 302 + mvc __LC_RETURN_PSW(16,%r13),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) 313 303 BPON 314 304 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15) 305 + stpt __LC_EXIT_TIMER(%r13) 315 306 lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15) 316 - stpt __LC_EXIT_TIMER 317 307 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE 318 308 SYM_CODE_END(ret_from_fork) 319 309 ··· 323 311 */ 324 312 325 313 SYM_CODE_START(pgm_check_handler) 326 - stpt __LC_SYS_ENTER_TIMER 314 + STMG_LC %r8,%r15,__LC_SAVE_AREA_SYNC 315 + GET_LC %r13 316 + stpt __LC_SYS_ENTER_TIMER(%r13) 327 317 BPOFF 328 - stmg %r8,%r15,__LC_SAVE_AREA_SYNC 329 318 lgr %r10,%r15 330 - lmg %r8,%r9,__LC_PGM_OLD_PSW 319 + lmg %r8,%r9,__LC_PGM_OLD_PSW(%r13) 331 320 tmhh %r8,0x0001 # coming from user space? 332 321 jno .Lpgm_skip_asce 333 - lctlg %c1,%c1,__LC_KERNEL_ASCE 322 + lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) 334 323 j 3f # -> fault in user space 335 324 .Lpgm_skip_asce: 336 325 1: tmhh %r8,0x4000 # PER bit set in old PSW ? 337 326 jnz 2f # -> enabled, can't be a double fault 338 - tm __LC_PGM_ILC+3,0x80 # check for per exception 327 + tm __LC_PGM_ILC+3(%r13),0x80 # check for per exception 339 328 jnz .Lpgm_svcper # -> single stepped svc 340 - 2: CHECK_STACK __LC_SAVE_AREA_SYNC 329 + 2: CHECK_STACK __LC_SAVE_AREA_SYNC,%r13 341 330 aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 342 331 # CHECK_VMAP_STACK branches to stack_overflow or 4f 343 - CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f 344 - 3: lg %r15,__LC_KERNEL_STACK 332 + CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,%r13,4f 333 + 3: lg %r15,__LC_KERNEL_STACK(%r13) 345 334 4: la %r11,STACK_FRAME_OVERHEAD(%r15) 346 335 xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) 347 336 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 348 337 stmg %r0,%r7,__PT_R0(%r11) 349 - mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC 350 - mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK 338 + mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC(%r13) 339 + mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK(%r13) 351 340 stctg %c1,%c1,__PT_CR1(%r11) 352 341 #if IS_ENABLED(CONFIG_KVM) 353 - ltg %r12,__LC_GMAP 342 + ltg %r12,__LC_GMAP(%r13) 354 343 jz 5f 355 344 clc __GMAP_ASCE(8,%r12), __PT_CR1(%r11) 356 345 jne 5f 357 346 BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST 358 - SIEEXIT __SF_SIE_CONTROL(%r10) 347 + SIEEXIT __SF_SIE_CONTROL(%r10),%r13 359 348 #endif 360 349 5: stmg %r8,%r9,__PT_PSW(%r11) 361 350 # clear user controlled registers to prevent speculative use ··· 372 359 tmhh %r8,0x0001 # returning to user space? 373 360 jno .Lpgm_exit_kernel 374 361 STACKLEAK_ERASE 375 - lctlg %c1,%c1,__LC_USER_ASCE 362 + lctlg %c1,%c1,__LC_USER_ASCE(%r13) 376 363 BPON 377 - stpt __LC_EXIT_TIMER 364 + stpt __LC_EXIT_TIMER(%r13) 378 365 .Lpgm_exit_kernel: 379 - mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) 366 + mvc __LC_RETURN_PSW(16,%r13),STACK_FRAME_OVERHEAD+__PT_PSW(%r15) 380 367 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15) 381 368 lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15) 382 369 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE ··· 385 372 # single stepped system call 386 373 # 387 374 .Lpgm_svcper: 388 - mvc __LC_RETURN_PSW(8),__LC_SVC_NEW_PSW 375 + mvc __LC_RETURN_PSW(8,%r13),__LC_SVC_NEW_PSW(%r13) 389 376 larl %r14,.Lsysc_per 390 - stg %r14,__LC_RETURN_PSW+8 377 + stg %r14,__LC_RETURN_PSW+8(%r13) 391 378 lghi %r14,1 392 - LBEAR __LC_PGM_LAST_BREAK 379 + LBEAR __LC_PGM_LAST_BREAK(%r13) 393 380 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE # branch to .Lsysc_per 394 381 SYM_CODE_END(pgm_check_handler) 395 382 ··· 398 385 */ 399 386 .macro INT_HANDLER name,lc_old_psw,handler 400 387 SYM_CODE_START(\name) 401 - stckf __LC_INT_CLOCK 402 - stpt __LC_SYS_ENTER_TIMER 403 - STBEAR __LC_LAST_BREAK 388 + STMG_LC %r8,%r15,__LC_SAVE_AREA_ASYNC 389 + GET_LC %r13 390 + stckf __LC_INT_CLOCK(%r13) 391 + stpt __LC_SYS_ENTER_TIMER(%r13) 392 + STBEAR __LC_LAST_BREAK(%r13) 404 393 BPOFF 405 - stmg %r8,%r15,__LC_SAVE_AREA_ASYNC 406 - lmg %r8,%r9,\lc_old_psw 394 + lmg %r8,%r9,\lc_old_psw(%r13) 407 395 tmhh %r8,0x0001 # interrupting from user ? 408 396 jnz 1f 409 397 #if IS_ENABLED(CONFIG_KVM) 410 - TSTMSK __LC_CPU_FLAGS,_CIF_SIE 398 + lg %r10,__LC_CURRENT(%r13) 399 + tm __TI_sie(%r10),0xff 411 400 jz 0f 412 401 BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST 413 - SIEEXIT __SF_SIE_CONTROL(%r15) 402 + SIEEXIT __SF_SIE_CONTROL(%r15),%r13 414 403 #endif 415 - 0: CHECK_STACK __LC_SAVE_AREA_ASYNC 404 + 0: CHECK_STACK __LC_SAVE_AREA_ASYNC,%r13 416 405 aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 417 406 j 2f 418 - 1: lctlg %c1,%c1,__LC_KERNEL_ASCE 419 - lg %r15,__LC_KERNEL_STACK 407 + 1: lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) 408 + lg %r15,__LC_KERNEL_STACK(%r13) 420 409 2: xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 421 410 la %r11,STACK_FRAME_OVERHEAD(%r15) 422 411 stmg %r0,%r7,__PT_R0(%r11) ··· 432 417 xgr %r7,%r7 433 418 xgr %r10,%r10 434 419 xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) 435 - mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC 436 - MBEAR %r11 420 + mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC(%r13) 421 + MBEAR %r11,%r13 437 422 stmg %r8,%r9,__PT_PSW(%r11) 438 423 lgr %r2,%r11 # pass pointer to pt_regs 439 424 brasl %r14,\handler 440 - mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) 425 + mvc __LC_RETURN_PSW(16,%r13),__PT_PSW(%r11) 441 426 tmhh %r8,0x0001 # returning to user ? 442 427 jno 2f 443 428 STACKLEAK_ERASE 444 - lctlg %c1,%c1,__LC_USER_ASCE 429 + lctlg %c1,%c1,__LC_USER_ASCE(%r13) 445 430 BPON 446 - stpt __LC_EXIT_TIMER 431 + stpt __LC_EXIT_TIMER(%r13) 447 432 2: LBEAR __PT_LAST_BREAK(%r11) 448 433 lmg %r0,%r15,__PT_R0(%r11) 449 434 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE ··· 458 443 */ 459 444 SYM_CODE_START(mcck_int_handler) 460 445 BPOFF 461 - lmg %r8,%r9,__LC_MCK_OLD_PSW 462 - TSTMSK __LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE 446 + GET_LC %r13 447 + lmg %r8,%r9,__LC_MCK_OLD_PSW(%r13) 448 + TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE_SYSTEM_DAMAGE 463 449 jo .Lmcck_panic # yes -> rest of mcck code invalid 464 - TSTMSK __LC_MCCK_CODE,MCCK_CODE_CR_VALID 450 + TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE_CR_VALID 465 451 jno .Lmcck_panic # control registers invalid -> panic 466 452 ptlb 467 - lghi %r14,__LC_CPU_TIMER_SAVE_AREA 468 - mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 469 - TSTMSK __LC_MCCK_CODE,MCCK_CODE_CPU_TIMER_VALID 453 + lay %r14,__LC_CPU_TIMER_SAVE_AREA(%r13) 454 + mvc __LC_MCCK_ENTER_TIMER(8,%r13),0(%r14) 455 + TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE_CPU_TIMER_VALID 470 456 jo 3f 471 - la %r14,__LC_SYS_ENTER_TIMER 472 - clc 0(8,%r14),__LC_EXIT_TIMER 457 + la %r14,__LC_SYS_ENTER_TIMER(%r13) 458 + clc 0(8,%r14),__LC_EXIT_TIMER(%r13) 473 459 jl 1f 474 - la %r14,__LC_EXIT_TIMER 475 - 1: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER 460 + la %r14,__LC_EXIT_TIMER(%r13) 461 + 1: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER(%r13) 476 462 jl 2f 477 - la %r14,__LC_LAST_UPDATE_TIMER 463 + la %r14,__LC_LAST_UPDATE_TIMER(%r13) 478 464 2: spt 0(%r14) 479 - mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 480 - 3: TSTMSK __LC_MCCK_CODE,MCCK_CODE_PSW_MWP_VALID 465 + mvc __LC_MCCK_ENTER_TIMER(8,%r13),0(%r14) 466 + 3: TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE_PSW_MWP_VALID 481 467 jno .Lmcck_panic 482 468 tmhh %r8,0x0001 # interrupting from user ? 483 469 jnz .Lmcck_user 484 - TSTMSK __LC_MCCK_CODE,MCCK_CODE_PSW_IA_VALID 470 + TSTMSK __LC_MCCK_CODE(%r13),MCCK_CODE_PSW_IA_VALID 485 471 jno .Lmcck_panic 486 472 #if IS_ENABLED(CONFIG_KVM) 487 - TSTMSK __LC_CPU_FLAGS,_CIF_SIE 473 + lg %r10,__LC_CURRENT(%r13) 474 + tm __TI_sie(%r10),0xff 488 475 jz .Lmcck_user 489 - # Need to compare the address instead of a CIF_SIE* flag. 476 + # Need to compare the address instead of __TI_SIE flag. 490 477 # Otherwise there would be a race between setting the flag 491 478 # and entering SIE (or leaving and clearing the flag). This 492 479 # would cause machine checks targeted at the guest to be ··· 497 480 clgrjl %r9,%r14, 4f 498 481 larl %r14,.Lsie_leave 499 482 clgrjhe %r9,%r14, 4f 500 - oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST 483 + lg %r10,__LC_PCPU 484 + oi __PCPU_FLAGS+7(%r10), _CIF_MCCK_GUEST 501 485 4: BPENTER __SF_SIE_FLAGS(%r15),_TIF_ISOLATE_BP_GUEST 502 - SIEEXIT __SF_SIE_CONTROL(%r15) 486 + SIEEXIT __SF_SIE_CONTROL(%r15),%r13 503 487 #endif 504 488 .Lmcck_user: 505 - lg %r15,__LC_MCCK_STACK 489 + lg %r15,__LC_MCCK_STACK(%r13) 506 490 la %r11,STACK_FRAME_OVERHEAD(%r15) 507 491 stctg %c1,%c1,__PT_CR1(%r11) 508 - lctlg %c1,%c1,__LC_KERNEL_ASCE 492 + lctlg %c1,%c1,__LC_KERNEL_ASCE(%r13) 509 493 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 510 - lghi %r14,__LC_GPREGS_SAVE_AREA+64 511 - stmg %r0,%r7,__PT_R0(%r11) 494 + lay %r14,__LC_GPREGS_SAVE_AREA(%r13) 495 + mvc __PT_R0(128,%r11),0(%r14) 512 496 # clear user controlled registers to prevent speculative use 513 497 xgr %r0,%r0 514 498 xgr %r1,%r1 ··· 519 501 xgr %r6,%r6 520 502 xgr %r7,%r7 521 503 xgr %r10,%r10 522 - mvc __PT_R8(64,%r11),0(%r14) 523 504 stmg %r8,%r9,__PT_PSW(%r11) 524 505 xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11) 525 506 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) ··· 526 509 brasl %r14,s390_do_machine_check 527 510 lctlg %c1,%c1,__PT_CR1(%r11) 528 511 lmg %r0,%r10,__PT_R0(%r11) 529 - mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW 530 - tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? 512 + mvc __LC_RETURN_MCCK_PSW(16,%r13),__PT_PSW(%r11) # move return PSW 513 + tm __LC_RETURN_MCCK_PSW+1(%r13),0x01 # returning to user ? 531 514 jno 0f 532 515 BPON 533 - stpt __LC_EXIT_TIMER 534 - 0: ALTERNATIVE "nop", __stringify(lghi %r12,__LC_LAST_BREAK_SAVE_AREA),193 516 + stpt __LC_EXIT_TIMER(%r13) 517 + 0: ALTERNATIVE "brcl 0,0", __stringify(lay %r12,__LC_LAST_BREAK_SAVE_AREA(%r13)),\ 518 + ALT_FACILITY(193) 535 519 LBEAR 0(%r12) 536 520 lmg %r11,%r15,__PT_R11(%r11) 537 521 LPSWEY __LC_RETURN_MCCK_PSW,__LC_RETURN_MCCK_LPSWE ··· 568 550 SYM_CODE_END(mcck_int_handler) 569 551 570 552 SYM_CODE_START(restart_int_handler) 571 - ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40 553 + ALTERNATIVE "nop", "lpp _LPP_OFFSET", ALT_FACILITY(40) 572 554 stg %r15,__LC_SAVE_AREA_RESTART 573 555 TSTMSK __LC_RESTART_FLAGS,RESTART_FLAG_CTLREGS,4 574 556 jz 0f ··· 576 558 0: larl %r15,daton_psw 577 559 lpswe 0(%r15) # turn dat on, keep irqs off 578 560 .Ldaton: 579 - lg %r15,__LC_RESTART_STACK 561 + GET_LC %r15 562 + lg %r15,__LC_RESTART_STACK(%r15) 580 563 xc STACK_FRAME_OVERHEAD(__PT_SIZE,%r15),STACK_FRAME_OVERHEAD(%r15) 581 564 stmg %r0,%r14,STACK_FRAME_OVERHEAD+__PT_R0(%r15) 582 - mvc STACK_FRAME_OVERHEAD+__PT_R15(8,%r15),__LC_SAVE_AREA_RESTART 583 - mvc STACK_FRAME_OVERHEAD+__PT_PSW(16,%r15),__LC_RST_OLD_PSW 565 + GET_LC %r13 566 + mvc STACK_FRAME_OVERHEAD+__PT_R15(8,%r15),__LC_SAVE_AREA_RESTART(%r13) 567 + mvc STACK_FRAME_OVERHEAD+__PT_PSW(16,%r15),__LC_RST_OLD_PSW(%r13) 584 568 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15) 585 - lg %r1,__LC_RESTART_FN # load fn, parm & source cpu 586 - lg %r2,__LC_RESTART_DATA 587 - lgf %r3,__LC_RESTART_SOURCE 569 + lg %r1,__LC_RESTART_FN(%r13) # load fn, parm & source cpu 570 + lg %r2,__LC_RESTART_DATA(%r13) 571 + lgf %r3,__LC_RESTART_SOURCE(%r13) 588 572 ltgr %r3,%r3 # test source cpu address 589 573 jm 1f # negative -> skip source stop 590 574 0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu ··· 608 588 * Setup a pt_regs so that show_trace can provide a good call trace. 609 589 */ 610 590 SYM_CODE_START(stack_overflow) 611 - lg %r15,__LC_NODAT_STACK # change to panic stack 591 + GET_LC %r15 592 + lg %r15,__LC_NODAT_STACK(%r15) # change to panic stack 612 593 la %r11,STACK_FRAME_OVERHEAD(%r15) 613 594 stmg %r0,%r7,__PT_R0(%r11) 614 595 stmg %r8,%r9,__PT_PSW(%r11)
+5 -3
arch/s390/kernel/head64.S
··· 10 10 11 11 #include <linux/init.h> 12 12 #include <linux/linkage.h> 13 + #include <asm/lowcore.h> 13 14 #include <asm/asm-offsets.h> 14 15 #include <asm/thread_info.h> 15 16 #include <asm/page.h> ··· 19 18 __HEAD 20 19 SYM_CODE_START(startup_continue) 21 20 larl %r1,tod_clock_base 22 - mvc 0(16,%r1),__LC_BOOT_CLOCK 21 + GET_LC %r2 22 + mvc 0(16,%r1),__LC_BOOT_CLOCK(%r2) 23 23 # 24 24 # Setup stack 25 25 # 26 26 larl %r14,init_task 27 - stg %r14,__LC_CURRENT 27 + stg %r14,__LC_CURRENT(%r2) 28 28 larl %r15,init_thread_union+STACK_INIT_OFFSET 29 - stg %r15,__LC_KERNEL_STACK 29 + stg %r15,__LC_KERNEL_STACK(%r2) 30 30 brasl %r14,sclp_early_adjust_va # allow sclp_early_printk 31 31 brasl %r14,startup_init # s390 specific early init 32 32 brasl %r14,start_kernel # common init code
+1 -1
arch/s390/kernel/ipl.c
··· 2112 2112 tracing_off(); 2113 2113 debug_locks_off(); 2114 2114 lgr_info_log(); 2115 - smp_call_online_cpu(__do_restart, arg); 2115 + smp_call_ipl_cpu(__do_restart, arg); 2116 2116 } 2117 2117 2118 2118 /* on halt */
+1 -1
arch/s390/kernel/machine_kexec.c
··· 62 62 * This need to be done *after* s390_reset_system set the 63 63 * prefix register of this CPU to zero 64 64 */ 65 - memcpy(absolute_pointer(__LC_FPREGS_SAVE_AREA), 65 + memcpy(absolute_pointer(get_lowcore()->floating_pt_save_area), 66 66 phys_to_virt(prefix + __LC_FPREGS_SAVE_AREA), 512); 67 67 68 68 call_nodat(1, int, purgatory, int, 1);
+9 -7
arch/s390/kernel/nospec-branch.c
··· 4 4 #include <linux/cpu.h> 5 5 #include <asm/nospec-branch.h> 6 6 7 + int nobp = IS_ENABLED(CONFIG_KERNEL_NOBP); 8 + 7 9 static int __init nobp_setup_early(char *str) 8 10 { 9 11 bool enabled; ··· 19 17 * The user explicitly requested nobp=1, enable it and 20 18 * disable the expoline support. 21 19 */ 22 - __set_facility(82, alt_stfle_fac_list); 20 + nobp = 1; 23 21 if (IS_ENABLED(CONFIG_EXPOLINE)) 24 22 nospec_disable = 1; 25 23 } else { 26 - __clear_facility(82, alt_stfle_fac_list); 24 + nobp = 0; 27 25 } 28 26 return 0; 29 27 } ··· 31 29 32 30 static int __init nospec_setup_early(char *str) 33 31 { 34 - __clear_facility(82, alt_stfle_fac_list); 32 + nobp = 0; 35 33 return 0; 36 34 } 37 35 early_param("nospec", nospec_setup_early); ··· 42 40 pr_info("Spectre V2 mitigation: etokens\n"); 43 41 if (nospec_uses_trampoline()) 44 42 pr_info("Spectre V2 mitigation: execute trampolines\n"); 45 - if (__test_facility(82, alt_stfle_fac_list)) 43 + if (nobp_enabled()) 46 44 pr_info("Spectre V2 mitigation: limited branch prediction\n"); 47 45 return 0; 48 46 } ··· 68 66 */ 69 67 if (__is_defined(CC_USING_EXPOLINE)) 70 68 nospec_disable = 1; 71 - __clear_facility(82, alt_stfle_fac_list); 69 + nobp = 0; 72 70 } else if (__is_defined(CC_USING_EXPOLINE)) { 73 71 /* 74 72 * The kernel has been compiled with expolines. 75 73 * Keep expolines enabled and disable nobp. 76 74 */ 77 75 nospec_disable = 0; 78 - __clear_facility(82, alt_stfle_fac_list); 76 + nobp = 0; 79 77 } 80 78 /* 81 79 * If the kernel has not been compiled with expolines the ··· 88 86 { 89 87 if (str && !strncmp(str, "on", 2)) { 90 88 nospec_disable = 0; 91 - __clear_facility(82, alt_stfle_fac_list); 89 + nobp = 0; 92 90 } 93 91 if (str && !strncmp(str, "off", 3)) 94 92 nospec_disable = 1;
+1 -1
arch/s390/kernel/nospec-sysfs.c
··· 17 17 return sprintf(buf, "Mitigation: etokens\n"); 18 18 if (nospec_uses_trampoline()) 19 19 return sprintf(buf, "Mitigation: execute trampolines\n"); 20 - if (__test_facility(82, alt_stfle_fac_list)) 20 + if (nobp_enabled()) 21 21 return sprintf(buf, "Mitigation: limited branch prediction\n"); 22 22 return sprintf(buf, "Vulnerable\n"); 23 23 }
+10 -4
arch/s390/kernel/perf_cpum_cf.c
··· 556 556 struct cf_trailer_entry *trailer_start, *trailer_stop; 557 557 struct cf_ctrset_entry *ctrstart, *ctrstop; 558 558 size_t offset = 0; 559 + int i; 559 560 560 - auth &= (1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1; 561 - do { 561 + for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) { 562 562 ctrstart = (struct cf_ctrset_entry *)(cpuhw->start + offset); 563 563 ctrstop = (struct cf_ctrset_entry *)(cpuhw->stop + offset); 564 + 565 + /* Counter set not authorized */ 566 + if (!(auth & cpumf_ctr_ctl[i])) 567 + continue; 568 + /* Counter set size zero was not saved */ 569 + if (!cpum_cf_read_setsize(i)) 570 + continue; 564 571 565 572 if (memcmp(ctrstop, ctrstart, sizeof(*ctrstop))) { 566 573 pr_err_once("cpum_cf_diag counter set compare error " 567 574 "in set %i\n", ctrstart->set); 568 575 return 0; 569 576 } 570 - auth &= ~cpumf_ctr_ctl[ctrstart->set]; 571 577 if (ctrstart->def == CF_DIAG_CTRSET_DEF) { 572 578 cfdiag_diffctrset((u64 *)(ctrstart + 1), 573 579 (u64 *)(ctrstop + 1), ctrstart->ctr); 574 580 offset += ctrstart->ctr * sizeof(u64) + 575 581 sizeof(*ctrstart); 576 582 } 577 - } while (ctrstart->def && auth); 583 + } 578 584 579 585 /* Save time_stamp from start of event in stop's trailer */ 580 586 trailer_start = (struct cf_trailer_entry *)(cpuhw->start + offset);
+19 -1
arch/s390/kernel/processor.c
··· 17 17 #include <linux/mm_types.h> 18 18 #include <linux/delay.h> 19 19 #include <linux/cpu.h> 20 - 20 + #include <linux/smp.h> 21 + #include <asm/text-patching.h> 21 22 #include <asm/diag.h> 22 23 #include <asm/facility.h> 23 24 #include <asm/elf.h> ··· 78 77 if (arch_vcpu_is_preempted(cpu)) 79 78 smp_yield_cpu(cpu); 80 79 } 80 + } 81 + 82 + static void do_sync_core(void *info) 83 + { 84 + sync_core(); 85 + } 86 + 87 + void text_poke_sync(void) 88 + { 89 + on_each_cpu(do_sync_core, NULL, 1); 90 + } 91 + 92 + void text_poke_sync_lock(void) 93 + { 94 + cpus_read_lock(); 95 + text_poke_sync(); 96 + cpus_read_unlock(); 81 97 } 82 98 83 99 /*
+11 -15
arch/s390/kernel/reipl.S
··· 9 9 #include <asm/asm-offsets.h> 10 10 #include <asm/nospec-insn.h> 11 11 #include <asm/sigp.h> 12 + #include <asm/lowcore.h> 12 13 13 14 GEN_BR_THUNK %r9 14 15 ··· 21 20 # r3 = Parameter for function 22 21 # 23 22 SYM_CODE_START(store_status) 24 - /* Save register one and load save area base */ 25 - stg %r1,__LC_SAVE_AREA_RESTART 23 + STMG_LC %r0,%r15,__LC_GPREGS_SAVE_AREA 26 24 /* General purpose registers */ 27 - lghi %r1,__LC_GPREGS_SAVE_AREA 28 - stmg %r0,%r15,0(%r1) 29 - mvc 8(8,%r1),__LC_SAVE_AREA_RESTART 25 + GET_LC %r13 30 26 /* Control registers */ 31 - lghi %r1,__LC_CREGS_SAVE_AREA 32 - stctg %c0,%c15,0(%r1) 27 + stctg %c0,%c15,__LC_CREGS_SAVE_AREA(%r13) 33 28 /* Access registers */ 34 - lghi %r1,__LC_AREGS_SAVE_AREA 35 - stam %a0,%a15,0(%r1) 29 + stamy %a0,%a15,__LC_AREGS_SAVE_AREA(%r13) 36 30 /* Floating point registers */ 37 - lghi %r1,__LC_FPREGS_SAVE_AREA 31 + lay %r1,__LC_FPREGS_SAVE_AREA(%r13) 38 32 std %f0, 0x00(%r1) 39 33 std %f1, 0x08(%r1) 40 34 std %f2, 0x10(%r1) ··· 47 51 std %f14,0x70(%r1) 48 52 std %f15,0x78(%r1) 49 53 /* Floating point control register */ 50 - lghi %r1,__LC_FP_CREG_SAVE_AREA 54 + lay %r1,__LC_FP_CREG_SAVE_AREA(%r13) 51 55 stfpc 0(%r1) 52 56 /* CPU timer */ 53 - lghi %r1,__LC_CPU_TIMER_SAVE_AREA 57 + lay %r1,__LC_CPU_TIMER_SAVE_AREA(%r13) 54 58 stpt 0(%r1) 55 59 /* Store prefix register */ 56 - lghi %r1,__LC_PREFIX_SAVE_AREA 60 + lay %r1,__LC_PREFIX_SAVE_AREA(%r13) 57 61 stpx 0(%r1) 58 62 /* Clock comparator - seven bytes */ 59 - lghi %r1,__LC_CLOCK_COMP_SAVE_AREA 60 63 larl %r4,clkcmp 61 64 stckc 0(%r4) 65 + lay %r1,__LC_CLOCK_COMP_SAVE_AREA(%r13) 62 66 mvc 1(7,%r1),1(%r4) 63 67 /* Program status word */ 64 - lghi %r1,__LC_PSW_SAVE_AREA 68 + lay %r1,__LC_PSW_SAVE_AREA(%r13) 65 69 epsw %r4,%r5 66 70 st %r4,0(%r1) 67 71 st %r5,4(%r1)
+5 -2
arch/s390/kernel/setup.c
··· 149 149 struct physmem_info __bootdata(physmem_info); 150 150 151 151 struct vm_layout __bootdata_preserved(vm_layout); 152 - EXPORT_SYMBOL_GPL(vm_layout); 152 + EXPORT_SYMBOL(vm_layout); 153 153 int __bootdata_preserved(__kaslr_enabled); 154 154 unsigned int __bootdata_preserved(zlib_dfltcc_support); 155 155 EXPORT_SYMBOL(zlib_dfltcc_support); 156 156 u64 __bootdata_preserved(stfle_fac_list[16]); 157 157 EXPORT_SYMBOL(stfle_fac_list); 158 - u64 alt_stfle_fac_list[16]; 159 158 struct oldmem_data __bootdata_preserved(oldmem_data); 160 159 161 160 unsigned long VMALLOC_START; ··· 405 406 panic("%s: Failed to allocate %zu bytes align=%zx\n", 406 407 __func__, sizeof(*lc), sizeof(*lc)); 407 408 409 + lc->pcpu = (unsigned long)per_cpu_ptr(&pcpu_devices, 0); 408 410 lc->restart_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_DAT; 409 411 lc->restart_psw.addr = __pa(restart_int_handler); 410 412 lc->external_new_psw.mask = PSW_KERNEL_BITS; ··· 888 888 pr_info("Linux is running natively in 64-bit mode\n"); 889 889 else 890 890 pr_info("Linux is running as a guest in 64-bit mode\n"); 891 + 892 + if (have_relocated_lowcore()) 893 + pr_info("Lowcore relocated to 0x%px\n", get_lowcore()); 891 894 892 895 log_component_list(); 893 896
+62 -79
arch/s390/kernel/smp.c
··· 74 74 CPU_STATE_CONFIGURED, 75 75 }; 76 76 77 - struct pcpu { 78 - unsigned long ec_mask; /* bit mask for ec_xxx functions */ 79 - unsigned long ec_clk; /* sigp timestamp for ec_xxx */ 80 - signed char state; /* physical cpu state */ 81 - signed char polarization; /* physical polarization */ 82 - u16 address; /* physical cpu address */ 83 - }; 84 - 85 77 static u8 boot_core_type; 86 - static struct pcpu pcpu_devices[NR_CPUS]; 78 + DEFINE_PER_CPU(struct pcpu, pcpu_devices); 79 + /* 80 + * Pointer to the pcpu area of the boot CPU. This is required when a restart 81 + * interrupt is triggered on an offline CPU. For that case accessing percpu 82 + * data with the common primitives does not work, since the percpu offset is 83 + * stored in a non existent lowcore. 84 + */ 85 + static struct pcpu *ipl_pcpu; 87 86 88 87 unsigned int smp_cpu_mt_shift; 89 88 EXPORT_SYMBOL(smp_cpu_mt_shift); ··· 173 174 int cpu; 174 175 175 176 for_each_cpu(cpu, mask) 176 - if (pcpu_devices[cpu].address == address) 177 - return pcpu_devices + cpu; 177 + if (per_cpu(pcpu_devices, cpu).address == address) 178 + return &per_cpu(pcpu_devices, cpu); 178 179 return NULL; 179 180 } 180 181 ··· 229 230 return -ENOMEM; 230 231 } 231 232 232 - static void pcpu_free_lowcore(struct pcpu *pcpu) 233 + static void pcpu_free_lowcore(struct pcpu *pcpu, int cpu) 233 234 { 234 235 unsigned long async_stack, nodat_stack, mcck_stack; 235 236 struct lowcore *lc; 236 - int cpu; 237 237 238 - cpu = pcpu - pcpu_devices; 239 238 lc = lowcore_ptr[cpu]; 240 239 nodat_stack = lc->nodat_stack - STACK_INIT_OFFSET; 241 240 async_stack = lc->async_stack - STACK_INIT_OFFSET; ··· 256 259 cpumask_set_cpu(cpu, &init_mm.context.cpu_attach_mask); 257 260 cpumask_set_cpu(cpu, mm_cpumask(&init_mm)); 258 261 lc->cpu_nr = cpu; 262 + lc->pcpu = (unsigned long)pcpu; 259 263 lc->restart_flags = RESTART_FLAG_CTLREGS; 260 264 lc->spinlock_lockval = arch_spin_lockval(cpu); 261 265 lc->spinlock_index = 0; ··· 275 277 arch_spin_lock_setup(cpu); 276 278 } 277 279 278 - static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk) 280 + static void pcpu_attach_task(int cpu, struct task_struct *tsk) 279 281 { 280 282 struct lowcore *lc; 281 - int cpu; 282 283 283 - cpu = pcpu - pcpu_devices; 284 284 lc = lowcore_ptr[cpu]; 285 285 lc->kernel_stack = (unsigned long)task_stack_page(tsk) + STACK_INIT_OFFSET; 286 286 lc->current_task = (unsigned long)tsk; ··· 292 296 lc->steal_timer = 0; 293 297 } 294 298 295 - static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data) 299 + static void pcpu_start_fn(int cpu, void (*func)(void *), void *data) 296 300 { 297 301 struct lowcore *lc; 298 - int cpu; 299 302 300 - cpu = pcpu - pcpu_devices; 301 303 lc = lowcore_ptr[cpu]; 302 304 lc->restart_stack = lc->kernel_stack; 303 305 lc->restart_fn = (unsigned long) func; 304 306 lc->restart_data = (unsigned long) data; 305 307 lc->restart_source = -1U; 306 - pcpu_sigp_retry(pcpu, SIGP_RESTART, 0); 308 + pcpu_sigp_retry(per_cpu_ptr(&pcpu_devices, cpu), SIGP_RESTART, 0); 307 309 } 308 310 309 311 typedef void (pcpu_delegate_fn)(void *); ··· 314 320 func(data); /* should not return */ 315 321 } 316 322 317 - static void pcpu_delegate(struct pcpu *pcpu, 323 + static void pcpu_delegate(struct pcpu *pcpu, int cpu, 318 324 pcpu_delegate_fn *func, 319 325 void *data, unsigned long stack) 320 326 { 321 327 struct lowcore *lc, *abs_lc; 322 328 unsigned int source_cpu; 323 329 324 - lc = lowcore_ptr[pcpu - pcpu_devices]; 330 + lc = lowcore_ptr[cpu]; 325 331 source_cpu = stap(); 326 332 327 333 if (pcpu->address == source_cpu) { ··· 371 377 smp_cpu_mt_shift = 0; 372 378 while (smp_cpu_mtid >= (1U << smp_cpu_mt_shift)) 373 379 smp_cpu_mt_shift++; 374 - pcpu_devices[0].address = stap(); 380 + per_cpu(pcpu_devices, 0).address = stap(); 375 381 } 376 382 return cc; 377 - } 378 - 379 - /* 380 - * Call function on an online CPU. 381 - */ 382 - void smp_call_online_cpu(void (*func)(void *), void *data) 383 - { 384 - struct pcpu *pcpu; 385 - 386 - /* Use the current cpu if it is online. */ 387 - pcpu = pcpu_find_address(cpu_online_mask, stap()); 388 - if (!pcpu) 389 - /* Use the first online cpu. */ 390 - pcpu = pcpu_devices + cpumask_first(cpu_online_mask); 391 - pcpu_delegate(pcpu, func, data, (unsigned long) restart_stack); 392 383 } 393 384 394 385 /* ··· 383 404 { 384 405 struct lowcore *lc = lowcore_ptr[0]; 385 406 386 - if (pcpu_devices[0].address == stap()) 407 + if (ipl_pcpu->address == stap()) 387 408 lc = get_lowcore(); 388 409 389 - pcpu_delegate(&pcpu_devices[0], func, data, 390 - lc->nodat_stack); 410 + pcpu_delegate(ipl_pcpu, 0, func, data, lc->nodat_stack); 391 411 } 392 412 393 413 int smp_find_processor_id(u16 address) ··· 394 416 int cpu; 395 417 396 418 for_each_present_cpu(cpu) 397 - if (pcpu_devices[cpu].address == address) 419 + if (per_cpu(pcpu_devices, cpu).address == address) 398 420 return cpu; 399 421 return -1; 400 422 } 401 423 402 424 void schedule_mcck_handler(void) 403 425 { 404 - pcpu_ec_call(pcpu_devices + smp_processor_id(), ec_mcck_pending); 426 + pcpu_ec_call(this_cpu_ptr(&pcpu_devices), ec_mcck_pending); 405 427 } 406 428 407 429 bool notrace arch_vcpu_is_preempted(int cpu) 408 430 { 409 431 if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu)) 410 432 return false; 411 - if (pcpu_running(pcpu_devices + cpu)) 433 + if (pcpu_running(per_cpu_ptr(&pcpu_devices, cpu))) 412 434 return false; 413 435 return true; 414 436 } ··· 420 442 return; 421 443 diag_stat_inc_norecursion(DIAG_STAT_X09C); 422 444 asm volatile("diag %0,0,0x9c" 423 - : : "d" (pcpu_devices[cpu].address)); 445 + : : "d" (per_cpu(pcpu_devices, cpu).address)); 424 446 } 425 447 EXPORT_SYMBOL_GPL(smp_yield_cpu); 426 448 ··· 441 463 442 464 end = get_tod_clock() + (1000000UL << 12); 443 465 for_each_cpu(cpu, &cpumask) { 444 - struct pcpu *pcpu = pcpu_devices + cpu; 466 + struct pcpu *pcpu = per_cpu_ptr(&pcpu_devices, cpu); 445 467 set_bit(ec_stop_cpu, &pcpu->ec_mask); 446 468 while (__pcpu_sigp(pcpu->address, SIGP_EMERGENCY_SIGNAL, 447 469 0, NULL) == SIGP_CC_BUSY && ··· 450 472 } 451 473 while (get_tod_clock() < end) { 452 474 for_each_cpu(cpu, &cpumask) 453 - if (pcpu_stopped(pcpu_devices + cpu)) 475 + if (pcpu_stopped(per_cpu_ptr(&pcpu_devices, cpu))) 454 476 cpumask_clear_cpu(cpu, &cpumask); 455 477 if (cpumask_empty(&cpumask)) 456 478 break; ··· 465 487 */ 466 488 void smp_send_stop(void) 467 489 { 490 + struct pcpu *pcpu; 468 491 int cpu; 469 492 470 493 /* Disable all interrupts/machine checks */ ··· 481 502 for_each_online_cpu(cpu) { 482 503 if (cpu == smp_processor_id()) 483 504 continue; 484 - pcpu_sigp_retry(pcpu_devices + cpu, SIGP_STOP, 0); 485 - while (!pcpu_stopped(pcpu_devices + cpu)) 505 + pcpu = per_cpu_ptr(&pcpu_devices, cpu); 506 + pcpu_sigp_retry(pcpu, SIGP_STOP, 0); 507 + while (!pcpu_stopped(pcpu)) 486 508 cpu_relax(); 487 509 } 488 510 } ··· 497 517 unsigned long bits; 498 518 499 519 /* handle bit signal external calls */ 500 - bits = xchg(&pcpu_devices[smp_processor_id()].ec_mask, 0); 520 + bits = this_cpu_xchg(pcpu_devices.ec_mask, 0); 501 521 if (test_bit(ec_stop_cpu, &bits)) 502 522 smp_stop_cpu(); 503 523 if (test_bit(ec_schedule, &bits)) ··· 522 542 int cpu; 523 543 524 544 for_each_cpu(cpu, mask) 525 - pcpu_ec_call(pcpu_devices + cpu, ec_call_function_single); 545 + pcpu_ec_call(per_cpu_ptr(&pcpu_devices, cpu), ec_call_function_single); 526 546 } 527 547 528 548 void arch_send_call_function_single_ipi(int cpu) 529 549 { 530 - pcpu_ec_call(pcpu_devices + cpu, ec_call_function_single); 550 + pcpu_ec_call(per_cpu_ptr(&pcpu_devices, cpu), ec_call_function_single); 531 551 } 532 552 533 553 /* ··· 537 557 */ 538 558 void arch_smp_send_reschedule(int cpu) 539 559 { 540 - pcpu_ec_call(pcpu_devices + cpu, ec_schedule); 560 + pcpu_ec_call(per_cpu_ptr(&pcpu_devices, cpu), ec_schedule); 541 561 } 542 562 543 563 #ifdef CONFIG_IRQ_WORK 544 564 void arch_irq_work_raise(void) 545 565 { 546 - pcpu_ec_call(pcpu_devices + smp_processor_id(), ec_irq_work); 566 + pcpu_ec_call(this_cpu_ptr(&pcpu_devices), ec_irq_work); 547 567 } 548 568 #endif 549 569 ··· 555 575 struct pcpu *pcpu; 556 576 unsigned long pa; 557 577 558 - pcpu = pcpu_devices + cpu; 578 + pcpu = per_cpu_ptr(&pcpu_devices, cpu); 559 579 lc = lowcore_ptr[cpu]; 560 580 pa = __pa(&lc->floating_pt_save_area); 561 581 if (__pcpu_sigp_relax(pcpu->address, SIGP_STORE_STATUS_AT_ADDRESS, ··· 663 683 664 684 void smp_cpu_set_polarization(int cpu, int val) 665 685 { 666 - pcpu_devices[cpu].polarization = val; 686 + per_cpu(pcpu_devices, cpu).polarization = val; 667 687 } 668 688 669 689 int smp_cpu_get_polarization(int cpu) 670 690 { 671 - return pcpu_devices[cpu].polarization; 691 + return per_cpu(pcpu_devices, cpu).polarization; 672 692 } 673 693 674 694 int smp_cpu_get_cpu_address(int cpu) 675 695 { 676 - return pcpu_devices[cpu].address; 696 + return per_cpu(pcpu_devices, cpu).address; 677 697 } 678 698 679 699 static void __ref smp_get_core_info(struct sclp_core_info *info, int early) ··· 712 732 for (i = 0; (i <= smp_cpu_mtid) && (cpu < nr_cpu_ids); i++) { 713 733 if (pcpu_find_address(cpu_present_mask, address + i)) 714 734 continue; 715 - pcpu = pcpu_devices + cpu; 735 + pcpu = per_cpu_ptr(&pcpu_devices, cpu); 716 736 pcpu->address = address + i; 717 737 if (configured) 718 738 pcpu->state = CPU_STATE_CONFIGURED; ··· 747 767 * that all SMT threads get subsequent logical CPU numbers. 748 768 */ 749 769 if (early) { 750 - core_id = pcpu_devices[0].address >> smp_cpu_mt_shift; 770 + core_id = per_cpu(pcpu_devices, 0).address >> smp_cpu_mt_shift; 751 771 for (i = 0; i < info->configured; i++) { 752 772 core = &info->core[i]; 753 773 if (core->core_id == core_id) { ··· 847 867 /* Upping and downing of CPUs */ 848 868 int __cpu_up(unsigned int cpu, struct task_struct *tidle) 849 869 { 850 - struct pcpu *pcpu = pcpu_devices + cpu; 870 + struct pcpu *pcpu = per_cpu_ptr(&pcpu_devices, cpu); 851 871 int rc; 852 872 853 873 if (pcpu->state != CPU_STATE_CONFIGURED) ··· 865 885 */ 866 886 system_ctlreg_lock(); 867 887 pcpu_prepare_secondary(pcpu, cpu); 868 - pcpu_attach_task(pcpu, tidle); 869 - pcpu_start_fn(pcpu, smp_start_secondary, NULL); 888 + pcpu_attach_task(cpu, tidle); 889 + pcpu_start_fn(cpu, smp_start_secondary, NULL); 870 890 /* Wait until cpu puts itself in the online & active maps */ 871 891 while (!cpu_online(cpu)) 872 892 cpu_relax(); ··· 911 931 struct pcpu *pcpu; 912 932 913 933 /* Wait until target cpu is down */ 914 - pcpu = pcpu_devices + cpu; 934 + pcpu = per_cpu_ptr(&pcpu_devices, cpu); 915 935 while (!pcpu_stopped(pcpu)) 916 936 cpu_relax(); 917 - pcpu_free_lowcore(pcpu); 937 + pcpu_free_lowcore(pcpu, cpu); 918 938 cpumask_clear_cpu(cpu, mm_cpumask(&init_mm)); 919 939 cpumask_clear_cpu(cpu, &init_mm.context.cpu_attach_mask); 940 + pcpu->flags = 0; 920 941 } 921 942 922 943 void __noreturn cpu_die(void) 923 944 { 924 945 idle_task_exit(); 925 - pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0); 946 + pcpu_sigp_retry(this_cpu_ptr(&pcpu_devices), SIGP_STOP, 0); 926 947 for (;;) ; 927 948 } 928 949 ··· 953 972 954 973 void __init smp_prepare_boot_cpu(void) 955 974 { 956 - struct pcpu *pcpu = pcpu_devices; 975 + struct lowcore *lc = get_lowcore(); 957 976 958 977 WARN_ON(!cpu_present(0) || !cpu_online(0)); 959 - pcpu->state = CPU_STATE_CONFIGURED; 960 - get_lowcore()->percpu_offset = __per_cpu_offset[0]; 978 + lc->percpu_offset = __per_cpu_offset[0]; 979 + ipl_pcpu = per_cpu_ptr(&pcpu_devices, 0); 980 + ipl_pcpu->state = CPU_STATE_CONFIGURED; 981 + lc->pcpu = (unsigned long)ipl_pcpu; 961 982 smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); 962 983 } 963 984 ··· 967 984 { 968 985 struct lowcore *lc = get_lowcore(); 969 986 970 - pcpu_devices[0].address = stap(); 971 987 lc->cpu_nr = 0; 988 + per_cpu(pcpu_devices, 0).address = stap(); 972 989 lc->spinlock_lockval = arch_spin_lockval(0); 973 990 lc->spinlock_index = 0; 974 991 } ··· 990 1007 ssize_t count; 991 1008 992 1009 mutex_lock(&smp_cpu_state_mutex); 993 - count = sprintf(buf, "%d\n", pcpu_devices[dev->id].state); 1010 + count = sprintf(buf, "%d\n", per_cpu(pcpu_devices, dev->id).state); 994 1011 mutex_unlock(&smp_cpu_state_mutex); 995 1012 return count; 996 1013 } ··· 1016 1033 for (i = 0; i <= smp_cpu_mtid; i++) 1017 1034 if (cpu_online(cpu + i)) 1018 1035 goto out; 1019 - pcpu = pcpu_devices + cpu; 1036 + pcpu = per_cpu_ptr(&pcpu_devices, cpu); 1020 1037 rc = 0; 1021 1038 switch (val) { 1022 1039 case 0: ··· 1028 1045 for (i = 0; i <= smp_cpu_mtid; i++) { 1029 1046 if (cpu + i >= nr_cpu_ids || !cpu_present(cpu + i)) 1030 1047 continue; 1031 - pcpu[i].state = CPU_STATE_STANDBY; 1048 + per_cpu(pcpu_devices, cpu + i).state = CPU_STATE_STANDBY; 1032 1049 smp_cpu_set_polarization(cpu + i, 1033 1050 POLARIZATION_UNKNOWN); 1034 1051 } ··· 1043 1060 for (i = 0; i <= smp_cpu_mtid; i++) { 1044 1061 if (cpu + i >= nr_cpu_ids || !cpu_present(cpu + i)) 1045 1062 continue; 1046 - pcpu[i].state = CPU_STATE_CONFIGURED; 1063 + per_cpu(pcpu_devices, cpu + i).state = CPU_STATE_CONFIGURED; 1047 1064 smp_cpu_set_polarization(cpu + i, 1048 1065 POLARIZATION_UNKNOWN); 1049 1066 } ··· 1062 1079 static ssize_t show_cpu_address(struct device *dev, 1063 1080 struct device_attribute *attr, char *buf) 1064 1081 { 1065 - return sprintf(buf, "%d\n", pcpu_devices[dev->id].address); 1082 + return sprintf(buf, "%d\n", per_cpu(pcpu_devices, dev->id).address); 1066 1083 } 1067 1084 static DEVICE_ATTR(address, 0444, show_cpu_address, NULL); 1068 1085 ··· 1088 1105 1089 1106 static int smp_cpu_online(unsigned int cpu) 1090 1107 { 1091 - struct cpu *c = &per_cpu(cpu_devices, cpu); 1108 + struct cpu *c = per_cpu_ptr(&cpu_devices, cpu); 1092 1109 1093 1110 return sysfs_create_group(&c->dev.kobj, &cpu_online_attr_group); 1094 1111 } 1095 1112 1096 1113 static int smp_cpu_pre_down(unsigned int cpu) 1097 1114 { 1098 - struct cpu *c = &per_cpu(cpu_devices, cpu); 1115 + struct cpu *c = per_cpu_ptr(&cpu_devices, cpu); 1099 1116 1100 1117 sysfs_remove_group(&c->dev.kobj, &cpu_online_attr_group); 1101 1118 return 0; ··· 1108 1125 1109 1126 int arch_register_cpu(int cpu) 1110 1127 { 1111 - struct cpu *c = &per_cpu(cpu_devices, cpu); 1128 + struct cpu *c = per_cpu_ptr(&cpu_devices, cpu); 1112 1129 int rc; 1113 1130 1114 1131 c->hotpluggable = arch_cpu_is_hotpluggable(cpu);
+15 -20
arch/s390/kernel/uv.c
··· 18 18 #include <asm/sections.h> 19 19 #include <asm/uv.h> 20 20 21 + #if !IS_ENABLED(CONFIG_KVM) 22 + unsigned long __gmap_translate(struct gmap *gmap, unsigned long gaddr) 23 + { 24 + return 0; 25 + } 26 + 27 + int gmap_fault(struct gmap *gmap, unsigned long gaddr, 28 + unsigned int fault_flags) 29 + { 30 + return 0; 31 + } 32 + #endif 33 + 21 34 /* the bootdata_preserved fields come from ones in arch/s390/boot/uv.c */ 22 - #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST 23 35 int __bootdata_preserved(prot_virt_guest); 24 36 EXPORT_SYMBOL(prot_virt_guest); 25 - #endif 26 37 27 38 /* 28 39 * uv_info contains both host and guest information but it's currently only ··· 46 35 struct uv_info __bootdata_preserved(uv_info); 47 36 EXPORT_SYMBOL(uv_info); 48 37 49 - #if IS_ENABLED(CONFIG_KVM) 50 38 int __bootdata_preserved(prot_virt_host); 51 39 EXPORT_SYMBOL(prot_virt_host); 52 40 ··· 553 543 return arch_make_folio_accessible(page_folio(page)); 554 544 } 555 545 EXPORT_SYMBOL_GPL(arch_make_page_accessible); 556 - #endif 557 - 558 - #if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM) 559 546 static ssize_t uv_query_facilities(struct kobject *kobj, 560 547 struct kobj_attribute *attr, char *buf) 561 548 { ··· 728 721 static ssize_t uv_is_prot_virt_guest(struct kobject *kobj, 729 722 struct kobj_attribute *attr, char *buf) 730 723 { 731 - int val = 0; 732 - 733 - #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST 734 - val = prot_virt_guest; 735 - #endif 736 - return sysfs_emit(buf, "%d\n", val); 724 + return sysfs_emit(buf, "%d\n", prot_virt_guest); 737 725 } 738 726 739 727 static ssize_t uv_is_prot_virt_host(struct kobject *kobj, 740 728 struct kobj_attribute *attr, char *buf) 741 729 { 742 - int val = 0; 743 - 744 - #if IS_ENABLED(CONFIG_KVM) 745 - val = prot_virt_host; 746 - #endif 747 - 748 - return sysfs_emit(buf, "%d\n", val); 730 + return sysfs_emit(buf, "%d\n", prot_virt_host); 749 731 } 750 732 751 733 static struct kobj_attribute uv_prot_virt_guest = ··· 786 790 return rc; 787 791 } 788 792 device_initcall(uv_info_init); 789 - #endif
+5
arch/s390/kernel/vmlinux.lds.S
··· 190 190 . = ALIGN(PAGE_SIZE); 191 191 INIT_DATA_SECTION(0x100) 192 192 193 + RUNTIME_CONST(shift, d_hash_shift) 194 + RUNTIME_CONST(ptr, dentry_hashtable) 195 + 193 196 PERCPU_SECTION(0x100) 194 197 195 198 . = ALIGN(PAGE_SIZE); ··· 222 219 QUAD(init_mm) 223 220 QUAD(swapper_pg_dir) 224 221 QUAD(invalid_pg_dir) 222 + QUAD(__alt_instructions) 223 + QUAD(__alt_instructions_end) 225 224 #ifdef CONFIG_KASAN 226 225 QUAD(kasan_early_shadow_page) 227 226 QUAD(kasan_early_shadow_pte)
+2 -2
arch/s390/lib/spinlock.c
··· 75 75 int owner; 76 76 77 77 asm_inline volatile( 78 - ALTERNATIVE("nop", ".insn rre,0xb2fa0000,4,0", 49) /* NIAI 4 */ 78 + ALTERNATIVE("nop", ".insn rre,0xb2fa0000,4,0", ALT_FACILITY(49)) /* NIAI 4 */ 79 79 " l %0,%1\n" 80 80 : "=d" (owner) : "Q" (*lock) : "memory"); 81 81 return owner; ··· 86 86 int expected = old; 87 87 88 88 asm_inline volatile( 89 - ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", 49) /* NIAI 8 */ 89 + ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */ 90 90 " cs %0,%3,%1\n" 91 91 : "=d" (old), "=Q" (*lock) 92 92 : "0" (old), "d" (new), "Q" (*lock)
+30
arch/s390/mm/dump_pagetables.c
··· 36 36 VMEMMAP_END_NR, 37 37 VMALLOC_NR, 38 38 VMALLOC_END_NR, 39 + #ifdef CONFIG_KMSAN 40 + KMSAN_VMALLOC_SHADOW_START_NR, 41 + KMSAN_VMALLOC_SHADOW_END_NR, 42 + KMSAN_VMALLOC_ORIGIN_START_NR, 43 + KMSAN_VMALLOC_ORIGIN_END_NR, 44 + KMSAN_MODULES_SHADOW_START_NR, 45 + KMSAN_MODULES_SHADOW_END_NR, 46 + KMSAN_MODULES_ORIGIN_START_NR, 47 + KMSAN_MODULES_ORIGIN_END_NR, 48 + #endif 39 49 MODULES_NR, 40 50 MODULES_END_NR, 41 51 ABS_LOWCORE_NR, ··· 75 65 [VMEMMAP_END_NR] = {0, "vmemmap Area End"}, 76 66 [VMALLOC_NR] = {0, "vmalloc Area Start"}, 77 67 [VMALLOC_END_NR] = {0, "vmalloc Area End"}, 68 + #ifdef CONFIG_KMSAN 69 + [KMSAN_VMALLOC_SHADOW_START_NR] = {0, "Kmsan vmalloc Shadow Start"}, 70 + [KMSAN_VMALLOC_SHADOW_END_NR] = {0, "Kmsan vmalloc Shadow End"}, 71 + [KMSAN_VMALLOC_ORIGIN_START_NR] = {0, "Kmsan vmalloc Origins Start"}, 72 + [KMSAN_VMALLOC_ORIGIN_END_NR] = {0, "Kmsan vmalloc Origins End"}, 73 + [KMSAN_MODULES_SHADOW_START_NR] = {0, "Kmsan Modules Shadow Start"}, 74 + [KMSAN_MODULES_SHADOW_END_NR] = {0, "Kmsan Modules Shadow End"}, 75 + [KMSAN_MODULES_ORIGIN_START_NR] = {0, "Kmsan Modules Origins Start"}, 76 + [KMSAN_MODULES_ORIGIN_END_NR] = {0, "Kmsan Modules Origins End"}, 77 + #endif 78 78 [MODULES_NR] = {0, "Modules Area Start"}, 79 79 [MODULES_END_NR] = {0, "Modules Area End"}, 80 80 [ABS_LOWCORE_NR] = {0, "Lowcore Area Start"}, ··· 326 306 #ifdef CONFIG_KFENCE 327 307 address_markers[KFENCE_START_NR].start_address = kfence_start; 328 308 address_markers[KFENCE_END_NR].start_address = kfence_start + KFENCE_POOL_SIZE; 309 + #endif 310 + #ifdef CONFIG_KMSAN 311 + address_markers[KMSAN_VMALLOC_SHADOW_START_NR].start_address = KMSAN_VMALLOC_SHADOW_START; 312 + address_markers[KMSAN_VMALLOC_SHADOW_END_NR].start_address = KMSAN_VMALLOC_SHADOW_END; 313 + address_markers[KMSAN_VMALLOC_ORIGIN_START_NR].start_address = KMSAN_VMALLOC_ORIGIN_START; 314 + address_markers[KMSAN_VMALLOC_ORIGIN_END_NR].start_address = KMSAN_VMALLOC_ORIGIN_END; 315 + address_markers[KMSAN_MODULES_SHADOW_START_NR].start_address = KMSAN_MODULES_SHADOW_START; 316 + address_markers[KMSAN_MODULES_SHADOW_END_NR].start_address = KMSAN_MODULES_SHADOW_END; 317 + address_markers[KMSAN_MODULES_ORIGIN_START_NR].start_address = KMSAN_MODULES_ORIGIN_START; 318 + address_markers[KMSAN_MODULES_ORIGIN_END_NR].start_address = KMSAN_MODULES_ORIGIN_END; 329 319 #endif 330 320 sort_address_markers(); 331 321 #ifdef CONFIG_PTDUMP_DEBUGFS
+2 -2
arch/s390/mm/maccess.c
··· 48 48 } 49 49 50 50 /* 51 - * s390_kernel_write - write to kernel memory bypassing DAT 51 + * __s390_kernel_write - write to kernel memory bypassing DAT 52 52 * @dst: destination address 53 53 * @src: source address 54 54 * @size: number of bytes to copy ··· 61 61 */ 62 62 static DEFINE_SPINLOCK(s390_kernel_write_lock); 63 63 64 - notrace void *s390_kernel_write(void *dst, const void *src, size_t size) 64 + notrace void *__s390_kernel_write(void *dst, const void *src, size_t size) 65 65 { 66 66 void *tmp = dst; 67 67 unsigned long flags;
+71 -39
arch/s390/pci/pci_irq.c
··· 268 268 } 269 269 } 270 270 271 - int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 271 + static int __alloc_airq(struct zpci_dev *zdev, int msi_vecs, 272 + unsigned long *bit) 272 273 { 273 - struct zpci_dev *zdev = to_zpci(pdev); 274 - unsigned int hwirq, msi_vecs, cpu; 275 - unsigned long bit; 276 - struct msi_desc *msi; 277 - struct msi_msg msg; 278 - int cpu_addr; 279 - int rc, irq; 280 - 281 - zdev->aisb = -1UL; 282 - zdev->msi_first_bit = -1U; 283 - if (type == PCI_CAP_ID_MSI && nvec > 1) 284 - return 1; 285 - msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); 286 - 287 274 if (irq_delivery == DIRECTED) { 288 275 /* Allocate cpu vector bits */ 289 - bit = airq_iv_alloc(zpci_ibv[0], msi_vecs); 290 - if (bit == -1UL) 276 + *bit = airq_iv_alloc(zpci_ibv[0], msi_vecs); 277 + if (*bit == -1UL) 291 278 return -EIO; 292 279 } else { 293 280 /* Allocate adapter summary indicator bit */ 294 - bit = airq_iv_alloc_bit(zpci_sbv); 295 - if (bit == -1UL) 281 + *bit = airq_iv_alloc_bit(zpci_sbv); 282 + if (*bit == -1UL) 296 283 return -EIO; 297 - zdev->aisb = bit; 284 + zdev->aisb = *bit; 298 285 299 286 /* Create adapter interrupt vector */ 300 287 zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK, NULL); ··· 289 302 return -ENOMEM; 290 303 291 304 /* Wire up shortcut pointer */ 292 - zpci_ibv[bit] = zdev->aibv; 305 + zpci_ibv[*bit] = zdev->aibv; 293 306 /* Each function has its own interrupt vector */ 294 - bit = 0; 307 + *bit = 0; 308 + } 309 + return 0; 310 + } 311 + 312 + int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 313 + { 314 + unsigned int hwirq, msi_vecs, irqs_per_msi, i, cpu; 315 + struct zpci_dev *zdev = to_zpci(pdev); 316 + struct msi_desc *msi; 317 + struct msi_msg msg; 318 + unsigned long bit; 319 + int cpu_addr; 320 + int rc, irq; 321 + 322 + zdev->aisb = -1UL; 323 + zdev->msi_first_bit = -1U; 324 + 325 + msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); 326 + if (msi_vecs < nvec) { 327 + pr_info("%s requested %d irqs, allocate system limit of %d", 328 + pci_name(pdev), nvec, zdev->max_msi); 295 329 } 296 330 297 - /* Request MSI interrupts */ 331 + rc = __alloc_airq(zdev, msi_vecs, &bit); 332 + if (rc < 0) 333 + return rc; 334 + 335 + /* 336 + * Request MSI interrupts: 337 + * When using MSI, nvec_used interrupt sources and their irq 338 + * descriptors are controlled through one msi descriptor. 339 + * Thus the outer loop over msi descriptors shall run only once, 340 + * while two inner loops iterate over the interrupt vectors. 341 + * When using MSI-X, each interrupt vector/irq descriptor 342 + * is bound to exactly one msi descriptor (nvec_used is one). 343 + * So the inner loops are executed once, while the outer iterates 344 + * over the MSI-X descriptors. 345 + */ 298 346 hwirq = bit; 299 347 msi_for_each_desc(msi, &pdev->dev, MSI_DESC_NOTASSOCIATED) { 300 - rc = -EIO; 301 348 if (hwirq - bit >= msi_vecs) 302 349 break; 303 - irq = __irq_alloc_descs(-1, 0, 1, 0, THIS_MODULE, 304 - (irq_delivery == DIRECTED) ? 305 - msi->affinity : NULL); 350 + irqs_per_msi = min_t(unsigned int, msi_vecs, msi->nvec_used); 351 + irq = __irq_alloc_descs(-1, 0, irqs_per_msi, 0, THIS_MODULE, 352 + (irq_delivery == DIRECTED) ? 353 + msi->affinity : NULL); 306 354 if (irq < 0) 307 355 return -ENOMEM; 308 - rc = irq_set_msi_desc(irq, msi); 309 - if (rc) 310 - return rc; 311 - irq_set_chip_and_handler(irq, &zpci_irq_chip, 312 - handle_percpu_irq); 356 + 357 + for (i = 0; i < irqs_per_msi; i++) { 358 + rc = irq_set_msi_desc_off(irq, i, msi); 359 + if (rc) 360 + return rc; 361 + irq_set_chip_and_handler(irq + i, &zpci_irq_chip, 362 + handle_percpu_irq); 363 + } 364 + 313 365 msg.data = hwirq - bit; 314 366 if (irq_delivery == DIRECTED) { 315 367 if (msi->affinity) ··· 361 335 msg.address_lo |= (cpu_addr << 8); 362 336 363 337 for_each_possible_cpu(cpu) { 364 - airq_iv_set_data(zpci_ibv[cpu], hwirq, irq); 338 + for (i = 0; i < irqs_per_msi; i++) 339 + airq_iv_set_data(zpci_ibv[cpu], 340 + hwirq + i, irq + i); 365 341 } 366 342 } else { 367 343 msg.address_lo = zdev->msi_addr & 0xffffffff; 368 - airq_iv_set_data(zdev->aibv, hwirq, irq); 344 + for (i = 0; i < irqs_per_msi; i++) 345 + airq_iv_set_data(zdev->aibv, hwirq + i, irq + i); 369 346 } 370 347 msg.address_hi = zdev->msi_addr >> 32; 371 348 pci_write_msi_msg(irq, &msg); 372 - hwirq++; 349 + hwirq += irqs_per_msi; 373 350 } 374 351 375 352 zdev->msi_first_bit = bit; 376 - zdev->msi_nr_irqs = msi_vecs; 353 + zdev->msi_nr_irqs = hwirq - bit; 377 354 378 355 rc = zpci_set_irq(zdev); 379 356 if (rc) 380 357 return rc; 381 358 382 - return (msi_vecs == nvec) ? 0 : msi_vecs; 359 + return (zdev->msi_nr_irqs == nvec) ? 0 : zdev->msi_nr_irqs; 383 360 } 384 361 385 362 void arch_teardown_msi_irqs(struct pci_dev *pdev) 386 363 { 387 364 struct zpci_dev *zdev = to_zpci(pdev); 388 365 struct msi_desc *msi; 366 + unsigned int i; 389 367 int rc; 390 368 391 369 /* Disable interrupts */ ··· 399 369 400 370 /* Release MSI interrupts */ 401 371 msi_for_each_desc(msi, &pdev->dev, MSI_DESC_ASSOCIATED) { 402 - irq_set_msi_desc(msi->irq, NULL); 403 - irq_free_desc(msi->irq); 372 + for (i = 0; i < msi->nvec_used; i++) { 373 + irq_set_msi_desc(msi->irq + i, NULL); 374 + irq_free_desc(msi->irq + i); 375 + } 404 376 msi->msg.address_lo = 0; 405 377 msi->msg.address_hi = 0; 406 378 msi->msg.data = 0;
+1 -1
drivers/s390/char/Kconfig
··· 96 96 config S390_UV_UAPI 97 97 def_tristate m 98 98 prompt "Ultravisor userspace API" 99 - depends on S390 && (KVM || PROTECTED_VIRTUALIZATION_GUEST) 99 + depends on S390 100 100 help 101 101 Selecting exposes parts of the UV interface to userspace 102 102 by providing a misc character device at /dev/uv.