* [Patch 0/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1
@ 2005-10-27 13:22 Masami Hiramatsu
2005-10-27 13:26 ` [Patch 1/4][Djprobe] " Masami Hiramatsu
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Masami Hiramatsu @ 2005-10-27 13:22 UTC (permalink / raw)
To: systemtap, ananth, Keshavamurthy, Anil S
Cc: sugita, Satoshi Oshima, Hideo Aoki
Hi,
I developed new four patches of djprobe for linux-2.6.14-rc5-mm1.
I took advices described below about previous patches in these
patches.
New features:
- separate djprobe code from */kprobe.{c,h}
- use hash table to find the djprobe instance in specified area.
- use wait_event() to wait for safety check worker.
- move some members of djprobe structure to arguments of
register_djprobe() function.
- support lockless kprobe implementation.
TODO:
- support architecture transparent interface.
(Djprobe interface emulated by kprobes)
- kprobe interoperability (coexistance in same address)
- support other architectures
patch 1: Introduce a instruction slot management structure to
handle different size slots.
patch 2: Djprobe core patch.
patch 3: Djprobe i386 patch.
Also, I developed a testing patch of bulk registration interface.
patch 4: Testing patch of bulk interface for review.
If they are good enough, I will post first 3 patches (except the
bulk patch) to LKML.
Best Regards,
--
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: hiramatu@sdl.hitachi.co.jp
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch 1/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1
2005-10-27 13:22 [Patch 0/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1 Masami Hiramatsu
@ 2005-10-27 13:26 ` Masami Hiramatsu
2005-10-27 13:28 ` [Patch 2/4][Djprobe] " Masami Hiramatsu
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Masami Hiramatsu @ 2005-10-27 13:26 UTC (permalink / raw)
To: systemtap, ananth, Keshavamurthy, Anil S
Cc: sugita, Satoshi Oshima, Hideo Aoki
Hi,
This patch enables get_insn_slot() to handle slots
that have different size.
It needs for supporting djprobe on NX bit.
--
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: hiramatu@sdl.hitachi.co.jp
include/linux/kprobes.h | 5 ++++
kernel/kprobes.c | 58 +++++++++++++++++++++++++++++++-----------------
2 files changed, 43 insertions(+), 20 deletions(-)
diff -Narup linux-2.6.14-rc5-mm1/include/linux/kprobes.h linux-2.6.14-rc5-mm1.djp.1/include/linux/kprobes.h
--- linux-2.6.14-rc5-mm1/include/linux/kprobes.h 2005-10-25 11:29:02.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.1/include/linux/kprobes.h 2005-10-25 13:11:26.000000000 +0900
@@ -147,6 +147,11 @@ struct kretprobe_instance {
struct task_struct *task;
};
+struct kprobe_insn_page_list {
+ struct hlist_head list;
+ int insn_size; /* size of an instruction slot */
+};
+
#ifdef CONFIG_KPROBES
extern spinlock_t kretprobe_lock;
extern int arch_prepare_kprobe(struct kprobe *p);
diff -Narup linux-2.6.14-rc5-mm1/kernel/kprobes.c linux-2.6.14-rc5-mm1.djp.1/kernel/kprobes.c
--- linux-2.6.14-rc5-mm1/kernel/kprobes.c 2005-10-25 11:29:02.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.1/kernel/kprobes.c 2005-10-25 13:13:58.000000000 +0900
@@ -58,44 +58,50 @@ static DEFINE_PER_CPU(struct kprobe *, k
* 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;
+ char slot_used[1];
};
-static struct hlist_head kprobe_insn_pages;
+static struct kprobe_insn_page_list kprobe_insn_pages = {
+ HLIST_HEAD_INIT, MAX_INSN_SIZE
+};
/**
- * 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 *pages)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
+ int ninsns = INSNS_PER_PAGE(pages->insn_size);
- hlist_for_each(pos, &kprobe_insn_pages) {
+ hlist_for_each(pos, &pages->list) {
kip = hlist_entry(pos, struct kprobe_insn_page, hlist);
- if (kip->nused < INSNS_PER_PAGE) {
+ if (kip->nused < ninsns) {
int i;
- for (i = 0; i < INSNS_PER_PAGE; i++) {
+ for (i = 0; i < ninsns; i++) {
if (!kip->slot_used[i]) {
kip->slot_used[i] = 1;
kip->nused++;
- return kip->insns + (i * MAX_INSN_SIZE);
+ return kip->insns +
+ (i * pages->insn_size);
}
}
/* Surprise! No unused slots. Fix kip->nused. */
- kip->nused = INSNS_PER_PAGE;
+ kip->nused = ninsns;
}
}
- /* 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. Use slot 0. */
+ kip = kmalloc(sizeof(struct kprobe_insn_page) +
+ sizeof(char) * (ninsns - 1), GFP_ATOMIC);
if (!kip) {
return NULL;
}
@@ -111,23 +117,25 @@ kprobe_opcode_t __kprobes *get_insn_slot
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, &pages->list);
+ memset(kip->slot_used, 0, ninsns);
kip->slot_used[0] = 1;
kip->nused = 1;
return kip->insns;
}
-void __kprobes free_insn_slot(kprobe_opcode_t *slot)
+void __kprobes __free_insn_slot(struct kprobe_insn_page_list *pages,
+ kprobe_opcode_t * slot)
{
struct kprobe_insn_page *kip;
struct hlist_node *pos;
+ int ninsns = INSNS_PER_PAGE(pages->insn_size);
- hlist_for_each(pos, &kprobe_insn_pages) {
+ hlist_for_each(pos, &pages->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 + (ninsns * pages->insn_size)) {
+ int i = (slot - kip->insns) / pages->insn_size;
kip->slot_used[i] = 0;
kip->nused--;
if (kip->nused == 0) {
@@ -138,10 +146,10 @@ void __kprobes free_insn_slot(kprobe_opc
* next time somebody inserts a probe.
*/
hlist_del(&kip->hlist);
- if (hlist_empty(&kprobe_insn_pages)) {
+ if (hlist_empty(&pages->list)) {
INIT_HLIST_NODE(&kip->hlist);
hlist_add_head(&kip->hlist,
- &kprobe_insn_pages);
+ &pages->list);
} else {
module_free(NULL, kip->insns);
kfree(kip);
@@ -152,6 +160,16 @@ void __kprobes free_insn_slot(kprobe_opc
}
}
+kprobe_opcode_t __kprobes *get_insn_slot(void)
+{
+ return __get_insn_slot(&kprobe_insn_pages);
+}
+
+void __kprobes free_insn_slot(kprobe_opcode_t * slot)
+{
+ __free_insn_slot(&kprobe_insn_pages, slot);
+}
+
/* We have preemption disabled.. so it is safe to use __ versions */
static inline void set_kprobe_instance(struct kprobe *kp)
{
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch 2/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1
2005-10-27 13:22 [Patch 0/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1 Masami Hiramatsu
2005-10-27 13:26 ` [Patch 1/4][Djprobe] " Masami Hiramatsu
@ 2005-10-27 13:28 ` Masami Hiramatsu
2005-10-27 13:30 ` [Patch 3/4][Djprobe] " Masami Hiramatsu
2005-10-27 13:31 ` [Patch 4/4][Djprobe][testing] " Masami Hiramatsu
3 siblings, 0 replies; 5+ messages in thread
From: Masami Hiramatsu @ 2005-10-27 13:28 UTC (permalink / raw)
To: systemtap, ananth, Keshavamurthy, Anil S
Cc: sugita, Satoshi Oshima, Hideo Aoki
Hi,
This patch is an architecture common code of djprobe.
The djprobe codes are separated from kprobe.{c,h}
--
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: hiramatu@sdl.hitachi.co.jp
include/linux/djprobe.h | 80 +++++++++++++++
include/linux/kprobes.h | 4
kernel/Makefile | 1
kernel/djprobe.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++
kernel/kprobes.c | 8 +
5 files changed, 345 insertions(+), 1 deletion(-)
diff -Narup linux-2.6.14-rc5-mm1.djp.1/include/linux/djprobe.h linux-2.6.14-rc5-mm1.djp.2/include/linux/djprobe.h
--- linux-2.6.14-rc5-mm1.djp.1/include/linux/djprobe.h 1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.2/include/linux/djprobe.h 2005-10-26 15:52:22.000000000 +0900
@@ -0,0 +1,80 @@
+#ifndef _LINUX_DJPROBE_H
+#define _LINUX_DJPROBE_H
+/*
+ * Kernel Direct Jump Probe (Djprobe)
+ * include/linux/djprobe.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Hitachi, Ltd. 2005
+ *
+ * 2005-Aug Created by Masami HIRAMATSU <hiramatu@sdl.hitachi.co.jp>
+ * Initial implementation of Direct jump probe (djprobe)
+ * to reduce overhead.
+ */
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/smp.h>
+#include <linux/kprobes.h>
+#include <asm/djprobe.h>
+
+struct djprobe;
+/* djprobe's instance (internal use)*/
+struct djprobe_instance {
+ struct list_head plist; /* list of djprobes for multiprobe support */
+ struct arch_djprobe_stub stub;
+ struct kprobe kp;
+ struct hlist_node hlist; /* list of djprobe_instances */
+};
+#define DJPI_EMPTY(djpi) (list_empty(&djpi->plist))
+
+struct djprobe;
+typedef void (*djprobe_handler_t) (struct djprobe *, struct pt_regs *);
+/*
+ * Direct Jump probe interface structure
+ */
+struct djprobe {
+ /* list of djprobes */
+ struct list_head plist;
+
+ /* probing handler (pre-executed) */
+ djprobe_handler_t handler;
+
+ /* pointer for instance */
+ struct djprobe_instance *inst;
+};
+
+#ifdef CONFIG_DJPROBE
+extern int arch_prepare_djprobe_instance(struct djprobe_instance *djpi,
+ unsigned long size);
+extern int djprobe_pre_handler(struct kprobe *, struct pt_regs *);
+extern void djprobe_post_handler(struct kprobe *, struct pt_regs *,
+ unsigned long);
+extern void arch_install_djprobe_instance(struct djprobe_instance *djpi);
+extern void arch_uninstall_djprobe_instance(struct djprobe_instance *djpi);
+struct djprobe_instance *__kprobes get_djprobe_instance(void *addr, int size);
+
+int register_djprobe(struct djprobe *p, void *addr, int size);
+void unregister_djprobe(struct djprobe *p);
+#else /* CONFIG_DJPROBE */
+static inline int register_djprobe(struct djprobe *p)
+{
+ return -ENOSYS;
+}
+static inline void unregister_djprobe(struct djprobe *p)
+{
+}
+#endif /* CONFIG_DJPROBE */
+#endif /* _LINUX_DJPROBE_H */
diff -Narup linux-2.6.14-rc5-mm1.djp.1/include/linux/kprobes.h linux-2.6.14-rc5-mm1.djp.2/include/linux/kprobes.h
--- linux-2.6.14-rc5-mm1.djp.1/include/linux/kprobes.h 2005-10-25 13:11:26.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.2/include/linux/kprobes.h 2005-10-25 13:32:59.000000000 +0900
@@ -163,10 +163,14 @@ extern int arch_init_kprobes(void);
extern void show_registers(struct pt_regs *regs);
extern kprobe_opcode_t *get_insn_slot(void);
extern void free_insn_slot(kprobe_opcode_t *slot);
+extern kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_page_list *pages);
+extern void __free_insn_slot(struct kprobe_insn_page_list *pages,
+ kprobe_opcode_t * slot);
/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */
struct kprobe *get_kprobe(void *addr);
struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
+int in_kprobes_functions(unsigned long addr);
/* kprobe_running() will just return the current_kprobe on this CPU */
static inline struct kprobe *kprobe_running(void)
diff -Narup linux-2.6.14-rc5-mm1.djp.1/kernel/djprobe.c linux-2.6.14-rc5-mm1.djp.2/kernel/djprobe.c
--- linux-2.6.14-rc5-mm1.djp.1/kernel/djprobe.c 1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.2/kernel/djprobe.c 2005-10-27 11:59:10.000000000 +0900
@@ -0,0 +1,253 @@
+/*
+ * Kernel Direct Jump Probe (Djprobe)
+ * kernel/djprobes.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Hitachi, Ltd. 2005
+ *
+ * 2005-Aug Created by Masami HIRAMATSU <hiramatu@sdl.hitachi.co.jp>
+ * Initial implementation of Direct jump probe (djprobe)
+ * to reduce overhead.
+ */
+#include <linux/djprobe.h>
+#include <linux/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <asm-generic/sections.h>
+#include <asm/cacheflush.h>
+#include <asm/errno.h>
+
+#include <linux/cpu.h>
+#include <linux/percpu.h>
+#include <asm/semaphore.h>
+
+/*
+ * The djprobe do not refer instances list when probe function called.
+ * This list is operated on registering and unregistering djprobe.
+ */
+#define DJPROBE_BLOCK_BITS 6
+#define DJPROBE_BLOCK_SIZE (1 << DJPROBE_BLOCK_BITS)
+#define DJPROBE_HASH_BITS 8
+#define DJPROBE_TABLE_SIZE (1 << DJPROBE_HASH_BITS)
+#define DJPROBE_TABLE_MASK (DJPROBE_TABLE_SIZE - 1)
+
+/* djprobe instance hash table */
+static struct hlist_head djprobe_inst_table[DJPROBE_TABLE_SIZE];
+
+#define hash_djprobe(key) \
+ (((unsigned long)(key) >> DJPROBE_BLOCK_BITS) & DJPROBE_TABLE_MASK)
+
+static DECLARE_MUTEX(djprobe_mutex);
+static DEFINE_PER_CPU(struct work_struct, djprobe_works);
+static DECLARE_WAIT_QUEUE_HEAD(djprobe_wqh);
+static atomic_t djprobe_count = ATOMIC_INIT(0);
+
+/* Instruction pages for djprobe's stub code */
+static struct kprobe_insn_page_list djprobe_insn_pages = {
+ HLIST_HEAD_INIT, 0
+};
+
+static inline void __free_djprobe_instance(struct djprobe_instance *djpi)
+{
+ hlist_del(&djpi->hlist);
+ if (djpi->kp.addr) {
+ unregister_kprobe(&(djpi->kp));
+ }
+ if (djpi->stub.insn)
+ __free_insn_slot(&djprobe_insn_pages, djpi->stub.insn);
+ kfree(djpi);
+}
+
+static inline
+ struct djprobe_instance *__create_djprobe_instance(struct djprobe *djp,
+ void *addr, int size)
+{
+ struct djprobe_instance *djpi;
+ /* allocate a new instance */
+ djpi = kcalloc(1, sizeof(struct djprobe_instance), GFP_ATOMIC);
+ if (djpi == NULL) {
+ goto out;
+ }
+ /* allocate stub */
+ djpi->stub.insn = __get_insn_slot(&djprobe_insn_pages);
+ if (djpi->stub.insn == NULL) {
+ __free_djprobe_instance(djpi);
+ djpi = NULL;
+ goto out;
+ }
+
+ /* attach */
+ djp->inst = djpi;
+ INIT_LIST_HEAD(&djpi->plist);
+ list_add_rcu(&djp->plist, &djpi->plist);
+ djpi->kp.addr = addr;
+ djpi->kp.pre_handler = djprobe_pre_handler;
+ djpi->kp.post_handler = djprobe_post_handler;
+ arch_prepare_djprobe_instance(djpi, size);
+
+ INIT_HLIST_NODE(&djpi->hlist);
+ hlist_add_head(&djpi->hlist, &djprobe_inst_table[hash_djprobe(addr)]);
+ out:
+ return djpi;
+}
+
+static struct djprobe_instance *__kprobes __get_djprobe_instance(void *addr,
+ int size)
+{
+ struct djprobe_instance *djpi;
+ struct hlist_node *node;
+ unsigned long idx, eidx;
+
+ idx = hash_djprobe(addr - ARCH_STUB_INSN_MAX);
+ eidx = ((hash_djprobe(addr + size) + 1) & DJPROBE_TABLE_MASK);
+ do {
+ hlist_for_each_entry(djpi, node, &djprobe_inst_table[idx],
+ hlist) {
+ if (((long)addr <
+ (long)djpi->kp.addr + DJPI_ARCH_SIZE(djpi))
+ && ((long)djpi->kp.addr < (long)addr + size)) {
+ return djpi;
+ }
+ }
+ idx = ((idx + 1) & DJPROBE_TABLE_MASK);
+ }while (idx != eidx);
+
+ return NULL;
+}
+
+struct djprobe_instance *__kprobes get_djprobe_instance(void *addr, int size)
+{
+ struct djprobe_instance *djpi;
+ down(&djprobe_mutex);
+ djpi = __get_djprobe_instance(addr, size);
+ up(&djprobe_mutex);
+ return djpi;
+}
+
+/* This work function invoked while djprobe_mutex is locked. */
+static void __kprobes __work_check_safety(void *data)
+{
+ if (atomic_dec_and_test(&djprobe_count)) {
+ wake_up_all(&djprobe_wqh);
+ }
+}
+
+static void __kprobes __check_safety(void)
+{
+ int cpu;
+ struct work_struct *wk;
+ lock_cpu_hotplug();
+ atomic_set(&djprobe_count, num_online_cpus() - 1);
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+ wk = &per_cpu(djprobe_works, cpu);
+ INIT_WORK(wk, __work_check_safety, NULL);
+ schedule_delayed_work_on(cpu, wk, 0);
+ }
+ wait_event(djprobe_wqh, (atomic_read(&djprobe_count) == 0));
+ unlock_cpu_hotplug();
+}
+
+int __kprobes register_djprobe(struct djprobe *djp, void *addr, int size)
+{
+ struct djprobe_instance *djpi;
+ struct kprobe *kp;
+ int ret = 0, i;
+
+ BUG_ON(in_interrupt());
+
+ if (size > ARCH_STUB_INSN_MAX || size < ARCH_STUB_INSN_MIN)
+ return -EINVAL;
+
+ if ((ret = in_kprobes_functions((unsigned long)addr)) != 0)
+ return ret;
+
+ down(&djprobe_mutex);
+ INIT_LIST_HEAD(&djp->plist);
+ /* check confliction with other djprobes */
+ djpi = __get_djprobe_instance(addr, size);
+ if (djpi) {
+ if (djpi->kp.addr == addr) {
+ djp->inst = djpi; /* add to another instance */
+ list_add_rcu(&djp->plist, &djpi->plist);
+ } else {
+ ret = -EEXIST; /* other djprobes were inserted */
+ }
+ goto out;
+ }
+ djpi = __create_djprobe_instance(djp, addr, size);
+ if (djpi == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* check confliction with kprobes */
+ for (i = 0; i < size; i++) {
+ kp = get_kprobe((void *)((long)addr + i));
+ if (kp != NULL) {
+ ret = -EEXIST; /* a kprobes were inserted */
+ goto fail;
+ }
+ }
+ ret = register_kprobe(&djpi->kp);
+ if (ret < 0) {
+ fail:
+ djpi->kp.addr = NULL;
+ djp->inst = NULL;
+ list_del_rcu(&djp->plist);
+ __free_djprobe_instance(djpi);
+ } else {
+ __check_safety();
+ arch_install_djprobe_instance(djpi);
+ }
+ out:
+ up(&djprobe_mutex);
+ return ret;
+}
+
+void __kprobes unregister_djprobe(struct djprobe *djp)
+{
+ struct djprobe_instance *djpi;
+
+ BUG_ON(in_interrupt());
+
+ down(&djprobe_mutex);
+ djpi = djp->inst;
+ if (djp->plist.next == djp->plist.prev) {
+ arch_uninstall_djprobe_instance(djpi); /* this requires irq enabled */
+ list_del_rcu(&djp->plist);
+ djp->inst = NULL;
+ __check_safety();
+ __free_djprobe_instance(djpi);
+ } else {
+ list_del_rcu(&djp->plist);
+ djp->inst = NULL;
+ }
+ up(&djprobe_mutex);
+}
+
+static int __init init_djprobe(void)
+{
+ djprobe_insn_pages.insn_size = ARCH_STUB_SIZE;
+ return 0;
+}
+
+__initcall(init_djprobe);
+
+EXPORT_SYMBOL_GPL(register_djprobe);
+EXPORT_SYMBOL_GPL(unregister_djprobe);
diff -Narup linux-2.6.14-rc5-mm1.djp.1/kernel/kprobes.c linux-2.6.14-rc5-mm1.djp.2/kernel/kprobes.c
--- linux-2.6.14-rc5-mm1.djp.1/kernel/kprobes.c 2005-10-25 13:13:58.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.2/kernel/kprobes.c 2005-10-26 15:53:05.000000000 +0900
@@ -37,6 +37,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleloader.h>
+#include <linux/djprobe.h>
#include <asm-generic/sections.h>
#include <asm/cacheflush.h>
#include <asm/errno.h>
@@ -467,7 +468,7 @@ static inline void cleanup_aggr_kprobe(s
spin_unlock_irqrestore(&kprobe_lock, flags);
}
-static int __kprobes in_kprobes_functions(unsigned long addr)
+int __kprobes in_kprobes_functions(unsigned long addr)
{
if (addr >= (unsigned long)__kprobes_text_start
&& addr < (unsigned long)__kprobes_text_end)
@@ -483,6 +484,11 @@ int __kprobes register_kprobe(struct kpr
if ((ret = in_kprobes_functions((unsigned long) p->addr)) != 0)
return ret;
+#ifdef CONFIG_DJPROBE
+ if (p->pre_handler != djprobe_pre_handler &&
+ get_djprobe_instance(p->addr, 1) != NULL)
+ return -EEXIST;
+#endif /* CONFIG_DJPROBE */
if ((ret = arch_prepare_kprobe(p)) != 0)
goto rm_kprobe;
diff -Narup linux-2.6.14-rc5-mm1.djp.1/kernel/Makefile linux-2.6.14-rc5-mm1.djp.2/kernel/Makefile
--- linux-2.6.14-rc5-mm1.djp.1/kernel/Makefile 2005-10-25 11:29:02.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.2/kernel/Makefile 2005-10-25 13:22:27.000000000 +0900
@@ -27,6 +27,7 @@ obj-$(CONFIG_STOP_MACHINE) += stop_machi
obj-$(CONFIG_AUDIT) += audit.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_DJPROBE) += djprobe.o
obj-$(CONFIG_SYSFS) += ksysfs.o
obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch 3/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1
2005-10-27 13:22 [Patch 0/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1 Masami Hiramatsu
2005-10-27 13:26 ` [Patch 1/4][Djprobe] " Masami Hiramatsu
2005-10-27 13:28 ` [Patch 2/4][Djprobe] " Masami Hiramatsu
@ 2005-10-27 13:30 ` Masami Hiramatsu
2005-10-27 13:31 ` [Patch 4/4][Djprobe][testing] " Masami Hiramatsu
3 siblings, 0 replies; 5+ messages in thread
From: Masami Hiramatsu @ 2005-10-27 13:30 UTC (permalink / raw)
To: systemtap, ananth, Keshavamurthy, Anil S
Cc: sugita, Satoshi Oshima, Hideo Aoki
Hi,
This patch is an i386 architecture dependent code
of djprobe.
The djprobe codes are separated from kprobe.{c,h}
--
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: hiramatu@sdl.hitachi.co.jp
arch/i386/Kconfig | 8 +
arch/i386/kernel/Makefile | 1
arch/i386/kernel/djprobe.c | 170 ++++++++++++++++++++++++++++++++++++++++
arch/i386/kernel/stub_djprobe.S | 77 ++++++++++++++++++
include/asm-i386/djprobe.h | 56 +++++++++++++
5 files changed, 312 insertions(+)
diff -Narup linux-2.6.14-rc5-mm1.djp.2/arch/i386/Kconfig linux-2.6.14-rc5-mm1.djp.3/arch/i386/Kconfig
--- linux-2.6.14-rc5-mm1.djp.2/arch/i386/Kconfig 2005-10-25 11:28:49.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.3/arch/i386/Kconfig 2005-10-27 11:26:55.000000000 +0900
@@ -1317,6 +1317,14 @@ config KPROBES
a probepoint and specifies the callback. Kprobes is useful
for kernel debugging, non-intrusive instrumentation and testing.
If in doubt, say "N".
+
+config DJPROBE
+ bool "Direct Jump probe"
+ depends on KPROBES && !PREEMPT
+ help
+ Djprobe allows you to dynamically hook at any kernel function
+ entry points and collect the debugging or performance analysis
+ information non-disruptively.
endmenu
source "arch/i386/Kconfig.debug"
diff -Narup linux-2.6.14-rc5-mm1.djp.2/arch/i386/kernel/djprobe.c linux-2.6.14-rc5-mm1.djp.3/arch/i386/kernel/djprobe.c
--- linux-2.6.14-rc5-mm1.djp.2/arch/i386/kernel/djprobe.c 1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.3/arch/i386/kernel/djprobe.c 2005-10-26 16:14:54.000000000 +0900
@@ -0,0 +1,170 @@
+/*
+ * Kernel Direct Jump Probe (Djprobes)
+ * arch/i386/kernel/djprobe.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Hitachi, Ltd. 2005
+ *
+ * 2005-Oct Created by Masami HIRAMATSU <hiramatu@sdl.hitachi.co.jp>
+ * Initial implementation of Direct jump probe (djprobe)
+ * to reduce overhead.
+ */
+
+#include <linux/config.h>
+#include <linux/djprobe.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/preempt.h>
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/desc.h>
+#include <asm/processor.h>
+
+
+/*
+ * When kernel full preemption is enabled, we can't ensure that no threads
+ * are executing the modified code. It may be stored in the stack of the
+ * threads. In this case, the djprobe interfaces are emulated by using
+ * kprobe.
+ * When kernel full preemption is disabled, threads are scheduled
+ * from only limited addresses. So it is easy to check whether the
+ * preemption can occur in the modified code.
+ */
+
+/*
+ * On pentium series, Unsynchronized cross-modifying code
+ * operations can cause unexpected instruction execution results.
+ * So after code modified, we should synchronize it on each processor.
+ */
+static void __local_serialize_cpu(void * info)
+{
+ serialize_cpu();
+}
+
+static inline void smp_serialize_cpus(void)
+{
+ on_each_cpu(__local_serialize_cpu, NULL, 1,1);
+}
+
+/* jmp code manipulators */
+struct __arch_jmp_op {
+ char op;
+ long raddr;
+} __attribute__((packed));
+/* insert jmp code */
+static inline void __set_jmp_op(void *from, void *to, int sync)
+{
+ struct __arch_jmp_op *jop;
+ jop = (struct __arch_jmp_op *)from;
+ jop->raddr=(long)(to) - ((long)(from) + 5);
+ mb();
+ if (sync) smp_serialize_cpus();
+ jop->op = RELATIVEJUMP_INSTRUCTION;
+}
+/* switch back to the kprobe */
+static inline void __set_breakpoint_op(void *dest, void *orig)
+{
+ struct __arch_jmp_op *jop = (struct __arch_jmp_op *)dest,
+ *jop2 = (struct __arch_jmp_op *)orig;
+
+ jop->op = BREAKPOINT_INSTRUCTION;
+ jop->raddr = jop2->raddr;
+ mb();
+ smp_serialize_cpus();
+}
+
+/* djprobe call back function: called from stub code */
+static void asmlinkage djprobe_callback(struct djprobe_instance * djpi,
+ struct pt_regs *regs)
+{
+ struct djprobe *djp;
+ list_for_each_entry_rcu(djp, &djpi->plist, plist) {
+ if (djp->handler)
+ djp->handler(djp, regs);
+ }
+}
+
+/*
+ * Copy post processing instructions
+ * Target instructions MUST be relocatable.
+ */
+int __kprobes arch_prepare_djprobe_instance(struct djprobe_instance *djpi,
+ unsigned long size)
+{
+ kprobe_opcode_t *stub;
+ stub = djpi->stub.insn;
+ djpi->stub.size = size;
+
+ /* copy arch-dep-instance from template */
+ memcpy((void*)stub, (void*)&arch_tmpl_stub_entry, ARCH_STUB_SIZE);
+
+ /* set probe information */
+ *((long*)(stub + ARCH_STUB_VAL_IDX)) = (long)djpi;
+ /* set probe function */
+ *((long*)(stub + ARCH_STUB_CALL_IDX)) = (long)djprobe_callback;
+
+ /* copy instructions into the middle of djporbe instance */
+ memcpy((void*)(stub + ARCH_STUB_INST_IDX),
+ (void*)djpi->kp.addr, size);
+
+ /* set returning jmp instruction at the tail of djporbe instance*/
+ __set_jmp_op(stub + ARCH_STUB_INST_IDX + size,
+ (void*)((long)djpi->kp.addr + size), 0);
+
+ return 0;
+}
+
+/* Insert "jmp" instruction into the probing point. */
+void __kprobes arch_install_djprobe_instance(struct djprobe_instance *djpi)
+{
+ __set_jmp_op((void*)djpi->kp.addr, (void*)djpi->stub.insn, 1);
+}
+
+/* Write back original instructions & kprobe */
+void __kprobes arch_uninstall_djprobe_instance(struct djprobe_instance *djpi)
+{
+ kprobe_opcode_t *stub;
+ stub = &djpi->stub.insn[ARCH_STUB_INST_IDX];
+ __set_breakpoint_op((void*)djpi->kp.addr, (void*)stub);
+}
+
+static DEFINE_SPINLOCK(djprobe_handler_lock);
+
+/* djprobe handler : switch to a bypass code */
+int __kprobes djprobe_pre_handler(struct kprobe * kp, struct pt_regs * regs)
+{
+ struct djprobe_instance *djpi =
+ container_of(kp,struct djprobe_instance, kp);
+ kprobe_opcode_t *stub = djpi->stub.insn;
+
+ spin_lock(&djprobe_handler_lock);
+ if (DJPI_EMPTY(djpi)) {
+ kp->ainsn.insn[0] = kp->opcode;
+ return 0;
+ } else {
+ regs->eip = (unsigned long)stub;
+ regs->eflags |= TF_MASK;
+ regs->eflags &= ~IF_MASK;
+ kp->ainsn.insn[0] = RETURN_INSTRUCTION;
+ return 1; /* already prepared */
+ }
+}
+
+void __kprobes djprobe_post_handler(struct kprobe * kp, struct pt_regs * regs,
+ unsigned long flags)
+{
+ spin_unlock(&djprobe_handler_lock);
+}
diff -Narup linux-2.6.14-rc5-mm1.djp.2/arch/i386/kernel/Makefile linux-2.6.14-rc5-mm1.djp.3/arch/i386/kernel/Makefile
--- linux-2.6.14-rc5-mm1.djp.2/arch/i386/kernel/Makefile 2005-10-25 11:28:49.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.3/arch/i386/kernel/Makefile 2005-10-25 14:39:12.000000000 +0900
@@ -29,6 +29,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o
obj-$(CONFIG_X86_NUMAQ) += numaq.o
obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_DJPROBE) += stub_djprobe.o djprobe.o
obj-$(CONFIG_MODULES) += module.o
obj-y += sysenter.o vsyscall.o
obj-$(CONFIG_ACPI_SRAT) += srat.o
diff -Narup linux-2.6.14-rc5-mm1.djp.2/arch/i386/kernel/stub_djprobe.S linux-2.6.14-rc5-mm1.djp.3/arch/i386/kernel/stub_djprobe.S
--- linux-2.6.14-rc5-mm1.djp.2/arch/i386/kernel/stub_djprobe.S 1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.3/arch/i386/kernel/stub_djprobe.S 2005-10-25 14:39:12.000000000 +0900
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/i386/stub_djprobe.S
+ *
+ * Copyright (C) HITACHI,LTD. 2005
+ * Created by Masami Hiramatsu <hiramatu@sdl.hitachi.co.jp>
+ */
+
+#include <linux/config.h>
+
+# jmp into this function from other functions.
+.global arch_tmpl_stub_entry
+arch_tmpl_stub_entry:
+ nop
+ subl $8, %esp #skip segment registers.
+ pushf
+ subl $20, %esp #skip segment registers.
+ pushl %eax
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+
+ movl %esp, %eax
+ pushl %eax
+ addl $60, %eax
+ movl %eax, 56(%esp)
+.global arch_tmpl_stub_val
+arch_tmpl_stub_val:
+ movl $0xffffffff, %eax
+ pushl %eax
+.global arch_tmpl_stub_call
+arch_tmpl_stub_call:
+ movl $0xffffffff, %eax
+ call *%eax
+ addl $8, %esp
+
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+ popl %eax
+ addl $20, %esp
+ popf
+ addl $8, %esp
+.global arch_tmpl_stub_inst
+arch_tmpl_stub_inst:
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+.global arch_tmpl_stub_end
+arch_tmpl_stub_end:
diff -Narup linux-2.6.14-rc5-mm1.djp.2/include/asm-i386/djprobe.h linux-2.6.14-rc5-mm1.djp.3/include/asm-i386/djprobe.h
--- linux-2.6.14-rc5-mm1.djp.2/include/asm-i386/djprobe.h 1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.3/include/asm-i386/djprobe.h 2005-10-25 14:39:12.000000000 +0900
@@ -0,0 +1,56 @@
+#ifndef _ASM_DJPROBE_H
+#define _ASM_DJPROBE_H
+/*
+ * Kernel Direct Jump Probe (Djprobe)
+ * include/asm-i386/djprobe.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Hitachi, Ltd. 2005
+ *
+ * 2005-Aug Created by Masami HIRAMATSU <hiramatu@sdl.hitachi.co.jp>
+ * Initial implementation of Direct jump probe (djprobe)
+ * to reduce overhead.
+ */
+
+#define RELATIVEJUMP_INSTRUCTION 0xe9
+#define RETURN_INSTRUCTION 0xc3
+
+#ifndef CONFIG_PREEMPT
+#define ARCH_SUPPORTS_DJPROBES
+#endif /* CONFIG_PREEMPT */
+
+/* stub template code */
+extern kprobe_opcode_t arch_tmpl_stub_entry;
+extern kprobe_opcode_t arch_tmpl_stub_val;
+extern kprobe_opcode_t arch_tmpl_stub_call;
+extern kprobe_opcode_t arch_tmpl_stub_inst;
+extern kprobe_opcode_t arch_tmpl_stub_end;
+
+#define ARCH_STUB_VAL_IDX ((long)&arch_tmpl_stub_val - (long)&arch_tmpl_stub_entry + 1)
+#define ARCH_STUB_CALL_IDX ((long)&arch_tmpl_stub_call - (long)&arch_tmpl_stub_entry + 1)
+#define ARCH_STUB_INST_IDX ((long)&arch_tmpl_stub_inst - (long)&arch_tmpl_stub_entry)
+#define ARCH_STUB_SIZE ((long)&arch_tmpl_stub_end - (long)&arch_tmpl_stub_entry)
+
+#define ARCH_STUB_INSN_MAX 20
+#define ARCH_STUB_INSN_MIN 5
+
+struct arch_djprobe_stub {
+ kprobe_opcode_t *insn;
+ int size;
+};
+#define DJPI_ARCH_SIZE(djpi) (djpi->stub.size)
+
+#endif /* _ASM_DJPROBE_H */
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch 4/4][Djprobe][testing] Djprobe update for linux-2.6.14-rc5-mm1
2005-10-27 13:22 [Patch 0/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1 Masami Hiramatsu
` (2 preceding siblings ...)
2005-10-27 13:30 ` [Patch 3/4][Djprobe] " Masami Hiramatsu
@ 2005-10-27 13:31 ` Masami Hiramatsu
3 siblings, 0 replies; 5+ messages in thread
From: Masami Hiramatsu @ 2005-10-27 13:31 UTC (permalink / raw)
To: systemtap, ananth, Keshavamurthy, Anil S
Cc: sugita, Satoshi Oshima, Hideo Aoki
Hi,
This patch provides bulk registration/unregistration interfaces
to djprobe.
--
Masami HIRAMATSU
2nd Research Dept.
Hitachi, Ltd., Systems Development Laboratory
E-mail: hiramatu@sdl.hitachi.co.jp
include/linux/djprobe.h | 20 ++++++++++++
kernel/djprobe.c | 80 +++++++++++++++++++++++++++++++++++++++---------
2 files changed, 86 insertions(+), 14 deletions(-)
diff -Narup linux-2.6.14-rc5-mm1.djp.3/include/linux/djprobe.h linux-2.6.14-rc5-mm1.djp.4/include/linux/djprobe.h
--- linux-2.6.14-rc5-mm1.djp.3/include/linux/djprobe.h 2005-10-26 15:52:22.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.4/include/linux/djprobe.h 2005-10-27 11:16:31.000000000 +0900
@@ -56,6 +56,12 @@ struct djprobe {
struct djprobe_instance *inst;
};
+struct djprobe_param {
+ struct djprobe *djp;
+ void *addr;
+ int size;
+};
+
#ifdef CONFIG_DJPROBE
extern int arch_prepare_djprobe_instance(struct djprobe_instance *djpi,
unsigned long size);
@@ -67,14 +73,28 @@ extern void arch_uninstall_djprobe_insta
struct djprobe_instance *__kprobes get_djprobe_instance(void *addr, int size);
int register_djprobe(struct djprobe *p, void *addr, int size);
+void register_bulk_djprobes(int nr_probes, struct djprobe_param params[]);
void unregister_djprobe(struct djprobe *p);
+void unregister_bulk_djprobes(int nr_probes, struct djprobe_param params[]);
#else /* CONFIG_DJPROBE */
static inline int register_djprobe(struct djprobe *p)
{
return -ENOSYS;
}
+static inline void register_bulk_djprobes(int nr_probes,
+ struct djprobe_param params[])
+{
+ int i;
+ for (i=0;i<nr_probes;i++)
+ params[i].djp->inst = NULL;
+}
+
static inline void unregister_djprobe(struct djprobe *p)
{
}
+static inline void unregister_bulk_djprobes(int nr_probes,
+ struct djprobe_param params[])
+{
+}
#endif /* CONFIG_DJPROBE */
#endif /* _LINUX_DJPROBE_H */
diff -Narup linux-2.6.14-rc5-mm1.djp.3/kernel/djprobe.c linux-2.6.14-rc5-mm1.djp.4/kernel/djprobe.c
--- linux-2.6.14-rc5-mm1.djp.3/kernel/djprobe.c 2005-10-27 11:59:10.000000000 +0900
+++ linux-2.6.14-rc5-mm1.djp.4/kernel/djprobe.c 2005-10-27 12:01:54.000000000 +0900
@@ -163,7 +163,8 @@ static void __kprobes __check_safety(voi
unlock_cpu_hotplug();
}
-int __kprobes register_djprobe(struct djprobe *djp, void *addr, int size)
+static int __kprobes __register_djprobe(struct djprobe *djp, void *addr,
+ int size)
{
struct djprobe_instance *djpi;
struct kprobe *kp;
@@ -177,7 +178,6 @@ int __kprobes register_djprobe(struct dj
if ((ret = in_kprobes_functions((unsigned long)addr)) != 0)
return ret;
- down(&djprobe_mutex);
INIT_LIST_HEAD(&djp->plist);
/* check confliction with other djprobes */
djpi = __get_djprobe_instance(addr, size);
@@ -211,32 +211,82 @@ int __kprobes register_djprobe(struct dj
djp->inst = NULL;
list_del_rcu(&djp->plist);
__free_djprobe_instance(djpi);
- } else {
- __check_safety();
- arch_install_djprobe_instance(djpi);
}
out:
+ return ret;
+}
+
+int __kprobes register_djprobe(struct djprobe *djp, void *addr, int size)
+{
+ int ret;
+ down(&djprobe_mutex);
+ ret = __register_djprobe(djp, addr, size);
+ if (ret == 0) {
+ __check_safety();
+ arch_install_djprobe_instance(djp->inst);
+ }
up(&djprobe_mutex);
return ret;
}
-void __kprobes unregister_djprobe(struct djprobe *djp)
+void __kprobes register_bulk_djprobes(int nr_probes,
+ struct djprobe_param params[])
{
- struct djprobe_instance *djpi;
+ int i;
+ down(&djprobe_mutex);
+ for (i = 0; i < nr_probes; i++) {
+ params[i].djp->inst = NULL;
+ __register_djprobe(params[i].djp, params[i].addr,
+ params[i].size);
+ }
+ __check_safety();
+ for (i = 0; i < nr_probes; i++) {
+ if (params[i].djp->inst)
+ arch_install_djprobe_instance(params[i].djp->inst);
+ }
+ up(&djprobe_mutex);
+}
+static void __kprobes __unregister_djprobe(struct djprobe *djp)
+{
BUG_ON(in_interrupt());
+ if (djp->plist.next == djp->plist.prev) {
+ /* this requires irq enabled */
+ arch_uninstall_djprobe_instance(djp->inst);
+ }
+ list_del_rcu(&djp->plist);
+ djp->inst = NULL;
+}
+
+void __kprobes unregister_djprobe(struct djprobe *djp)
+{
+ struct djprobe_instance *djpi;
down(&djprobe_mutex);
djpi = djp->inst;
- if (djp->plist.next == djp->plist.prev) {
- arch_uninstall_djprobe_instance(djpi); /* this requires irq enabled */
- list_del_rcu(&djp->plist);
- djp->inst = NULL;
+ __unregister_djprobe(djp);
+ if (DJPI_EMPTY(djpi)) {
__check_safety();
__free_djprobe_instance(djpi);
- } else {
- list_del_rcu(&djp->plist);
- djp->inst = NULL;
+ }
+ up(&djprobe_mutex);
+}
+
+void __kprobes unregister_bulk_djprobes(int nr_probes,
+ struct djprobe_param params[])
+{
+ struct djprobe_instance *djpi;
+ int i;
+ down(&djprobe_mutex);
+ for (i = 0; i < nr_probes; i++) {
+ __unregister_djprobe(params[i].djp);
+ }
+ __check_safety();
+ for (i = 0; i < nr_probes; i++) {
+ djpi = __get_djprobe_instance(params[i].addr, 1);
+ if (djpi && DJPI_EMPTY(djpi)) {
+ __free_djprobe_instance(djpi);
+ }
}
up(&djprobe_mutex);
}
@@ -250,4 +300,6 @@ static int __init init_djprobe(void)
__initcall(init_djprobe);
EXPORT_SYMBOL_GPL(register_djprobe);
+EXPORT_SYMBOL_GPL(register_bulk_djprobes);
EXPORT_SYMBOL_GPL(unregister_djprobe);
+EXPORT_SYMBOL_GPL(unregister_bulk_djprobes);
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2005-10-27 13:31 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-27 13:22 [Patch 0/4][Djprobe] Djprobe update for linux-2.6.14-rc5-mm1 Masami Hiramatsu
2005-10-27 13:26 ` [Patch 1/4][Djprobe] " Masami Hiramatsu
2005-10-27 13:28 ` [Patch 2/4][Djprobe] " Masami Hiramatsu
2005-10-27 13:30 ` [Patch 3/4][Djprobe] " Masami Hiramatsu
2005-10-27 13:31 ` [Patch 4/4][Djprobe][testing] " Masami Hiramatsu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).