Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 121045
b: refs/heads/master
c: fd3fdf1
h: refs/heads/master
i:
  121043: dae6a0e
v: v3
  • Loading branch information
Pekka Paalanen authored and Ingo Molnar committed Oct 27, 2008
1 parent e8ca8e0 commit af4fccd
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5d9881ea1440f046ee851bbaa2a2962543336a11
refs/heads/master: fd3fdf11d3c649769e02459c5f1b8081a15e9007
4 changes: 0 additions & 4 deletions trunk/arch/x86/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,10 @@ config IOMMU_LEAK
Add a simple leak tracer to the IOMMU code. This is useful when you
are debugging a buggy device driver that leaks IOMMU mappings.

config MMIOTRACE_HOOKS
bool

config MMIOTRACE
bool "Memory mapped IO tracing"
depends on DEBUG_KERNEL && PCI
select TRACING
select MMIOTRACE_HOOKS
help
Mmiotrace traces Memory Mapped I/O access and is meant for
debugging and reverse engineering. It is called from the ioremap
Expand Down
3 changes: 1 addition & 2 deletions trunk/arch/x86/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ obj-$(CONFIG_X86_PTDUMP) += dump_pagetables.o

obj-$(CONFIG_HIGHMEM) += highmem_32.o

obj-$(CONFIG_MMIOTRACE_HOOKS) += kmmio.o
obj-$(CONFIG_MMIOTRACE) += mmiotrace.o
mmiotrace-y := pf_in.o mmio-mod.o
mmiotrace-y := kmmio.o pf_in.o mmio-mod.o
obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o

obj-$(CONFIG_NUMA) += numa_$(BITS).o
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
{
#ifdef CONFIG_MMIOTRACE_HOOKS
#ifdef CONFIG_MMIOTRACE
if (unlikely(is_kmmio_active()))
if (kmmio_handler(regs, addr) == 1)
return -1;
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/marker.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ extern marker_probe_func __mark_empty_function;

extern void marker_probe_cb(const struct marker *mdata,
void *call_private, ...);
extern void marker_probe_cb_noarg(const struct marker *mdata,
void *call_private, ...);

/*
* Connect a probe to a marker.
Expand Down
80 changes: 52 additions & 28 deletions trunk/kernel/marker.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ static DEFINE_MUTEX(markers_mutex);
*/
#define MARKER_HASH_BITS 6
#define MARKER_TABLE_SIZE (1 << MARKER_HASH_BITS)
static struct hlist_head marker_table[MARKER_TABLE_SIZE];

/*
* Note about RCU :
Expand All @@ -65,10 +64,11 @@ struct marker_entry {
void *oldptr;
int rcu_pending;
unsigned char ptype:1;
unsigned char format_allocated:1;
char name[0]; /* Contains name'\0'format'\0' */
};

static struct hlist_head marker_table[MARKER_TABLE_SIZE];

/**
* __mark_empty_function - Empty probe callback
* @probe_private: probe private data
Expand Down Expand Up @@ -157,7 +157,7 @@ EXPORT_SYMBOL_GPL(marker_probe_cb);
*
* Should be connected to markers "MARK_NOARGS".
*/
static void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...)
void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...)
{
va_list args; /* not initialized */
char ptype;
Expand Down Expand Up @@ -197,6 +197,7 @@ static void marker_probe_cb_noarg(const struct marker *mdata, void *call_private
}
rcu_read_unlock_sched();
}
EXPORT_SYMBOL_GPL(marker_probe_cb_noarg);

