Commit fd3d2742 authored by Gerald Schaefer's avatar Gerald Schaefer Committed by Martin Schwidefsky

s390/kprobes: use static buffer for insn_page

With a relocatable kernel that could reside at any place in memory, the
current logic for allocating a kprobes insn_page does not work. The
GFP_DMA allocated buffer might be more than 2 GB away from the kernel.

Use a static buffer for the insn_page instead.
Signed-off-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Reviewed-by: default avatarPhilipp Rudo <prudo@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent ff4a742d
...@@ -27,29 +27,30 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); ...@@ -27,29 +27,30 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
struct kretprobe_blackpoint kretprobe_blacklist[] = { }; struct kretprobe_blackpoint kretprobe_blacklist[] = { };
DEFINE_INSN_CACHE_OPS(dmainsn); DEFINE_INSN_CACHE_OPS(s390_insn);
static void *alloc_dmainsn_page(void) static int insn_page_in_use;
{ static char insn_page[PAGE_SIZE] __aligned(PAGE_SIZE);
void *page;
page = (void *) __get_free_page(GFP_KERNEL | GFP_DMA); static void *alloc_s390_insn_page(void)
if (page) {
set_memory_x((unsigned long) page, 1); if (xchg(&insn_page_in_use, 1) == 1)
return page; return NULL;
set_memory_x((unsigned long) &insn_page, 1);
return &insn_page;
} }
static void free_dmainsn_page(void *page) static void free_s390_insn_page(void *page)
{ {
set_memory_nx((unsigned long) page, 1); set_memory_nx((unsigned long) page, 1);
free_page((unsigned long)page); xchg(&insn_page_in_use, 0);
} }
struct kprobe_insn_cache kprobe_dmainsn_slots = { struct kprobe_insn_cache kprobe_s390_insn_slots = {
.mutex = __MUTEX_INITIALIZER(kprobe_dmainsn_slots.mutex), .mutex = __MUTEX_INITIALIZER(kprobe_s390_insn_slots.mutex),
.alloc = alloc_dmainsn_page, .alloc = alloc_s390_insn_page,
.free = free_dmainsn_page, .free = free_s390_insn_page,
.pages = LIST_HEAD_INIT(kprobe_dmainsn_slots.pages), .pages = LIST_HEAD_INIT(kprobe_s390_insn_slots.pages),
.insn_size = MAX_INSN_SIZE, .insn_size = MAX_INSN_SIZE,
}; };
...@@ -102,7 +103,7 @@ static int s390_get_insn_slot(struct kprobe *p) ...@@ -102,7 +103,7 @@ static int s390_get_insn_slot(struct kprobe *p)
*/ */
p->ainsn.insn = NULL; p->ainsn.insn = NULL;
if (is_kernel_addr(p->addr)) if (is_kernel_addr(p->addr))
p->ainsn.insn = get_dmainsn_slot(); p->ainsn.insn = get_s390_insn_slot();
else if (is_module_addr(p->addr)) else if (is_module_addr(p->addr))
p->ainsn.insn = get_insn_slot(); p->ainsn.insn = get_insn_slot();
return p->ainsn.insn ? 0 : -ENOMEM; return p->ainsn.insn ? 0 : -ENOMEM;
...@@ -114,7 +115,7 @@ static void s390_free_insn_slot(struct kprobe *p) ...@@ -114,7 +115,7 @@ static void s390_free_insn_slot(struct kprobe *p)
if (!p->ainsn.insn) if (!p->ainsn.insn)
return; return;
if (is_kernel_addr(p->addr)) if (is_kernel_addr(p->addr))
free_dmainsn_slot(p->ainsn.insn, 0); free_s390_insn_slot(p->ainsn.insn, 0);
else else
free_insn_slot(p->ainsn.insn, 0); free_insn_slot(p->ainsn.insn, 0);
p->ainsn.insn = NULL; p->ainsn.insn = NULL;
......
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