Skip to content

Commit f90f214

Browse files
committed
Merge tag 's390-6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Vasily Gorbik: - Add sorting of mcount locations at build time - Rework uaccess functions with C exception handling to shorten inline assembly size and enable full inlining. This yields near-optimal code for small constant copies with a ~40kb kernel size increase - Add support for a configurable STRICT_MM_TYPECHECKS which allows to generate better code, but also allows to have type checking for debug builds - Optimize get_lowcore() for common callers with alternatives that nearly revert to the pre-relocated lowcore code, while also slightly reducing syscall entry and exit time - Convert MACHINE_HAS_* checks for single facility tests into cpu_has_* style macros that call test_facility(), and for features with additional conditions, add a new ALT_TYPE_FEATURE alternative to provide a static branch via alternative patching. Also, move machine feature detection to the decompressor for early patching and add debugging functionality to easily show which alternatives are patched - Add exception table support to early boot / startup code to get rid of the open coded exception handling - Use asm_inline for all inline assemblies with EX_TABLE or ALTERNATIVE to ensure correct inlining and unrolling decisions - Remove 2k page table leftovers now that s390 has been switched to always allocate 4k page tables - Split kfence pool into 4k mappings in arch_kfence_init_pool() and remove the architecture-specific kfence_split_mapping() - Use READ_ONCE_NOCHECK() in regs_get_kernel_stack_nth() to silence spurious KASAN warnings from opportunistic ftrace argument tracing - Force __atomic_add_const() variants on s390 to always return void, ensuring compile errors for improper usage - Remove s390's ioremap_wt() and pgprot_writethrough() due to mismatched semantics and lack of known users, relying on asm-generic fallbacks - Signal eventfd in vfio-ap to notify userspace when the guest AP configuration changes, including during mdev removal - Convert mdev_types from an array to a pointer in vfio-ccw and vfio-ap drivers to avoid fake flex array confusion - Cleanup trap code - Remove references to the outdated [email protected] address - Other various small fixes and improvements all over the code * tag 's390-6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (78 commits) s390: Use inline qualifier for all EX_TABLE and ALTERNATIVE inline assemblies s390/kfence: Split kfence pool into 4k mappings in arch_kfence_init_pool() s390/ptrace: Avoid KASAN false positives in regs_get_kernel_stack_nth() s390/boot: Ignore vmlinux.map s390/sysctl: Remove "vm/allocate_pgste" sysctl s390: Remove 2k vs 4k page table leftovers s390/tlb: Use mm_has_pgste() instead of mm_alloc_pgste() s390/lowcore: Use lghi instead llilh to clear register s390/syscall: Merge __do_syscall() and do_syscall() s390/spinlock: Implement SPINLOCK_LOCKVAL with inline assembly s390/smp: Implement raw_smp_processor_id() with inline assembly s390/current: Implement current with inline assembly s390/lowcore: Use inline qualifier for get_lowcore() inline assembly s390: Move s390 sysctls into their own file under arch/s390 s390/syscall: Simplify syscall_get_arguments() s390/vfio-ap: Notify userspace that guest's AP config changed when mdev removed s390: Remove ioremap_wt() and pgprot_writethrough() s390/mm: Add configurable STRICT_MM_TYPECHECKS s390/mm: Convert pgste_val() into function s390/mm: Convert pgprot_val() into function ...
2 parents 1fa753c + 0dafe99 commit f90f214

File tree

141 files changed

+1442
-1092
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+1442
-1092
lines changed

arch/s390/Kconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ config S390
7070
imply IMA_SECURE_AND_OR_TRUSTED_BOOT
7171
select ALTERNATE_USER_ADDRESS_SPACE
7272
select ARCH_32BIT_USTAT_F_TINODE
73-
select ARCH_BINFMT_ELF_STATE
7473
select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
7574
select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM
7675
select ARCH_ENABLE_MEMORY_HOTREMOVE
@@ -183,6 +182,7 @@ config S390
183182
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
184183
select HAVE_ARCH_VMAP_STACK
185184
select HAVE_ASM_MODVERSIONS
185+
select HAVE_BUILDTIME_MCOUNT_SORT
186186
select HAVE_CMPXCHG_DOUBLE
187187
select HAVE_CMPXCHG_LOCAL
188188
select HAVE_DEBUG_KMEMLEAK

