From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27526 invoked by alias); 19 Oct 2006 09:00:43 -0000 Received: (qmail 26151 invoked by uid 22791); 19 Oct 2006 09:00:41 -0000 X-Spam-Status: No, hits=1.1 required=5.0 tests=AWL,BAYES_20,TW_DJ,UNPARSEABLE_RELAY X-Spam-Check-By: sourceware.org Received: from mail4.hitachi.co.jp (HELO mail4.hitachi.co.jp) (133.145.228.5) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 19 Oct 2006 09:00:34 +0000 Received: from mlsv8.hitachi.co.jp (unknown [133.145.228.16]) by mail4.hitachi.co.jp (Postfix) with ESMTP id 1413E33CE7 for ; Thu, 19 Oct 2006 18:00:32 +0900 (JST) Received: from mfilter-s2.hitachi.co.jp by mlsv8.hitachi.co.jp (8.12.11/8.12.11) id k9J90VgM014621; Thu, 19 Oct 2006 18:00:31 +0900 Received: from vshuts5.hitachi.co.jp (unverified) by mfilter-s2.hitachi.co.jp (Content Technologies SMTPRS 4.3.17) with SMTP id ; Thu, 19 Oct 2006 18:00:31 +0900 Received: from hsdlgw92.sdl.hitachi.co.jp ([133.144.7.20]) by vshuts5.hitachi.co.jp with SMTP id M2006101918003018166 ; Thu, 19 Oct 2006 18:00:31 +0900 Received: from vgate2.sdl.hitachi.co.jp by hsdlgw92.sdl.hitachi.co.jp (8.9.3/3.7W06061314) id SAA20136; Thu, 19 Oct 2006 18:00:28 +0900 Received: from maila.sdl.hitachi.co.jp ([133.144.14.196]) by vgate2.sdl.hitachi.co.jp (SAVSMTP 3.1.1.32) with SMTP id M2006101918002904255 ; Thu, 19 Oct 2006 18:00:29 +0900 Received: from [127.0.0.1] ([10.232.9.172]) by maila.sdl.hitachi.co.jp (8.13.1/3.7W04031011) with ESMTP id k9J90SF5006386; Thu, 19 Oct 2006 18:00:29 +0900 Message-ID: <45373E99.20301@hitachi.com> Date: Thu, 19 Oct 2006 09:00:00 -0000 From: Masami Hiramatsu Organization: Systems Development Lab., Hitachi, Ltd., Japan User-Agent: Thunderbird 1.5.0.7 (Windows/20060909) MIME-Version: 1.0 To: "Keshavamurthy, Anil S" , Ananth N Mavinakayanahalli , Prasanna S Panchamukhi , Ingo Molnar , SystemTAP Cc: Masami Hiramatsu , Satoshi Oshima , Hideo Aoki , Yumiko Sugita Subject: [PATCH 1/5][djprobe] generalize the length of the instruction slots. References: <45338593.6090207@hitachi.com> In-Reply-To: <45338593.6090207@hitachi.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2006-q4/txt/msg00176.txt.bz2 Hi, This patch generalizes get/free_insn_slot() to manage multiple length instruction slots, because the djprobe needs longer instruction slots than kprobes. NOTE: This patch depends on my previous patch which enables kprobe-booster on the preemptible kernel. http://sources.redhat.com/ml/systemtap/2006-q4/msg00126.html -- Masami HIRAMATSU Linux Technology Center Hitachi, Ltd., Systems Development Laboratory E-mail: masami.hiramatsu.pt@hitachi.com --- include/linux/kprobes.h | 6 +++ kernel/kprobes.c | 85 ++++++++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 31 deletions(-) Index: linux-2.6.19-rc1-mm1/include/linux/kprobes.h =================================================================== --- linux-2.6.19-rc1-mm1.orig/include/linux/kprobes.h 2006-10-16 21:43:07.000000000 +0900 +++ linux-2.6.19-rc1-mm1/include/linux/kprobes.h 2006-10-16 22:10:18.000000000 +0900 @@ -157,6 +157,12 @@ struct task_struct *task; }; +struct kprobe_insn_page_list { + struct hlist_head list; + int insn_size; /* size of an instruction slot */ + int nr_garbage; +}; + extern spinlock_t kretprobe_lock; extern struct mutex kprobe_mutex; extern int arch_prepare_kprobe(struct kprobe *p); Index: linux-2.6.19-rc1-mm1/kernel/kprobes.c =================================================================== --- linux-2.6.19-rc1-mm1.orig/kernel/kprobes.c 2006-10-16 21:50:44.000000000 +0900 +++ linux-2.6.19-rc1-mm1/kernel/kprobes.c 2006-10-16 22:10:39.000000000 +0900 @@ -77,52 +77,60 @@ * 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))) +#define INSNS_PER_PAGE(size) (PAGE_SIZE/(size * sizeof(kprobe_opcode_t))) struct kprobe_insn_page { struct hlist_node hlist; kprobe_opcode_t *insns; /* Page of instruction slots */ - char slot_used[INSNS_PER_PAGE]; int nused; int ngarbage; + char slot_used[1]; }; -static struct hlist_head kprobe_insn_pages; -static int kprobe_garbage_slots; -static int collect_garbage_slots(void); +static struct kprobe_insn_page_list kprobe_insn_pages = { + .list = HLIST_HEAD_INIT, + .insn_size = MAX_INSN_SIZE, + .nr_garbage = 0, +}; + +static int collect_garbage_slots(struct kprobe_insn_page_list *plist); /** - * get_insn_slot() - Find a slot on an executable page for an instruction. + * __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. */ -kprobe_opcode_t __kprobes *get_insn_slot(void) +kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_page_list *plist) { struct kprobe_insn_page *kip; struct hlist_node *pos; + int max_insn = INSNS_PER_PAGE(plist->insn_size); retry: - hlist_for_each(pos, &kprobe_insn_pages) { + hlist_for_each(pos, &plist->list) { kip = hlist_entry(pos, struct kprobe_insn_page, hlist); - if (kip->nused < INSNS_PER_PAGE) { + if (kip->nused < max_insn) { int i; - for (i = 0; i < INSNS_PER_PAGE; i++) { + for (i = 0; i < max_insn; i++) { if (!kip->slot_used[i]) { kip->slot_used[i] = 1; kip->nused++; - return kip->insns + (i * MAX_INSN_SIZE); + return kip->insns + + (i * plist->insn_size); } } /* Surprise! No unused slots. Fix kip->nused. */ - kip->nused = INSNS_PER_PAGE; + kip->nused = max_insn; } } /* If there are any garbage slots, collect it and try again. */ - if (kprobe_garbage_slots && collect_garbage_slots() == 0) { + if (plist->nr_garbage > 0 && collect_garbage_slots(plist) == 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); + kip = kmalloc(sizeof(struct kprobe_insn_page) + + sizeof(char) * (max_insn - 1), + GFP_KERNEL); if (!kip) { return NULL; } @@ -138,8 +146,8 @@ return NULL; } INIT_HLIST_NODE(&kip->hlist); - hlist_add_head(&kip->hlist, &kprobe_insn_pages); - memset(kip->slot_used, 0, INSNS_PER_PAGE); + hlist_add_head(&kip->hlist, &plist->list); + memset(kip->slot_used, 0, max_insn); kip->slot_used[0] = 1; kip->nused = 1; kip->ngarbage = 0; @@ -147,7 +155,8 @@ } /* Return 1 if all garbages are collected, otherwise 0. */ -static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx) +static int __kprobes collect_one_slot(struct kprobe_insn_page_list *plist, + struct kprobe_insn_page *kip, int idx) { kip->slot_used[idx] = 0; kip->nused--; @@ -159,10 +168,10 @@ * next time somebody inserts a probe. */ hlist_del(&kip->hlist); - if (hlist_empty(&kprobe_insn_pages)) { + if (hlist_empty(&plist->list)) { INIT_HLIST_NODE(&kip->hlist); hlist_add_head(&kip->hlist, - &kprobe_insn_pages); + &plist->list); return 1; } else { module_free(NULL, kip->insns); @@ -172,10 +181,12 @@ return 0; } -static int __kprobes collect_garbage_slots(void) +static int __kprobes + collect_garbage_slots(struct kprobe_insn_page_list *plist) { struct kprobe_insn_page *kip; struct hlist_node *pos, *next; + int max_insn = INSNS_PER_PAGE(plist->insn_size); int ret = -1; #if defined(CONFIG_PREEMPT) && defined(CONFIG_PM) @@ -183,20 +194,20 @@ if (freeze_processes() != 0) goto thaw_all; #endif - hlist_for_each_safe(pos, next, &kprobe_insn_pages) { + hlist_for_each_safe(pos, next, &plist->list) { int i; kip = hlist_entry(pos, struct kprobe_insn_page, hlist); 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 < max_insn; i++) { if (kip->slot_used[i] == -1 && - collect_one_slot(kip, i)) + collect_one_slot(plist, kip, i)) goto collected; } } collected: - kprobe_garbage_slots = 0; + plist->nr_garbage = 0; ret = 0; #if defined(CONFIG_PREEMPT) && defined(CONFIG_PM) thaw_all: @@ -205,29 +216,41 @@ return ret; } -void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty) +void __kprobes __free_insn_slot(struct kprobe_insn_page_list *plist, + kprobe_opcode_t * slot, int dirty) { struct kprobe_insn_page *kip; struct hlist_node *pos; + int max_insn = INSNS_PER_PAGE(plist->insn_size); - hlist_for_each(pos, &kprobe_insn_pages) { + hlist_for_each(pos, &plist->list) { kip = hlist_entry(pos, struct kprobe_insn_page, hlist); if (kip->insns <= slot && - slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) { - int i = (slot - kip->insns) / MAX_INSN_SIZE; + slot < kip->insns + (max_insn * plist->insn_size)) { + int i = (slot - kip->insns) / plist->insn_size; if (dirty) { kip->slot_used[i] = -1; kip->ngarbage++; } else { - collect_one_slot(kip, i); + collect_one_slot(plist, kip, i); break; } } } - if (dirty && (++kprobe_garbage_slots > INSNS_PER_PAGE)) { - collect_garbage_slots(); + if (dirty && (++plist->nr_garbage > max_insn)) { + collect_garbage_slots(plist); } } + +kprobe_opcode_t __kprobes *get_insn_slot(void) +{ + return __get_insn_slot(&kprobe_insn_pages); +} + +void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty) +{ + __free_insn_slot(&kprobe_insn_pages, slot, dirty); +} #endif /* We have preemption disabled.. so it is safe to use __ versions */