Commit a30df1ea authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'riscv-for-linus-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V fixes from Palmer Dabbelt:

 - A build fix to avoid static branches in cpu_relax(), which greatly
   inflates the jump tables and breaks at least
   CONFIG_CC_OPTIMIZE_FOR_SIZE=y.

 - A fix for a kernel panic when probing impossible instruction
   positions.

 - A fix to disable unwind tables, which are enabled by default for
   GCC-13 and result in unhandled relocations in modules.

* tag 'riscv-for-linus-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
  riscv: disable generation of unwind tables
  riscv: kprobe: Fixup kernel panic when probing an illegal position
  riscv: Fix build with CONFIG_CC_OPTIMIZE_FOR_SIZE=y
parents bffede38 2f394c0e
...@@ -80,6 +80,9 @@ ifeq ($(CONFIG_PERF_EVENTS),y) ...@@ -80,6 +80,9 @@ ifeq ($(CONFIG_PERF_EVENTS),y)
KBUILD_CFLAGS += -fno-omit-frame-pointer KBUILD_CFLAGS += -fno-omit-frame-pointer
endif endif
# Avoid generating .eh_frame sections.
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax)
KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax) KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax)
......
...@@ -70,7 +70,6 @@ static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX); ...@@ -70,7 +70,6 @@ static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX);
*/ */
enum riscv_isa_ext_key { enum riscv_isa_ext_key {
RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */ RISCV_ISA_EXT_KEY_FPU, /* For 'F' and 'D' */
RISCV_ISA_EXT_KEY_ZIHINTPAUSE,
RISCV_ISA_EXT_KEY_SVINVAL, RISCV_ISA_EXT_KEY_SVINVAL,
RISCV_ISA_EXT_KEY_MAX, RISCV_ISA_EXT_KEY_MAX,
}; };
...@@ -91,8 +90,6 @@ static __always_inline int riscv_isa_ext2key(int num) ...@@ -91,8 +90,6 @@ static __always_inline int riscv_isa_ext2key(int num)
return RISCV_ISA_EXT_KEY_FPU; return RISCV_ISA_EXT_KEY_FPU;
case RISCV_ISA_EXT_d: case RISCV_ISA_EXT_d:
return RISCV_ISA_EXT_KEY_FPU; return RISCV_ISA_EXT_KEY_FPU;
case RISCV_ISA_EXT_ZIHINTPAUSE:
return RISCV_ISA_EXT_KEY_ZIHINTPAUSE;
case RISCV_ISA_EXT_SVINVAL: case RISCV_ISA_EXT_SVINVAL:
return RISCV_ISA_EXT_KEY_SVINVAL; return RISCV_ISA_EXT_KEY_SVINVAL;
default: default:
......
...@@ -4,30 +4,26 @@ ...@@ -4,30 +4,26 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/jump_label.h>
#include <asm/barrier.h> #include <asm/barrier.h>
#include <asm/hwcap.h>
static inline void cpu_relax(void) static inline void cpu_relax(void)
{ {
if (!static_branch_likely(&riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_ZIHINTPAUSE])) {
#ifdef __riscv_muldiv #ifdef __riscv_muldiv
int dummy; int dummy;
/* In lieu of a halt instruction, induce a long-latency stall. */ /* In lieu of a halt instruction, induce a long-latency stall. */
__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy)); __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
#endif #endif
} else {
/* #ifdef __riscv_zihintpause
* Reduce instruction retirement. /*
* This assumes the PC changes. * Reduce instruction retirement.
*/ * This assumes the PC changes.
#ifdef CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE */
__asm__ __volatile__ ("pause"); __asm__ __volatile__ ("pause");
#else #else
/* Encoding of the pause instruction */ /* Encoding of the pause instruction */
__asm__ __volatile__ (".4byte 0x100000F"); __asm__ __volatile__ (".4byte 0x100000F");
#endif #endif
}
barrier(); barrier();
} }
......
...@@ -48,6 +48,21 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) ...@@ -48,6 +48,21 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
post_kprobe_handler(p, kcb, regs); post_kprobe_handler(p, kcb, regs);
} }
static bool __kprobes arch_check_kprobe(struct kprobe *p)
{
unsigned long tmp = (unsigned long)p->addr - p->offset;
unsigned long addr = (unsigned long)p->addr;
while (tmp <= addr) {
if (tmp == addr)
return true;
tmp += GET_INSN_LENGTH(*(u16 *)tmp);
}
return false;
}
int __kprobes arch_prepare_kprobe(struct kprobe *p) int __kprobes arch_prepare_kprobe(struct kprobe *p)
{ {
unsigned long probe_addr = (unsigned long)p->addr; unsigned long probe_addr = (unsigned long)p->addr;
...@@ -55,6 +70,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) ...@@ -55,6 +70,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
if (probe_addr & 0x1) if (probe_addr & 0x1)
return -EILSEQ; return -EILSEQ;
if (!arch_check_kprobe(p))
return -EILSEQ;
/* copy instruction */ /* copy instruction */
p->opcode = *p->addr; p->opcode = *p->addr;
......
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