arch/s390/Kconfig.debug

+10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ config DEBUG_ENTRY
1313

1414
If unsure, say N.
1515

16+
config STRICT_MM_TYPECHECKS
17+
bool "Strict Memory Management Type Checks"
18+
depends on DEBUG_KERNEL
19+
help
20+
Enable strict type checking for memory management types like pte_t
21+
and pmd_t. This generates slightly worse code and should be used
22+
for debug builds.
23+
24+
If unsure, say N.
25+
1626
config CIO_INJECT
1727
bool "CIO Inject interfaces"
1828
depends on DEBUG_KERNEL && DEBUG_FS

arch/s390/boot/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ relocs.S
55
section_cmp.*
66
vmlinux
77
vmlinux.lds
8+
vmlinux.map
89
vmlinux.syms

arch/s390/boot/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
2626

2727
obj-y := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o
2828
obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
29-
obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o alternative.o
29+
obj-y += version.o pgm_check.o ctype.o ipl_data.o relocs.o alternative.o
3030
obj-y += uv.o printk.o
3131
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
3232
obj-y += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o

arch/s390/boot/alternative.c

+135
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,138 @@
11
// SPDX-License-Identifier: GPL-2.0
2+
#define boot_fmt(fmt) "alt: " fmt
3+
#include "boot.h"
4+
5+
#define a_debug boot_debug
26

37
#include "../kernel/alternative.c"
8+
9+
static void alt_debug_all(int type)
10+
{
11+
int i;
12+
13+
switch (type) {
14+
case ALT_TYPE_FACILITY:
15+
for (i = 0; i < ARRAY_SIZE(alt_debug.facilities); i++)
16+
alt_debug.facilities[i] = -1UL;
17+
break;
18+
case ALT_TYPE_FEATURE:
19+
for (i = 0; i < ARRAY_SIZE(alt_debug.mfeatures); i++)
20+
alt_debug.mfeatures[i] = -1UL;
21+
break;
22+
case ALT_TYPE_SPEC:
23+
alt_debug.spec = 1;
24+
break;
25+
}
26+
}
27+
28+
static void alt_debug_modify(int type, unsigned int nr, bool clear)
29+
{
30+
switch (type) {
31+
case ALT_TYPE_FACILITY:
32+
if (clear)
33+
__clear_facility(nr, alt_debug.facilities);
34+
else
35+
__set_facility(nr, alt_debug.facilities);
36+
break;
37+
case ALT_TYPE_FEATURE:
38+
if (clear)
39+
__clear_machine_feature(nr, alt_debug.mfeatures);
40+
else
41+
__set_machine_feature(nr, alt_debug.mfeatures);
42+
break;
43+
}
44+
}
45+
46+
static char *alt_debug_parse(int type, char *str)
47+
{
48+
unsigned long val, endval;
49+
char *endp;
50+
bool clear;
51+
int i;
52+
53+
if (*str == ':') {
54+
str++;
55+
} else {
56+
alt_debug_all(type);
57+
return str;
58+
}
59+
clear = false;
60+
if (*str == '!') {
61+
alt_debug_all(type);
62+
clear = true;
63+
str++;
64+
}
65+
while (*str) {
66+
val = simple_strtoull(str, &endp, 0);
67+
if (str == endp)
68+
break;
69+
str = endp;
70+
if (*str == '-') {
71+
str++;
72+
endval = simple_strtoull(str, &endp, 0);
73+
if (str == endp)
74+
break;
75+
str = endp;
76+
while (val <= endval) {
77+
alt_debug_modify(type, val, clear);
78+
val++;
79+
}
80+
} else {
81+
alt_debug_modify(type, val, clear);
82+
}
83+
if (*str != ',')
84+
break;
85+
str++;
86+
}
87+
return str;
88+
}
89+
90+
/*
91+
* Use debug-alternative command line parameter for debugging:
92+
* "debug-alternative"
93+
* -> print debug message for every single alternative
94+
*
95+
* "debug-alternative=0;2"
96+
* -> print debug message for all alternatives with type 0 and 2
97+
*
98+
* "debug-alternative=0:0-7"
99+
* -> print debug message for all alternatives with type 0 and with
100+
* facility numbers within the range of 0-7
101+
* (if type 0 is ALT_TYPE_FACILITY)
102+
*
103+
* "debug-alternative=0:!8;1"
104+
* -> print debug message for all alternatives with type 0, for all
105+
* facility number, except facility 8, and in addition print all
106+
* alternatives with type 1
107+
*/
108+
void alt_debug_setup(char *str)
109+
{
110+
unsigned long type;
111+
char *endp;
112+
int i;
113+
114+
if (!str) {
115+
alt_debug_all(ALT_TYPE_FACILITY);
116+
alt_debug_all(ALT_TYPE_FEATURE);
117+
alt_debug_all(ALT_TYPE_SPEC);
118+
return;
119+
}
120+
while (*str) {
121+
type = simple_strtoull(str, &endp, 0);
122+
if (str == endp)
123+
break;
124+
str = endp;
125+
switch (type) {
126+
case ALT_TYPE_FACILITY:
127+
case ALT_TYPE_FEATURE:
128+
str = alt_debug_parse(type, str);
129+
break;
130+
case ALT_TYPE_SPEC:
131+
alt_debug_all(ALT_TYPE_SPEC);
132+
break;
133+
}
134+
if (*str != ';')
135+
break;
136+
str++;
137+
}
138+
}

