The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <compudj@krystal.dyndns.org>
To: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
	lkml <linux-kernel@vger.kernel.org>,
	systemtap <systemtap@sources.redhat.com>,
	DLE <dle-develop@lists.sourceforge.net>,
	Jim Keniston <jkenisto@us.ibm.com>,
	Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
	Christoph Hellwig <hch@infradead.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Anders Kaseorg <andersk@ksplice.com>,
	Tim Abbott <tabbott@ksplice.com>,
	Andi Kleen <andi@firstfloor.org>, Jason Baron <jbaron@redhat.com>
Subject: Re: [PATCH -tip v3&10 02/18] kprobes: Introduce generic insn_slot framework
Date: Thu, 25 Feb 2010 10:21:30 -0500	[thread overview]
Message-ID: <20100225152130.GB12635@Krystal> (raw)
In-Reply-To: <20100225133358.6725.82430.stgit@localhost6.localdomain6>

* Masami Hiramatsu (mhiramat@redhat.com) wrote:
> Make insn_slot framework support various size slots.
> Current insn_slot just supports one-size instruction buffer slot. However,
> kprobes jump optimization needs larger size buffers.

OK, so you end up having one insn slot cache for kprobes and one insn
slot (eventually) for the static jump patching (which needs larger
instruction slots than kprobes). That seems like a good way to ensure
you do not use more memory than necessary.

We could possibly go even further and automatically use the right insn
slot cache given the size of the instruction entry that must be added (a
bit like the memory allocator which have different pools for each
allocation order).

Possibly that using the terminology of "memory pools" rather than
"cache" could be a better fit too. So what this really becomes is an
instruction slot allocator and garbage collector.

Thanks,

Mathieu

