Commit d9c1e640 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-5.16-5' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Heiko Carstens:

 - Add missing handling of R_390_PLT32DBL relocation type in
   arch_kexec_apply_relocations_add(). Clang and the upcoming gcc 11.3
   generate such relocation entries, which our relocation code silently
   ignores, and which finally will result in an endless loop within the
   purgatory code in case of kexec.

 - Add proper handling of errors and print error messages when applying
   relocations

 - Fix duplicate tracking of irq nesting level in entry code

 - Let recordmcount.pl also look for jgnop mnemonic. Starting with
   binutils 2.37 objdump emits a jgnop mnemonic instead of brcl, which
   breaks mcount location detection. This is only a problem if used with
   compilers older than gcc 9, since with gcc 9 and newer compilers
   recordmcount.pl is not used anymore.

 - Remove preempt_disable()/preempt_enable() pair in
   kprobe_ftrace_handler() which was done for all architectures except
   for s390.

 - Update defconfig

* tag 's390-5.16-5' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  recordmcount.pl: look for jgnop instruction as well as bcrl on s390
  s390/entry: fix duplicate tracking of irq nesting level
  s390: enable switchdev support in defconfig
  s390/kexec: handle R_390_PLT32DBL rela in arch_kexec_apply_relocations_add()
  s390/ftrace: remove preempt_disable()/preempt_enable() pair
  s390/kexec_file: fix error handling when applying relocations
  s390/kexec_file: print some more error messages