arch/s390/boot/boot.h

+2-6
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@
1111
#include <linux/printk.h>
1212
#include <asm/physmem_info.h>
1313

14-
struct machine_info {
15-
unsigned char has_edat1 : 1;
16-
unsigned char has_edat2 : 1;
17-
};
18-
1914
struct vmlinux_info {
2015
unsigned long entry;
2116
unsigned long image_size; /* does not include .bss */
@@ -69,7 +64,8 @@ void parse_boot_command_line(void);
6964
void verify_facilities(void);
7065
void print_missing_facilities(void);
7166
void sclp_early_setup_buffer(void);
72-
void print_pgm_check_info(void);
67+
void alt_debug_setup(char *str);
68+
void do_pgm_check(struct pt_regs *regs);
7369
unsigned long randomize_within_range(unsigned long size, unsigned long align,
7470
unsigned long min, unsigned long max);
7571
void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned long asce_limit);

arch/s390/boot/head.S

+15-10
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,9 @@ SYM_CODE_START_LOCAL(startup_normal)
254254
xc 0xf00(256),0xf00
255255
larl %r13,.Lctl
256256
lctlg %c0,%c15,0(%r13) # load control registers
257-
stcke __LC_BOOT_CLOCK
258-
mvc __LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1
257+
larl %r13,tod_clock_base
258+
stcke 0(%r13)
259+
mvc __LC_LAST_UPDATE_CLOCK(8),1(%r13)
259260
larl %r13,6f
260261
spt 0(%r13)
261262
mvc __LC_LAST_UPDATE_TIMER(8),0(%r13)
@@ -292,12 +293,6 @@ SYM_CODE_END(startup_normal)
292293

293294
#include "head_kdump.S"
294295