> 
> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
> Cc: Ingo Molnar <mingo@elte.hu>
> Cc: Jim Keniston <jkenisto@us.ibm.com>
> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
> Cc: Christoph Hellwig <hch@infradead.org>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: H. Peter Anvin <hpa@zytor.com>
> Cc: Anders Kaseorg <andersk@ksplice.com>
> Cc: Tim Abbott <tabbott@ksplice.com>
> Cc: Andi Kleen <andi@firstfloor.org>
> Cc: Jason Baron <jbaron@redhat.com>
> Cc: Mathieu Desnoyers <compudj@krystal.dyndns.org>
> ---
> 
>  kernel/kprobes.c |  104 ++++++++++++++++++++++++++++++++++--------------------
>  1 files changed, 65 insertions(+), 39 deletions(-)
> 
> diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> index ccec774..7810562 100644
> --- a/kernel/kprobes.c
> +++ b/kernel/kprobes.c
> @@ -105,57 +105,74 @@ static struct kprobe_blackpoint kprobe_blacklist[] = {
>   * stepping on the instruction on a vmalloced/kmalloced/data page
>   * is a recipe for disaster
>   */
> -#define INSNS_PER_PAGE	(PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
> -
>  struct kprobe_insn_page {
>  	struct list_head list;
>  	kprobe_opcode_t *insns;		/* Page of instruction slots */
> -	char slot_used[INSNS_PER_PAGE];
>  	int nused;
>  	int ngarbage;
> +	char slot_used[];
> +};
> +
> +#define KPROBE_INSN_PAGE_SIZE(slots)			\
> +	(offsetof(struct kprobe_insn_page, slot_used) +	\
> +	 (sizeof(char) * (slots)))
> +
> +struct kprobe_insn_cache {
> +	struct list_head pages;	/* list of kprobe_insn_page */
> +	size_t insn_size;	/* size of instruction slot */
> +	int nr_garbage;
>  };
>  
> +static int slots_per_page(struct kprobe_insn_cache *c)
> +{
> +	return PAGE_SIZE/(c->insn_size * sizeof(kprobe_opcode_t));
> +}
> +
>  enum kprobe_slot_state {
>  	SLOT_CLEAN = 0,
>  	SLOT_DIRTY = 1,
>  	SLOT_USED = 2,
>  };
>  
> -static DEFINE_MUTEX(kprobe_insn_mutex);	/* Protects kprobe_insn_pages */
> -static LIST_HEAD(kprobe_insn_pages);
> -static int kprobe_garbage_slots;
> -static int collect_garbage_slots(void);
> +static DEFINE_MUTEX(kprobe_insn_mutex);	/* Protects kprobe_insn_slots */
> +static struct kprobe_insn_cache kprobe_insn_slots = {
> +	.pages = LIST_HEAD_INIT(kprobe_insn_slots.pages),
> +	.insn_size = MAX_INSN_SIZE,
> +	.nr_garbage = 0,
> +};
> +static int __kprobes collect_garbage_slots(struct kprobe_insn_cache *c);
>  
>  /**
>   * __get_insn_slot() - Find a slot on an executable page for an instruction.
>   * We allocate an executable page if there's no room on existing ones.
>   */
> -static kprobe_opcode_t __kprobes *__get_insn_slot(void)
> +static kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c)
>  {
>  	struct kprobe_insn_page *kip;
>  
>   retry:
> -	list_for_each_entry(kip, &kprobe_insn_pages, list) {
> -		if (kip->nused < INSNS_PER_PAGE) {
> +	list_for_each_entry(kip, &c->pages, list) {
> +		if (kip->nused < slots_per_page(c)) {
>  			int i;
> -			for (i = 0; i < INSNS_PER_PAGE; i++) {
> +			for (i = 0; i < slots_per_page(c); i++) {
>  				if (kip->slot_used[i] == SLOT_CLEAN) {
>  					kip->slot_used[i] = SLOT_USED;
>  					kip->nused++;
> -					return kip->insns + (i * MAX_INSN_SIZE);
> +					return kip->insns + (i * c->insn_size);
>  				}
>  			}
> -			/* Surprise!  No unused slots.  Fix kip->nused. */
> -			kip->nused = INSNS_PER_PAGE;
> +			/* kip->nused is broken. Fix it. */
> +			kip->nused = slots_per_page(c);
> +			WARN_ON(1);
>  		}
>  	}
>  
>  	/* If there are any garbage slots, collect it and try again. */
> -	if (kprobe_garbage_slots && collect_garbage_slots() == 0) {
> +	if (c->nr_garbage && collect_garbage_slots(c) == 0)
>  		goto retry;
> -	}
> -	/* All out of space.  Need to allocate a new page. Use slot 0. */
> -	kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
> +
> +	/* All out of space.  Need to allocate a new page. */
> +	kip = kmalloc(KPROBE_INSN_PAGE_SIZE(slots_per_page(c)), GFP_KERNEL);
>  	if (!kip)
>  		return NULL;
>  
> @@ -170,20 +187,23 @@ static kprobe_opcode_t __kprobes *__get_insn_slot(void)
>  		return NULL;
>  	}
>  	INIT_LIST_HEAD(&kip->list);
> -	list_add(&kip->list, &kprobe_insn_pages);
> -	memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE);
> +	memset(kip->slot_used, SLOT_CLEAN, slots_per_page(c));
>  	kip->slot_used[0] = SLOT_USED;
>  	kip->nused = 1;
>  	kip->ngarbage = 0;
> +	list_add(&kip->list, &c->pages);
>  	return kip->insns;
>  }
>  
> +
>  kprobe_opcode_t __kprobes *get_insn_slot(void)
>  {
> -	kprobe_opcode_t *ret;
> +	kprobe_opcode_t *ret = NULL;
> +
>  	mutex_lock(&kprobe_insn_mutex);
> -	ret = __get_insn_slot();
> +	ret = __get_insn_slot(&kprobe_insn_slots);
>  	mutex_unlock(&kprobe_insn_mutex);
> +
>  	return ret;
>  }
>  
> @@ -199,7 +219,7 @@ static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
>  		 * so as not to have to set it up again the
>  		 * next time somebody inserts a probe.
>  		 */
> -		if (!list_is_singular(&kprobe_insn_pages)) {
> +		if (!list_is_singular(&kip->list)) {
>  			list_del(&kip->list);
>  			module_free(NULL, kip->insns);
>  			kfree(kip);
> @@ -209,49 +229,55 @@ static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
>  	return 0;
>  }
>  
> -static int __kprobes collect_garbage_slots(void)
> +static int __kprobes collect_garbage_slots(struct kprobe_insn_cache *c)
>  {
>  	struct kprobe_insn_page *kip, *next;
>  
>  	/* Ensure no-one is interrupted on the garbages */
>  	synchronize_sched();
>  
> -	list_for_each_entry_safe(kip, next, &kprobe_insn_pages, list) {
> +	list_for_each_entry_safe(kip, next, &c->pages, list) {
>  		int i;
>  		if (kip->ngarbage == 0)
>  			continue;
>  		kip->ngarbage = 0;	/* we will collect all garbages */
> -		for (i = 0; i < INSNS_PER_PAGE; i++) {
> +		for (i = 0; i < slots_per_page(c); i++) {
>  			if (kip->slot_used[i] == SLOT_DIRTY &&
>  			    collect_one_slot(kip, i))
>  				break;
>  		}
>  	}
> -	kprobe_garbage_slots = 0;
> +	c->nr_garbage = 0;
>  	return 0;
>  }
>  
> -void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
> +static void __kprobes __free_insn_slot(struct kprobe_insn_cache *c,
> +				       kprobe_opcode_t *slot, int dirty)
>  {
>  	struct kprobe_insn_page *kip;
>  
> -	mutex_lock(&kprobe_insn_mutex);
> -	list_for_each_entry(kip, &kprobe_insn_pages, list) {
> -		if (kip->insns <= slot &&
> -		    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
> -			int i = (slot - kip->insns) / MAX_INSN_SIZE;
> +	list_for_each_entry(kip, &c->pages, list) {
> +		long idx = ((long)slot - (long)kip->insns) / c->insn_size;
> +		if (idx >= 0 && idx < slots_per_page(c)) {
> +			WARN_ON(kip->slot_used[idx] != SLOT_USED);
>  			if (dirty) {
> -				kip->slot_used[i] = SLOT_DIRTY;
> +				kip->slot_used[idx] = SLOT_DIRTY;
>  				kip->ngarbage++;
> +				if (++c->nr_garbage > slots_per_page(c))
> +					collect_garbage_slots(c);
>  			} else
> -				collect_one_slot(kip, i);
> -			break;
> +				collect_one_slot(kip, idx);
> +			return;
>  		}
>  	}
> +	/* Could not free this slot. */
> +	WARN_ON(1);
> +}
>  
> -	if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE)
> -		collect_garbage_slots();
> -
> +void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
> +{
> +	mutex_lock(&kprobe_insn_mutex);
> +	__free_insn_slot(&kprobe_insn_slots, slot, dirty);
>  	mutex_unlock(&kprobe_insn_mutex);
>  }
>  #endif
> 
> 
> -- 
> Masami Hiramatsu
> 
> Software Engineer
> Hitachi Computer Products (America), Inc.
> Software Solutions Division
> 
> e-mail: mhiramat@redhat.com
> 

-- 
Mathieu Desnoyers
Operating System Efficiency Consultant
EfficiOS Inc.
http://www.efficios.com

  reply	other threads:[~2010-02-25 15:21 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-25 13:33 [PATCH -tip v3&10 00/18] perf-probe updates - optprobe, elfutils and lazy matching Masami Hiramatsu
2010-02-25 13:33 ` [PATCH -tip v3&10 01/18] kprobes/x86: Cleanup RELATIVEJUMP_INSTRUCTION to RELATIVEJUMP_OPCODE Masami Hiramatsu
2010-02-25 15:10   ` Mathieu Desnoyers
2010-02-25 19:27   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:33 ` [PATCH -tip v3&10 02/18] kprobes: Introduce generic insn_slot framework Masami Hiramatsu
2010-02-25 15:21   ` Mathieu Desnoyers [this message]
2010-03-02  2:55     ` Masami Hiramatsu
2010-03-03  0:18       ` Masami Hiramatsu
2010-03-03  0:32         ` Mathieu Desnoyers
2010-03-03  0:35           ` Masami Hiramatsu
2010-02-25 19:28   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 03/18] kprobes: Introduce kprobes jump optimization Masami Hiramatsu
2010-02-25 19:28   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 04/18] kprobes: Jump optimization sysctl interface Masami Hiramatsu
2010-02-25 19:28   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 05/18] kprobes/x86: Boost probes when reentering Masami Hiramatsu
2010-02-25 19:29   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 06/18] kprobes/x86: Cleanup save/restore registers Masami Hiramatsu
2010-02-25 19:29   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 07/18] x86: Add text_poke_smp for SMP cross modifying code Masami Hiramatsu
2010-02-25 15:33   ` Mathieu Desnoyers
2010-02-26  3:53     ` Masami Hiramatsu
2010-03-03  0:48       ` Mathieu Desnoyers
2010-03-03  0:56         ` Masami Hiramatsu
2010-02-25 19:29   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 08/18] kprobes/x86: Support kprobes jump optimization on x86 Masami Hiramatsu
2010-02-25 19:29   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 09/18] kprobes: Add documents of jump optimization Masami Hiramatsu
2010-02-25 19:30   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 10/18] perf probe: Do not show --line option without dwarf support Masami Hiramatsu
2010-02-25 19:30   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 11/18] perf probe: Update perf probe document Masami Hiramatsu
2010-02-25 19:30   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 12/18] perf probe: Fix bugs in line range finder Masami Hiramatsu
2010-02-25 19:30   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 13/18] perf probe: Rename probe finder functions Masami Hiramatsu
2010-02-25 19:31   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 14/18] perf probe: Use elfutils-libdw for analyzing debuginfo Masami Hiramatsu
2010-02-25 19:31   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 15/18] perf probe: Use libdw callback routines Masami Hiramatsu
2010-02-25 19:31   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 16/18] perf probe: Check function address range strictly in line finder Masami Hiramatsu
2010-02-25 19:31   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:36 ` [PATCH -tip v3&10 17/18] perf probe: show more lines after last line Masami Hiramatsu
2010-02-25 19:32   ` [tip:perf/probes] perf probe: Show " tip-bot for Masami Hiramatsu
2010-02-25 13:36 ` [PATCH -tip v3&10 18/18] perf probe: Add lazy line matching support Masami Hiramatsu
2010-02-25 19:32   ` [tip:perf/probes] " tip-bot for Masami Hiramatsu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100225152130.GB12635@Krystal \
    --to=compudj@krystal.dyndns.org \
    --cc=ananth@in.ibm.com \
    --cc=andersk@ksplice.com \
    --cc=andi@firstfloor.org \
    --cc=dle-develop@lists.sourceforge.net \
    --cc=fweisbec@gmail.com \
    --cc=hch@infradead.org \
    --cc=hpa@zytor.com \
    --cc=jbaron@redhat.com \
    --cc=jkenisto@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhiramat@redhat.com \
    --cc=mingo@elte.hu \
    --cc=rostedt@goodmis.org \
    --cc=srikar@linux.vnet.ibm.com \
    --cc=systemtap@sources.redhat.com \
    --cc=tabbott@ksplice.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox