2008-05-13 02:20:56 +07:00
|
|
|
#ifndef MMIOTRACE_H
|
|
|
|
#define MMIOTRACE_H
|
|
|
|
|
2008-05-13 02:21:03 +07:00
|
|
|
#include <linux/types.h>
|
x86: mmiotrace full patch, preview 1
kmmio.c handles the list of mmio probes with callbacks, list of traced
pages, and attaching into the page fault handler and die notifier. It
arms, traps and disarms the given pages, this is the core of mmiotrace.
mmio-mod.c is a user interface, hooking into ioremap functions and
registering the mmio probes. It also decodes the required information
from trapped mmio accesses via the pre and post callbacks in each probe.
Currently, hooking into ioremap functions works by redefining the symbols
of the target (binary) kernel module, so that it calls the traced
versions of the functions.
The most notable changes done since the last discussion are:
- kmmio.c is a built-in, not part of the module
- direct call from fault.c to kmmio.c, removing all dynamic hooks
- prepare for unregistering probes at any time
- make kmmio re-initializable and accessible to more than one user
- rewrite kmmio locking to remove all spinlocks from page fault path
Can I abuse call_rcu() like I do in kmmio.c:unregister_kmmio_probe()
or is there a better way?
The function called via call_rcu() itself calls call_rcu() again,
will this work or break? There I need a second grace period for RCU
after the first grace period for page faults.
Mmiotrace itself (mmio-mod.c) is still a module, I am going to attack
that next. At some point I will start looking into how to make mmiotrace
a tracer component of ftrace (thanks for the hint, Ingo). Ftrace should
make the user space part of mmiotracing as simple as
'cat /debug/trace/mmio > dump.txt'.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
#include <linux/list.h>
|
|
|
|
|
|
|
|
struct kmmio_probe;
|
|
|
|
struct pt_regs;
|
|
|
|
|
|
|
|
typedef void (*kmmio_pre_handler_t)(struct kmmio_probe *,
|
|
|
|
struct pt_regs *, unsigned long addr);
|
|
|
|
typedef void (*kmmio_post_handler_t)(struct kmmio_probe *,
|
|
|
|
unsigned long condition, struct pt_regs *);
|
|
|
|
|
|
|
|
struct kmmio_probe {
|
2008-05-13 02:20:57 +07:00
|
|
|
struct list_head list; /* kmmio internal list */
|
x86: mmiotrace full patch, preview 1
kmmio.c handles the list of mmio probes with callbacks, list of traced
pages, and attaching into the page fault handler and die notifier. It
arms, traps and disarms the given pages, this is the core of mmiotrace.
mmio-mod.c is a user interface, hooking into ioremap functions and
registering the mmio probes. It also decodes the required information
from trapped mmio accesses via the pre and post callbacks in each probe.
Currently, hooking into ioremap functions works by redefining the symbols
of the target (binary) kernel module, so that it calls the traced
versions of the functions.
The most notable changes done since the last discussion are:
- kmmio.c is a built-in, not part of the module
- direct call from fault.c to kmmio.c, removing all dynamic hooks
- prepare for unregistering probes at any time
- make kmmio re-initializable and accessible to more than one user
- rewrite kmmio locking to remove all spinlocks from page fault path
Can I abuse call_rcu() like I do in kmmio.c:unregister_kmmio_probe()
or is there a better way?
The function called via call_rcu() itself calls call_rcu() again,
will this work or break? There I need a second grace period for RCU
after the first grace period for page faults.
Mmiotrace itself (mmio-mod.c) is still a module, I am going to attack
that next. At some point I will start looking into how to make mmiotrace
a tracer component of ftrace (thanks for the hint, Ingo). Ftrace should
make the user space part of mmiotracing as simple as
'cat /debug/trace/mmio > dump.txt'.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
unsigned long addr; /* start location of the probe point */
|
|
|
|
unsigned long len; /* length of the probe region */
|
|
|
|
kmmio_pre_handler_t pre_handler; /* Called before addr is executed. */
|
|
|
|
kmmio_post_handler_t post_handler; /* Called after addr is executed */
|
2008-05-13 02:21:03 +07:00
|
|
|
void *private;
|
x86: mmiotrace full patch, preview 1
kmmio.c handles the list of mmio probes with callbacks, list of traced
pages, and attaching into the page fault handler and die notifier. It
arms, traps and disarms the given pages, this is the core of mmiotrace.
mmio-mod.c is a user interface, hooking into ioremap functions and
registering the mmio probes. It also decodes the required information
from trapped mmio accesses via the pre and post callbacks in each probe.
Currently, hooking into ioremap functions works by redefining the symbols
of the target (binary) kernel module, so that it calls the traced
versions of the functions.
The most notable changes done since the last discussion are:
- kmmio.c is a built-in, not part of the module
- direct call from fault.c to kmmio.c, removing all dynamic hooks
- prepare for unregistering probes at any time
- make kmmio re-initializable and accessible to more than one user
- rewrite kmmio locking to remove all spinlocks from page fault path
Can I abuse call_rcu() like I do in kmmio.c:unregister_kmmio_probe()
or is there a better way?
The function called via call_rcu() itself calls call_rcu() again,
will this work or break? There I need a second grace period for RCU
after the first grace period for page faults.
Mmiotrace itself (mmio-mod.c) is still a module, I am going to attack
that next. At some point I will start looking into how to make mmiotrace
a tracer component of ftrace (thanks for the hint, Ingo). Ftrace should
make the user space part of mmiotracing as simple as
'cat /debug/trace/mmio > dump.txt'.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
/* kmmio is active by some kmmio_probes? */
|
|
|
|
static inline int is_kmmio_active(void)
|
|
|
|
{
|
|
|
|
extern unsigned int kmmio_count;
|
|
|
|
return kmmio_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern int register_kmmio_probe(struct kmmio_probe *p);
|
|
|
|
extern void unregister_kmmio_probe(struct kmmio_probe *p);
|
|
|
|
|
|
|
|
/* Called from page fault handler. */
|
|
|
|
extern int kmmio_handler(struct pt_regs *regs, unsigned long addr);
|
|
|
|
|
2008-05-13 02:20:57 +07:00
|
|
|
#ifdef CONFIG_MMIOTRACE
|
2008-09-17 02:00:34 +07:00
|
|
|
/* Called from ioremap.c */
|
2008-05-13 02:21:03 +07:00
|
|
|
extern void mmiotrace_ioremap(resource_size_t offset, unsigned long size,
|
|
|
|
void __iomem *addr);
|
2008-05-13 02:20:57 +07:00
|
|
|
extern void mmiotrace_iounmap(volatile void __iomem *addr);
|
2008-09-17 02:00:34 +07:00
|
|
|
|
|
|
|
/* For anyone to insert markers. Remember trailing newline. */
|
|
|
|
extern int mmiotrace_printk(const char *fmt, ...)
|
|
|
|
__attribute__ ((format (printf, 1, 2)));
|
2008-05-13 02:20:57 +07:00
|
|
|
#else
|
2008-05-13 02:21:03 +07:00
|
|
|
static inline void mmiotrace_ioremap(resource_size_t offset,
|
|
|
|
unsigned long size, void __iomem *addr)
|
2008-05-13 02:20:57 +07:00
|
|
|
{
|
|
|
|
}
|
2008-05-13 02:21:03 +07:00
|
|
|
|
2008-05-13 02:20:57 +07:00
|
|
|
static inline void mmiotrace_iounmap(volatile void __iomem *addr)
|
|
|
|
{
|
|
|
|
}
|
2008-09-17 02:00:34 +07:00
|
|
|
|
|
|
|
static inline int mmiotrace_printk(const char *fmt, ...)
|
|
|
|
__attribute__ ((format (printf, 1, 0)));
|
|
|
|
|
|
|
|
static inline int mmiotrace_printk(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_MMIOTRACE */
|
2008-05-13 02:20:57 +07:00
|
|
|
|
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
enum mm_io_opcode {
|
|
|
|
MMIO_READ = 0x1, /* struct mmiotrace_rw */
|
|
|
|
MMIO_WRITE = 0x2, /* struct mmiotrace_rw */
|
|
|
|
MMIO_PROBE = 0x3, /* struct mmiotrace_map */
|
|
|
|
MMIO_UNPROBE = 0x4, /* struct mmiotrace_map */
|
2008-09-17 02:03:56 +07:00
|
|
|
MMIO_UNKNOWN_OP = 0x5, /* struct mmiotrace_rw */
|
2008-05-13 02:20:56 +07:00
|
|
|
};
|
|
|
|
|
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
struct mmiotrace_rw {
|
2008-05-13 02:21:03 +07:00
|
|
|
resource_size_t phys; /* PCI address of register */
|
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
unsigned long value;
|
|
|
|
unsigned long pc; /* optional program counter */
|
|
|
|
int map_id;
|
|
|
|
unsigned char opcode; /* one of MMIO_{READ,WRITE,UNKNOWN_OP} */
|
|
|
|
unsigned char width; /* size of register access in bytes */
|
2008-05-13 02:20:56 +07:00
|
|
|
};
|
|
|
|
|
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
struct mmiotrace_map {
|
2008-05-13 02:21:03 +07:00
|
|
|
resource_size_t phys; /* base address in PCI space */
|
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
unsigned long virt; /* base virtual address */
|
|
|
|
unsigned long len; /* mapping size */
|
|
|
|
int map_id;
|
|
|
|
unsigned char opcode; /* MMIO_PROBE or MMIO_UNPROBE */
|
2008-05-13 02:20:56 +07:00
|
|
|
};
|
|
|
|
|
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-13 02:20:57 +07:00
|
|
|
/* in kernel/trace/trace_mmiotrace.c */
|
|
|
|
extern void enable_mmiotrace(void);
|
|
|
|
extern void disable_mmiotrace(void);
|
|
|
|
extern void mmio_trace_rw(struct mmiotrace_rw *rw);
|
|
|
|
extern void mmio_trace_mapping(struct mmiotrace_map *map);
|
2008-09-17 02:00:34 +07:00
|
|
|
extern int mmio_trace_printk(const char *fmt, va_list args);
|
2008-05-13 02:20:56 +07:00
|
|
|
|
|
|
|
#endif /* MMIOTRACE_H */
|