295-
#
296-
# This program check is active immediately after kernel start
297-
# and until early_pgm_check_handler is set in kernel/early.c
298-
# It simply saves general/control registers and psw in
299-
# the save area and does disabled wait with a faulty address.
300-
#
301296
SYM_CODE_START_LOCAL(startup_pgm_check_handler)
302297
stmg %r8,%r15,__LC_SAVE_AREA
303298
la %r8,4095
@@ -311,8 +306,18 @@ SYM_CODE_START_LOCAL(startup_pgm_check_handler)
311306
oi __LC_RETURN_PSW+1,0x2 # set wait state bit
312307
larl %r9,.Lold_psw_disabled_wait
313308
stg %r9,__LC_PGM_NEW_PSW+8
314-
larl %r15,_dump_info_stack_end-STACK_FRAME_OVERHEAD
315-
brasl %r14,print_pgm_check_info
309+
larl %r15,_dump_info_stack_end-(STACK_FRAME_OVERHEAD+__PT_SIZE)
310+
la %r2,STACK_FRAME_OVERHEAD(%r15)
311+
mvc __PT_PSW(16,%r2),__LC_PSW_SAVE_AREA-4095(%r8)
312+
mvc __PT_R0(128,%r2),__LC_GPREGS_SAVE_AREA-4095(%r8)
313+
mvc __PT_LAST_BREAK(8,%r2),__LC_PGM_LAST_BREAK
314+
mvc __PT_INT_CODE(4,%r2),__LC_PGM_INT_CODE
315+
brasl %r14,do_pgm_check
316+
larl %r9,startup_pgm_check_handler
317+
stg %r9,__LC_PGM_NEW_PSW+8
318+
mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
319+
lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
320+
lpswe __LC_RETURN_PSW
316321
.Lold_psw_disabled_wait:
317322
la %r8,4095
318323
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r8)

arch/s390/boot/ipl_parm.c

+12-23
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/pgtable.h>
66
#include <asm/abs_lowcore.h>
77
#include <asm/page-states.h>
8+
#include <asm/machine.h>
89
#include <asm/ebcdic.h>
910
#include <asm/sclp.h>
1011
#include <asm/sections.h>
@@ -34,29 +35,14 @@ int vmalloc_size_set;
3435

3536
static inline int __diag308(unsigned long subcode, void *addr)
3637
{
37-
unsigned long reg1, reg2;
38-
union register_pair r1;
39-
psw_t old;
40-
41-
r1.even = (unsigned long) addr;
42-
r1.odd = 0;
43-
asm volatile(
44-
" mvc 0(16,%[psw_old]),0(%[psw_pgm])\n"
45-
" epsw %[reg1],%[reg2]\n"
46-
" st %[reg1],0(%[psw_pgm])\n"
47-
" st %[reg2],4(%[psw_pgm])\n"
48-
" larl %[reg1],1f\n"
49-
" stg %[reg1],8(%[psw_pgm])\n"
38+
union register_pair r1 = { .even = (unsigned long)addr, .odd = 0 };
39+
40+
asm_inline volatile(
5041
" diag %[r1],%[subcode],0x308\n"
51-
"1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n"
52-
: [r1] "+&d" (r1.pair),
53-
[reg1] "=&d" (reg1),
54-
[reg2] "=&a" (reg2),
55-
"+Q" (get_lowcore()->program_new_psw),
56-
"=Q" (old)
57-
: [subcode] "d" (subcode),
58-
[psw_old] "a" (&old),
59-
[psw_pgm] "a" (&get_lowcore()->program_new_psw)
42+
"0:\n"
43+
EX_TABLE(0b, 0b)
44+
: [r1] "+d" (r1.pair)
45+
: [subcode] "d" (subcode)
6046
: "cc", "memory");
6147
return r1.odd;
6248
}
@@ -295,6 +281,9 @@ void parse_boot_command_line(void)
295281
if (!strcmp(param, "facilities") && val)
296282
modify_fac_list(val);
297283

284+
if (!strcmp(param, "debug-alternative"))
285+
alt_debug_setup(val);
286+
298287
if (!strcmp(param, "nokaslr"))
299288
__kaslr_enabled = 0;
300289

@@ -312,7 +301,7 @@ void parse_boot_command_line(void)
312301
}
313302
#endif
314303
if (!strcmp(param, "relocate_lowcore") && test_facility(193))
315-
relocate_lowcore = 1;
304+
set_machine_feature(MFEATURE_LOWCORE);
316305
if (!strcmp(param, "earlyprintk"))
317306
boot_earlyprintk = true;
318307
if (!strcmp(param, "debug"))

