Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4c6c34a authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Linus Torvalds
Browse files

[PATCH] kprobes: enable booster on the preemptible kernel



When we are unregistering a kprobe-booster, we can't release its
instruction buffer immediately on the preemptive kernel, because some
processes might be preempted on the buffer.  The freeze_processes() and
thaw_processes() functions can clean most of processes up from the buffer.
There are still some non-frozen threads who have the PF_NOFREEZE flag.  If
those threads are sleeping (not preempted) at the known place outside the
buffer, we can ensure safety of freeing.

However, the processing of this check routine takes a long time.  So, this
patch introduces the garbage collection mechanism of insn_slot.  It also
introduces the "dirty" flag to free_insn_slot because of efficiency.

The "clean" instruction slots (dirty flag is cleared) are released
immediately.  But the "dirty" slots which are used by boosted kprobes, are
marked as garbages.  collect_garbage_slots() will be invoked to release
"dirty" slots if there are more than INSNS_PER_PAGE garbage slots or if
there are no unused slots.

Cc: "Keshavamurthy, Anil S" <anil.s.keshavamurthy@intel.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: "bibo,mao" <bibo.mao@intel.com>
Cc: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Cc: Yumiko Sugita <yumiko.sugita.yf@hitachi.com>
Cc: Satoshi Oshima <soshima@redhat.com>
Cc: Hideo Aoki <haoki@redhat.com>
Signed-off-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Acked-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c15bb296
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -184,7 +184,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
	mutex_lock(&kprobe_mutex);
	free_insn_slot(p->ainsn.insn);
	free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
	mutex_unlock(&kprobe_mutex);
}

@@ -333,7 +333,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
		return 1;

ss_probe:
#ifndef CONFIG_PREEMPT
#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
	if (p->ainsn.boostable == 1 && !p->post_handler){
		/* Boost up -- we can execute copied instructions directly */
		reset_current_kprobe();
+1 −1
Original line number Diff line number Diff line
@@ -481,7 +481,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
	mutex_lock(&kprobe_mutex);
	free_insn_slot(p->ainsn.insn);
	free_insn_slot(p->ainsn.insn, 0);
	mutex_unlock(&kprobe_mutex);
}
/*
+1 −1
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
	mutex_lock(&kprobe_mutex);
	free_insn_slot(p->ainsn.insn);
	free_insn_slot(p->ainsn.insn, 0);
	mutex_unlock(&kprobe_mutex);
}

+1 −1
Original line number Diff line number Diff line
@@ -200,7 +200,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
	mutex_lock(&kprobe_mutex);
	free_insn_slot(p->ainsn.insn);
	free_insn_slot(p->ainsn.insn, 0);
	mutex_unlock(&kprobe_mutex);
}

+1 −1
Original line number Diff line number Diff line
@@ -224,7 +224,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
	mutex_lock(&kprobe_mutex);
	free_insn_slot(p->ainsn.insn);
	free_insn_slot(p->ainsn.insn, 0);
	mutex_unlock(&kprobe_mutex);
}

Loading