s390/kprobes: Remove custom insn slot allocator
authorHeiko Carstens <hca@linux.ibm.com>
Wed, 15 May 2024 12:52:21 +0000 (14:52 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Thu, 16 May 2024 08:31:32 +0000 (10:31 +0200)
Since commit c98d2ecae08f ("s390/mm: Uncouple physical vs virtual address
spaces") the kernel image and module area are within the same 4GB area.

This eliminates the need of a custom insn slot allocator for kprobes within
the kernel image, since standard module_alloc() allocated pages are
sufficient for PC relative instructions with a signed 32 bit offset.

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/kernel/Makefile
arch/s390/kernel/kprobes.c
arch/s390/kernel/kprobes.h [deleted file]
arch/s390/kernel/kprobes_insn_page.S [deleted file]

index db2d9ba5a86d229a91a9ff375c70a2edc0b9ed26..7241fa194709208d0feacd64fc89e91691e70746 100644 (file)
@@ -59,7 +59,6 @@ obj-$(CONFIG_COMPAT)          += compat_linux.o compat_signal.o
 obj-$(CONFIG_COMPAT)           += $(compat-obj-y)
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
-obj-$(CONFIG_KPROBES)          += kprobes_insn_page.o
 obj-$(CONFIG_KPROBES)          += mcount.o
 obj-$(CONFIG_RETHOOK)          += rethook.o
 obj-$(CONFIG_FUNCTION_TRACER)  += ftrace.o
index f0cf20d4b3c58070159b9a64b250ec4af12add53..d8b8e341cfc2de81051b754c51ed855393b09d27 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/set_memory.h>
 #include <asm/sections.h>
 #include <asm/dis.h>
-#include "kprobes.h"
 #include "entry.h"
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe);
@@ -32,8 +31,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 struct kretprobe_blackpoint kretprobe_blacklist[] = { };
 
-static int insn_page_in_use;
-
 void *alloc_insn_page(void)
 {
        void *page;
@@ -45,26 +42,6 @@ void *alloc_insn_page(void)
        return page;
 }
 
-static void *alloc_s390_insn_page(void)
-{
-       if (xchg(&insn_page_in_use, 1) == 1)
-               return NULL;
-       return &kprobes_insn_page;
-}
-
-static void free_s390_insn_page(void *page)
-{
-       xchg(&insn_page_in_use, 0);
-}
-
-struct kprobe_insn_cache kprobe_s390_insn_slots = {
-       .mutex = __MUTEX_INITIALIZER(kprobe_s390_insn_slots.mutex),
-       .alloc = alloc_s390_insn_page,
-       .free = free_s390_insn_page,
-       .pages = LIST_HEAD_INIT(kprobe_s390_insn_slots.pages),
-       .insn_size = MAX_INSN_SIZE,
-};
-
 static void copy_instruction(struct kprobe *p)
 {
        kprobe_opcode_t insn[MAX_INSN_SIZE];
@@ -78,10 +55,10 @@ static void copy_instruction(struct kprobe *p)
        if (probe_is_insn_relative_long(&insn[0])) {
                /*
                 * For pc-relative instructions in RIL-b or RIL-c format patch
-                * the RI2 displacement field. We have already made sure that
-                * the insn slot for the patched instruction is within the same
-                * 2GB area as the original instruction (either kernel image or
-                * module area). Therefore the new displacement will always fit.
+                * the RI2 displacement field. The insn slot for the to be
+                * patched instruction is within the same 4GB area like the
+                * original instruction. Therefore the new displacement will
+                * always fit.
                 */
                disp = *(s32 *)&insn[1];
                addr = (u64)(unsigned long)p->addr;
@@ -93,34 +70,6 @@ static void copy_instruction(struct kprobe *p)
 }
 NOKPROBE_SYMBOL(copy_instruction);
 
-static int s390_get_insn_slot(struct kprobe *p)
-{
-       /*
-        * Get an insn slot that is within the same 2GB area like the original
-        * instruction. That way instructions with a 32bit signed displacement
-        * field can be patched and executed within the insn slot.
-        */
-       p->ainsn.insn = NULL;
-       if (is_kernel((unsigned long)p->addr))
-               p->ainsn.insn = get_s390_insn_slot();
-       else if (is_module_addr(p->addr))
-               p->ainsn.insn = get_insn_slot();
-       return p->ainsn.insn ? 0 : -ENOMEM;
-}
-NOKPROBE_SYMBOL(s390_get_insn_slot);
-
-static void s390_free_insn_slot(struct kprobe *p)
-{
-       if (!p->ainsn.insn)
-               return;
-       if (is_kernel((unsigned long)p->addr))
-               free_s390_insn_slot(p->ainsn.insn, 0);
-       else
-               free_insn_slot(p->ainsn.insn, 0);
-       p->ainsn.insn = NULL;
-}
-NOKPROBE_SYMBOL(s390_free_insn_slot);
-
 /* Check if paddr is at an instruction boundary */
 static bool can_probe(unsigned long paddr)
 {
@@ -174,7 +123,8 @@ int arch_prepare_kprobe(struct kprobe *p)
        /* Make sure the probe isn't going on a difficult instruction */
        if (probe_is_prohibited_opcode(p->addr))
                return -EINVAL;
-       if (s390_get_insn_slot(p))
+       p->ainsn.insn = get_insn_slot();
+       if (!p->ainsn.insn)
                return -ENOMEM;
        copy_instruction(p);
        return 0;
@@ -216,7 +166,10 @@ NOKPROBE_SYMBOL(arch_disarm_kprobe);
 
 void arch_remove_kprobe(struct kprobe *p)
 {
-       s390_free_insn_slot(p);
+       if (!p->ainsn.insn)
+               return;
+       free_insn_slot(p->ainsn.insn, 0);
+       p->ainsn.insn = NULL;
 }
 NOKPROBE_SYMBOL(arch_remove_kprobe);
 
diff --git a/arch/s390/kernel/kprobes.h b/arch/s390/kernel/kprobes.h
deleted file mode 100644 (file)
index dc3ed50..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-#ifndef _ARCH_S390_KPROBES_H
-#define _ARCH_S390_KPROBES_H
-
-#include <linux/kprobes.h>
-
-DEFINE_INSN_CACHE_OPS(s390_insn);
-
-#endif
diff --git a/arch/s390/kernel/kprobes_insn_page.S b/arch/s390/kernel/kprobes_insn_page.S
deleted file mode 100644 (file)
index 0fe4d72..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <linux/linkage.h>
-
-/*
- * insn_page is a special 4k aligned dummy function for kprobes.
- * It will contain all kprobed instructions that are out-of-line executed.
- * The page must be within the kernel image to guarantee that the
- * out-of-line instructions are within 2GB distance of their original
- * location. Using a dummy function ensures that the insn_page is within
- * the text section of the kernel and mapped read-only/executable from
- * the beginning on, thus avoiding to split large mappings if the page
- * would be in the data section instead.
- */
-       .section .kprobes.text, "ax"
-       .balign 4096
-SYM_CODE_START(kprobes_insn_page)
-       .rept 2048
-       .word 0x07fe
-       .endr
-SYM_CODE_END(kprobes_insn_page)
-       .previous