arch/s390/boot/pgm_check_info.c arch/s390/boot/pgm_check.c

+36-10
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,61 @@ void print_stacktrace(unsigned long sp)
3232
}
3333
}
3434

35-
void print_pgm_check_info(void)
35+
extern struct exception_table_entry __start___ex_table[];
36+
extern struct exception_table_entry __stop___ex_table[];
37+
38+
static inline unsigned long extable_insn(const struct exception_table_entry *x)
39+
{
40+
return (unsigned long)&x->insn + x->insn;
41+
}
42+
43+
static bool ex_handler(struct pt_regs *regs)
44+
{
45+
const struct exception_table_entry *ex;
46+
47+
for (ex = __start___ex_table; ex < __stop___ex_table; ex++) {
48+
if (extable_insn(ex) != regs->psw.addr)
49+
continue;
50+
if (ex->type != EX_TYPE_FIXUP)
51+
return false;
52+
regs->psw.addr = extable_fixup(ex);
53+
return true;
54+
}
55+
return false;
56+
}
57+
58+
void do_pgm_check(struct pt_regs *regs)
3659
{
37-
unsigned long *gpregs = (unsigned long *)get_lowcore()->gpregs_save_area;
38-
struct psw_bits *psw = &psw_bits(get_lowcore()->psw_save_area);
60+
struct psw_bits *psw = &psw_bits(regs->psw);
61+
unsigned long *gpregs = regs->gprs;
3962

63+
if (ex_handler(regs))
64+
return;
4065
if (bootdebug)
4166
boot_rb_dump();
4267
boot_emerg("Linux version %s\n", kernel_version);
4368
if (!is_prot_virt_guest() && early_command_line[0])
4469
boot_emerg("Kernel command line: %s\n", early_command_line);
4570
boot_emerg("Kernel fault: interruption code %04x ilc:%d\n",
46-
get_lowcore()->pgm_code, get_lowcore()->pgm_ilc >> 1);
71+
regs->int_code & 0xffff, regs->int_code >> 17);
4772
if (kaslr_enabled()) {
4873
boot_emerg("Kernel random base: %lx\n", __kaslr_offset);
4974
boot_emerg("Kernel random base phys: %lx\n", __kaslr_offset_phys);
5075
}
5176
boot_emerg("PSW : %016lx %016lx (%pS)\n",
52-
get_lowcore()->psw_save_area.mask,
53-
get_lowcore()->psw_save_area.addr,
54-
(void *)get_lowcore()->psw_save_area.addr);
77+
regs->psw.mask, regs->psw.addr, (void *)regs->psw.addr);
5578
boot_emerg(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n",
5679
psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck,
5780
psw->wait, psw->pstate, psw->as, psw->cc, psw->pm, psw->ri, psw->eaba);
5881
boot_emerg("GPRS: %016lx %016lx %016lx %016lx\n", gpregs[0], gpregs[1], gpregs[2], gpregs[3]);
5982
boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[4], gpregs[5], gpregs[6], gpregs[7]);
6083
boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[8], gpregs[9], gpregs[10], gpregs[11]);
6184
boot_emerg(" %016lx %016lx %016lx %016lx\n", gpregs[12], gpregs[13], gpregs[14], gpregs[15]);
62-
print_stacktrace(get_lowcore()->gpregs_save_area[15]);
85+
print_stacktrace(gpregs[15]);
6386
boot_emerg("Last Breaking-Event-Address:\n");
64-
boot_emerg(" [<%016lx>] %pS\n", (unsigned long)get_lowcore()->pgm_last_break,
65-
(void *)get_lowcore()->pgm_last_break);
87+
boot_emerg(" [<%016lx>] %pS\n", regs->last_break, (void *)regs->last_break);
88+
/* Convert to disabled wait PSW */
89+
psw->io = 0;
90+
psw->ext = 0;
91+
psw->wait = 1;
6692
}

0 commit comments

Comments
 (0)