static void free_old_closure(struct rcu_head *head)
{
Expand Down Expand Up @@ -415,7 +416,6 @@ static struct marker_entry *add_marker(const char *name, const char *format)
e->single.probe_private = NULL;
e->multi = NULL;
e->ptype = 0;
e->format_allocated = 0;
e->refcount = 0;
e->rcu_pending = 0;
hlist_add_head(&e->hlist, head);
Expand Down Expand Up @@ -447,8 +447,6 @@ static int remove_marker(const char *name)
if (e->single.func != __mark_empty_function)
return -EBUSY;
hlist_del(&e->hlist);
if (e->format_allocated)
kfree(e->format);
/* Make sure the call_rcu has been executed */
if (e->rcu_pending)
rcu_barrier_sched();
Expand All @@ -459,34 +457,57 @@ static int remove_marker(const char *name)
/*
* Set the mark_entry format to the format found in the element.
*/
static int marker_set_format(struct marker_entry *entry, const char *format)
static int marker_set_format(struct marker_entry **entry, const char *format)
{
entry->format = kstrdup(format, GFP_KERNEL);
if (!entry->format)
return -ENOMEM;
entry->format_allocated = 1;
struct marker_entry *e;
size_t name_len = strlen((*entry)->name) + 1;
size_t format_len = strlen(format) + 1;


e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,
GFP_KERNEL);
if (!e)
return -ENOMEM;
memcpy(&e->name[0], (*entry)->name, name_len);
e->format = &e->name[name_len];
memcpy(e->format, format, format_len);
if (strcmp(e->format, MARK_NOARGS) == 0)
e->call = marker_probe_cb_noarg;
else
e->call = marker_probe_cb;
e->single = (*entry)->single;
e->multi = (*entry)->multi;
e->ptype = (*entry)->ptype;
e->refcount = (*entry)->refcount;
e->rcu_pending = 0;
hlist_add_before(&e->hlist, &(*entry)->hlist);
hlist_del(&(*entry)->hlist);
/* Make sure the call_rcu has been executed */
if ((*entry)->rcu_pending)
rcu_barrier_sched();
kfree(*entry);
*entry = e;
trace_mark(core_marker_format, "name %s format %s",
entry->name, entry->format);
e->name, e->format);
return 0;
}

/*
* Sets the probe callback corresponding to one marker.
*/
static int set_marker(struct marker_entry *entry, struct marker *elem,
static int set_marker(struct marker_entry **entry, struct marker *elem,
int active)
{
int ret;
WARN_ON(strcmp(entry->name, elem->name) != 0);
WARN_ON(strcmp((*entry)->name, elem->name) != 0);

if (entry->format) {
if (strcmp(entry->format, elem->format) != 0) {
if ((*entry)->format) {
if (strcmp((*entry)->format, elem->format) != 0) {
printk(KERN_NOTICE
"Format mismatch for probe %s "
"(%s), marker (%s)\n",
entry->name,
entry->format,
(*entry)->name,
(*entry)->format,
elem->format);
return -EPERM;
}
Expand All @@ -502,33 +523,34 @@ static int set_marker(struct marker_entry *entry, struct marker *elem,
* pass from a "safe" callback (with argument) to an "unsafe"
* callback (does not set arguments).
*/
elem->call = entry->call;
elem->call = (*entry)->call;
/*
* Sanity check :
* We only update the single probe private data when the ptr is
* set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)
*/
WARN_ON(elem->single.func != __mark_empty_function
&& elem->single.probe_private != entry->single.probe_private
&& !elem->ptype);
elem->single.probe_private = entry->single.probe_private;
&& elem->single.probe_private
!= (*entry)->single.probe_private &&
!elem->ptype);
elem->single.probe_private = (*entry)->single.probe_private;
/*
* Make sure the private data is valid when we update the
* single probe ptr.
*/
smp_wmb();
elem->single.func = entry->single.func;
elem->single.func = (*entry)->single.func;
/*
* We also make sure that the new probe callbacks array is consistent
* before setting a pointer to it.
*/
rcu_assign_pointer(elem->multi, entry->multi);
rcu_assign_pointer(elem->multi, (*entry)->multi);
/*
* Update the function or multi probe array pointer before setting the
* ptype.
*/
smp_wmb();
elem->ptype = entry->ptype;
elem->ptype = (*entry)->ptype;
elem->state = active;

return 0;
Expand Down Expand Up @@ -572,7 +594,8 @@ void marker_update_probe_range(struct marker *begin,
for (iter = begin; iter < end; iter++) {
mark_entry = get_marker(iter->name);
if (mark_entry) {
set_marker(mark_entry, iter, !!mark_entry->refcount);
set_marker(&mark_entry, iter,
!!mark_entry->refcount);
/*
* ignore error, continue
*/
Expand Down Expand Up @@ -634,7 +657,7 @@ int marker_probe_register(const char *name, const char *format,
ret = PTR_ERR(entry);
} else if (format) {
if (!entry->format)
ret = marker_set_format(entry, format);
ret = marker_set_format(&entry, format);
else if (strcmp(entry->format, format))
ret = -EPERM;
}
Expand Down Expand Up @@ -825,6 +848,8 @@ void *marker_get_private_data(const char *name, marker_probe_func *probe,
if (!e->ptype) {
if (num == 0 && e->single.func == probe)
return e->single.probe_private;
else
break;
} else {
struct marker_probe_closure *closure;
int match = 0;
Expand All @@ -836,7 +861,6 @@ void *marker_get_private_data(const char *name, marker_probe_func *probe,
return closure[i].probe_private;
}
}
break;
}
}
return ERR_PTR(-ENOENT);
Expand Down

0 comments on commit af4fccd

Please sign in to comment.