Skip to content

Commit

Permalink
s390/kprobes: Remove custom insn slot allocator
Browse files Browse the repository at this point in the history
Since commit c98d2ec ("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>
  • Loading branch information
Heiko Carstens committed May 16, 2024
1 parent e7dec0b commit d890e6a
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 89 deletions.
1 change: 0 additions & 1 deletion arch/s390/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 10 additions & 57 deletions arch/s390/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@
#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);
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;
Expand All @@ -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];
Expand All @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
9 changes: 0 additions & 9 deletions arch/s390/kernel/kprobes.h

This file was deleted.

22 changes: 0 additions & 22 deletions arch/s390/kernel/kprobes_insn_page.S

This file was deleted.

0 comments on commit d890e6a

Please sign in to comment.