parents 213d9d4c 85bf17b2
...@@ -117,6 +117,7 @@ CONFIG_UNIX=y ...@@ -117,6 +117,7 @@ CONFIG_UNIX=y
CONFIG_UNIX_DIAG=m CONFIG_UNIX_DIAG=m
CONFIG_XFRM_USER=m CONFIG_XFRM_USER=m
CONFIG_NET_KEY=m CONFIG_NET_KEY=m
CONFIG_NET_SWITCHDEV=y
CONFIG_SMC=m CONFIG_SMC=m
CONFIG_SMC_DIAG=m CONFIG_SMC_DIAG=m
CONFIG_INET=y CONFIG_INET=y
...@@ -511,6 +512,7 @@ CONFIG_NLMON=m ...@@ -511,6 +512,7 @@ CONFIG_NLMON=m
CONFIG_MLX4_EN=m CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y CONFIG_MLX5_CORE_EN=y
CONFIG_MLX5_ESWITCH=y
# CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set # CONFIG_NET_VENDOR_MICROSEMI is not set
......
...@@ -109,6 +109,7 @@ CONFIG_UNIX=y ...@@ -109,6 +109,7 @@ CONFIG_UNIX=y
CONFIG_UNIX_DIAG=m CONFIG_UNIX_DIAG=m
CONFIG_XFRM_USER=m CONFIG_XFRM_USER=m
CONFIG_NET_KEY=m CONFIG_NET_KEY=m
CONFIG_NET_SWITCHDEV=y
CONFIG_SMC=m CONFIG_SMC=m
CONFIG_SMC_DIAG=m CONFIG_SMC_DIAG=m
CONFIG_INET=y CONFIG_INET=y
...@@ -502,6 +503,7 @@ CONFIG_NLMON=m ...@@ -502,6 +503,7 @@ CONFIG_NLMON=m
CONFIG_MLX4_EN=m CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y CONFIG_MLX5_CORE_EN=y
CONFIG_MLX5_ESWITCH=y
# CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set # CONFIG_NET_VENDOR_MICROSEMI is not set
......
...@@ -290,7 +290,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, ...@@ -290,7 +290,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
return; return;
regs = ftrace_get_regs(fregs); regs = ftrace_get_regs(fregs);
preempt_disable_notrace();
p = get_kprobe((kprobe_opcode_t *)ip); p = get_kprobe((kprobe_opcode_t *)ip);
if (unlikely(!p) || kprobe_disabled(p)) if (unlikely(!p) || kprobe_disabled(p))
goto out; goto out;
...@@ -318,7 +317,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, ...@@ -318,7 +317,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
} }
__this_cpu_write(current_kprobe, NULL); __this_cpu_write(current_kprobe, NULL);
out: out:
preempt_enable_notrace();
ftrace_test_recursion_unlock(bit); ftrace_test_recursion_unlock(bit);
} }
NOKPROBE_SYMBOL(kprobe_ftrace_handler); NOKPROBE_SYMBOL(kprobe_ftrace_handler);
......
...@@ -138,7 +138,7 @@ void noinstr do_io_irq(struct pt_regs *regs) ...@@ -138,7 +138,7 @@ void noinstr do_io_irq(struct pt_regs *regs)
struct pt_regs *old_regs = set_irq_regs(regs); struct pt_regs *old_regs = set_irq_regs(regs);
int from_idle; int from_idle;
irq_enter(); irq_enter_rcu();
if (user_mode(regs)) { if (user_mode(regs)) {
update_timer_sys(); update_timer_sys();
...@@ -158,7 +158,8 @@ void noinstr do_io_irq(struct pt_regs *regs) ...@@ -158,7 +158,8 @@ void noinstr do_io_irq(struct pt_regs *regs)
do_irq_async(regs, IO_INTERRUPT); do_irq_async(regs, IO_INTERRUPT);
} while (MACHINE_IS_LPAR && irq_pending(regs)); } while (MACHINE_IS_LPAR && irq_pending(regs));
irq_exit(); irq_exit_rcu();
set_irq_regs(old_regs); set_irq_regs(old_regs);
irqentry_exit(regs, state); irqentry_exit(regs, state);
...@@ -172,7 +173,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) ...@@ -172,7 +173,7 @@ void noinstr do_ext_irq(struct pt_regs *regs)
struct pt_regs *old_regs = set_irq_regs(regs); struct pt_regs *old_regs = set_irq_regs(regs);
int from_idle; int from_idle;
irq_enter(); irq_enter_rcu();
if (user_mode(regs)) { if (user_mode(regs)) {
update_timer_sys(); update_timer_sys();
...@@ -190,7 +191,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) ...@@ -190,7 +191,7 @@ void noinstr do_ext_irq(struct pt_regs *regs)
do_irq_async(regs, EXT_INTERRUPT); do_irq_async(regs, EXT_INTERRUPT);
irq_exit(); irq_exit_rcu();
set_irq_regs(old_regs); set_irq_regs(old_regs);
irqentry_exit(regs, state); irqentry_exit(regs, state);
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com> * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
*/ */
#define pr_fmt(fmt) "kexec: " fmt
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kexec.h> #include <linux/kexec.h>
...@@ -290,8 +292,16 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, ...@@ -290,8 +292,16 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
const Elf_Shdr *relsec, const Elf_Shdr *relsec,
const Elf_Shdr *symtab) const Elf_Shdr *symtab)
{ {
const char *strtab, *name, *shstrtab;
const Elf_Shdr *sechdrs;
Elf_Rela *relas; Elf_Rela *relas;
int i, r_type; int i, r_type;
int ret;
/* String & section header string table */
sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
strtab = (char *)pi->ehdr + sechdrs[symtab->sh_link].sh_offset;
shstrtab = (char *)pi->ehdr + sechdrs[pi->ehdr->e_shstrndx].sh_offset;
relas = (void *)pi->ehdr + relsec->sh_offset; relas = (void *)pi->ehdr + relsec->sh_offset;
...@@ -304,15 +314,27 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, ...@@ -304,15 +314,27 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
sym = (void *)pi->ehdr + symtab->sh_offset; sym = (void *)pi->ehdr + symtab->sh_offset;
sym += ELF64_R_SYM(relas[i].r_info); sym += ELF64_R_SYM(relas[i].r_info);
if (sym->st_shndx == SHN_UNDEF) if (sym->st_name)
name = strtab + sym->st_name;
else
name = shstrtab + sechdrs[sym->st_shndx].sh_name;
if (sym->st_shndx == SHN_UNDEF) {
pr_err("Undefined symbol: %s\n", name);
return -ENOEXEC; return -ENOEXEC;
}
if (sym->st_shndx == SHN_COMMON) if (sym->st_shndx == SHN_COMMON) {
pr_err("symbol '%s' in common section\n", name);
return -ENOEXEC; return -ENOEXEC;
}
if (sym->st_shndx >= pi->ehdr->e_shnum && if (sym->st_shndx >= pi->ehdr->e_shnum &&
sym->st_shndx != SHN_ABS) sym->st_shndx != SHN_ABS) {
pr_err("Invalid section %d for symbol %s\n",
sym->st_shndx, name);
return -ENOEXEC; return -ENOEXEC;
}
loc = pi->purgatory_buf; loc = pi->purgatory_buf;
loc += section->sh_offset; loc += section->sh_offset;
...@@ -326,7 +348,15 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, ...@@ -326,7 +348,15 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
addr = section->sh_addr + relas[i].r_offset; addr = section->sh_addr + relas[i].r_offset;
r_type = ELF64_R_TYPE(relas[i].r_info); r_type = ELF64_R_TYPE(relas[i].r_info);
arch_kexec_do_relocs(r_type, loc, val, addr);
if (r_type == R_390_PLT32DBL)
r_type = R_390_PC32DBL;
ret = arch_kexec_do_relocs(r_type, loc, val, addr);
if (ret) {
pr_err("Unknown rela relocation: %d\n", r_type);
return -ENOEXEC;
}
} }
return 0; return 0;
} }
......
...@@ -219,7 +219,7 @@ if ($arch eq "x86_64") { ...@@ -219,7 +219,7 @@ if ($arch eq "x86_64") {
} elsif ($arch eq "s390" && $bits == 64) { } elsif ($arch eq "s390" && $bits == 64) {
if ($cc =~ /-DCC_USING_HOTPATCH/) { if ($cc =~ /-DCC_USING_HOTPATCH/) {
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$"; $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*(bcrl\\s*0,|jgnop\\s*)[0-9a-f]+ <([^\+]*)>\$";
$mcount_adjust = 0; $mcount_adjust = 0;
} }
$alignment = 8; $alignment = 8;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment