mirror of
https://github.com/suyu-emu/horinux.git
synced 2026-09-21 14:15:21 -07:00
Merge branch 'tracing-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'tracing-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (131 commits) tracing/fastboot: improve help text tracing/stacktrace: improve help text tracing/fastboot: fix initcalls disposition in bootgraph.pl tracing/fastboot: fix bootgraph.pl initcall name regexp tracing/fastboot: fix issues and improve output of bootgraph.pl tracepoints: synchronize unregister static inline tracepoints: tracepoint_synchronize_unregister() ftrace: make ftrace_test_p6nop disassembler-friendly markers: fix synchronize marker unregister static inline tracing/fastboot: add better resolution to initcall debug/tracing trace: add build-time check to avoid overrunning hex buffer ftrace: fix hex output mode of ftrace tracing/fastboot: fix initcalls disposition in bootgraph.pl tracing/fastboot: fix printk format typo in boot tracer ftrace: return an error when setting a nonexistent tracer ftrace: make some tracers reentrant ring-buffer: make reentrant ring-buffer: move page indexes into page headers tracing/fastboot: only trace non-module initcalls ftrace: move pc counter in irqtrace ... Manually fix conflicts: - init/main.c: initcall tracing - kernel/module.c: verbose level vs tracepoints - scripts/bootgraph.pl: fallout from cherry-picking commits.
This commit is contained in:
@@ -50,10 +50,12 @@ Connecting a function (probe) to a marker is done by providing a probe (function
|
||||
to call) for the specific marker through marker_probe_register() and can be
|
||||
activated by calling marker_arm(). Marker deactivation can be done by calling
|
||||
marker_disarm() as many times as marker_arm() has been called. Removing a probe
|
||||
is done through marker_probe_unregister(); it will disarm the probe and make
|
||||
sure there is no caller left using the probe when it returns. Probe removal is
|
||||
preempt-safe because preemption is disabled around the probe call. See the
|
||||
"Probe example" section below for a sample probe module.
|
||||
is done through marker_probe_unregister(); it will disarm the probe.
|
||||
marker_synchronize_unregister() must be called before the end of the module exit
|
||||
function to make sure there is no caller left using the probe. This, and the
|
||||
fact that preemption is disabled around the probe call, make sure that probe
|
||||
removal and module unload are safe. See the "Probe example" section below for a
|
||||
sample probe module.
|
||||
|
||||
The marker mechanism supports inserting multiple instances of the same marker.
|
||||
Markers can be put in inline functions, inlined static functions, and
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
Using the Linux Kernel Tracepoints
|
||||
|
||||
Mathieu Desnoyers
|
||||
|
||||
|
||||
This document introduces Linux Kernel Tracepoints and their use. It provides
|
||||
examples of how to insert tracepoints in the kernel and connect probe functions
|
||||
to them and provides some examples of probe functions.
|
||||
|
||||
|
||||
* Purpose of tracepoints
|
||||
|
||||
A tracepoint placed in code provides a hook to call a function (probe) that you
|
||||
can provide at runtime. A tracepoint can be "on" (a probe is connected to it) or
|
||||
"off" (no probe is attached). When a tracepoint is "off" it has no effect,
|
||||
except for adding a tiny time penalty (checking a condition for a branch) and
|
||||
space penalty (adding a few bytes for the function call at the end of the
|
||||
instrumented function and adds a data structure in a separate section). When a
|
||||
tracepoint is "on", the function you provide is called each time the tracepoint
|
||||
is executed, in the execution context of the caller. When the function provided
|
||||
ends its execution, it returns to the caller (continuing from the tracepoint
|
||||
site).
|
||||
|
||||
You can put tracepoints at important locations in the code. They are
|
||||
lightweight hooks that can pass an arbitrary number of parameters,
|
||||
which prototypes are described in a tracepoint declaration placed in a header
|
||||
file.
|
||||
|
||||
They can be used for tracing and performance accounting.
|
||||
|
||||
|
||||
* Usage
|
||||
|
||||
Two elements are required for tracepoints :
|
||||
|
||||
- A tracepoint definition, placed in a header file.
|
||||
- The tracepoint statement, in C code.
|
||||
|
||||
In order to use tracepoints, you should include linux/tracepoint.h.
|
||||
|
||||
In include/trace/subsys.h :
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
DEFINE_TRACE(subsys_eventname,
|
||||
TPPTOTO(int firstarg, struct task_struct *p),
|
||||
TPARGS(firstarg, p));
|
||||
|
||||
In subsys/file.c (where the tracing statement must be added) :
|
||||
|
||||
#include <trace/subsys.h>
|
||||
|
||||
void somefct(void)
|
||||
{
|
||||
...
|
||||
trace_subsys_eventname(arg, task);
|
||||
...
|
||||
}
|
||||
|
||||
Where :
|
||||
- subsys_eventname is an identifier unique to your event
|
||||
- subsys is the name of your subsystem.
|
||||
- eventname is the name of the event to trace.
|
||||
- TPPTOTO(int firstarg, struct task_struct *p) is the prototype of the function
|
||||
called by this tracepoint.
|
||||
- TPARGS(firstarg, p) are the parameters names, same as found in the prototype.
|
||||
|
||||
Connecting a function (probe) to a tracepoint is done by providing a probe
|
||||
(function to call) for the specific tracepoint through
|
||||
register_trace_subsys_eventname(). Removing a probe is done through
|
||||
unregister_trace_subsys_eventname(); it will remove the probe sure there is no
|
||||
caller left using the probe when it returns. Probe removal is preempt-safe
|
||||
because preemption is disabled around the probe call. See the "Probe example"
|
||||
section below for a sample probe module.
|
||||
|
||||
The tracepoint mechanism supports inserting multiple instances of the same
|
||||
tracepoint, but a single definition must be made of a given tracepoint name over
|
||||
all the kernel to make sure no type conflict will occur. Name mangling of the
|
||||
tracepoints is done using the prototypes to make sure typing is correct.
|
||||
Verification of probe type correctness is done at the registration site by the
|
||||
compiler. Tracepoints can be put in inline functions, inlined static functions,
|
||||
and unrolled loops as well as regular functions.
|
||||
|
||||
The naming scheme "subsys_event" is suggested here as a convention intended
|
||||
to limit collisions. Tracepoint names are global to the kernel: they are
|
||||
considered as being the same whether they are in the core kernel image or in
|
||||
modules.
|
||||
|
||||
|
||||
* Probe / tracepoint example
|
||||
|
||||
See the example provided in samples/tracepoints/src
|
||||
|
||||
Compile them with your kernel.
|
||||
|
||||
Run, as root :
|
||||
modprobe tracepoint-example (insmod order is not important)
|
||||
modprobe tracepoint-probe-example
|
||||
cat /proc/tracepoint-example (returns an expected error)
|
||||
rmmod tracepoint-example tracepoint-probe-example
|
||||
dmesg
|
||||
@@ -36,7 +36,7 @@ $ mount -t debugfs debugfs /debug
|
||||
$ echo mmiotrace > /debug/tracing/current_tracer
|
||||
$ cat /debug/tracing/trace_pipe > mydump.txt &
|
||||
Start X or whatever.
|
||||
$ echo "X is up" > /debug/tracing/marker
|
||||
$ echo "X is up" > /debug/tracing/trace_marker
|
||||
$ echo none > /debug/tracing/current_tracer
|
||||
Check for lost events.
|
||||
|
||||
@@ -59,9 +59,8 @@ The 'cat' process should stay running (sleeping) in the background.
|
||||
Load the driver you want to trace and use it. Mmiotrace will only catch MMIO
|
||||
accesses to areas that are ioremapped while mmiotrace is active.
|
||||
|
||||
[Unimplemented feature:]
|
||||
During tracing you can place comments (markers) into the trace by
|
||||
$ echo "X is up" > /debug/tracing/marker
|
||||
$ echo "X is up" > /debug/tracing/trace_marker
|
||||
This makes it easier to see which part of the (huge) trace corresponds to
|
||||
which action. It is recommended to place descriptive markers about what you
|
||||
do.
|
||||
|
||||
@@ -232,6 +232,7 @@ static void __exit sputrace_exit(void)
|
||||
|
||||
remove_proc_entry("sputrace", NULL);
|
||||
kfree(sputrace_log);
|
||||
marker_synchronize_unregister();
|
||||
}
|
||||
|
||||
module_init(sputrace_init);
|
||||
|
||||
@@ -26,6 +26,7 @@ config X86
|
||||
select HAVE_KPROBES
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE
|
||||
select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
#include <asm/apic.h>
|
||||
#include <asm/intel_arch_perfmon.h>
|
||||
|
||||
@@ -336,7 +338,8 @@ static void single_msr_unreserve(void)
|
||||
release_perfctr_nmi(wd_ops->perfctr);
|
||||
}
|
||||
|
||||
static void single_msr_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
|
||||
static void __kprobes
|
||||
single_msr_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
|
||||
{
|
||||
/* start the cycle over again */
|
||||
write_watchdog_counter(wd->perfctr_msr, NULL, nmi_hz);
|
||||
@@ -401,7 +404,7 @@ static int setup_p6_watchdog(unsigned nmi_hz)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void p6_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
|
||||
static void __kprobes p6_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
|
||||
{
|
||||
/*
|
||||
* P6 based Pentium M need to re-unmask
|
||||
@@ -605,7 +608,7 @@ static void p4_unreserve(void)
|
||||
release_perfctr_nmi(MSR_P4_IQ_PERFCTR0);
|
||||
}
|
||||
|
||||
static void p4_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
|
||||
static void __kprobes p4_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
|
||||
{
|
||||
unsigned dummy;
|
||||
/*
|
||||
@@ -784,7 +787,7 @@ unsigned lapic_adjust_nmi_hz(unsigned hz)
|
||||
return hz;
|
||||
}
|
||||
|
||||
int lapic_wd_event(unsigned nmi_hz)
|
||||
int __kprobes lapic_wd_event(unsigned nmi_hz)
|
||||
{
|
||||
struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
|
||||
u64 ctr;
|
||||
|
||||
@@ -1153,20 +1153,6 @@ ENDPROC(xen_failsafe_callback)
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
|
||||
ENTRY(mcount)
|
||||
pushl %eax
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
movl 0xc(%esp), %eax
|
||||
subl $MCOUNT_INSN_SIZE, %eax
|
||||
|
||||
.globl mcount_call
|
||||
mcount_call:
|
||||
call ftrace_stub
|
||||
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %eax
|
||||
|
||||
ret
|
||||
END(mcount)
|
||||
|
||||
|
||||
@@ -64,32 +64,6 @@
|
||||
#ifdef CONFIG_FTRACE
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
ENTRY(mcount)
|
||||
|
||||
subq $0x38, %rsp
|
||||
movq %rax, (%rsp)
|
||||
movq %rcx, 8(%rsp)
|
||||
movq %rdx, 16(%rsp)
|
||||
movq %rsi, 24(%rsp)
|
||||
movq %rdi, 32(%rsp)
|
||||
movq %r8, 40(%rsp)
|
||||
movq %r9, 48(%rsp)
|
||||
|
||||
movq 0x38(%rsp), %rdi
|
||||
subq $MCOUNT_INSN_SIZE, %rdi
|
||||
|
||||
.globl mcount_call
|
||||
mcount_call:
|
||||
call ftrace_stub
|
||||
|
||||
movq 48(%rsp), %r9
|
||||
movq 40(%rsp), %r8
|
||||
movq 32(%rsp), %rdi
|
||||
movq 24(%rsp), %rsi
|
||||
movq 16(%rsp), %rdx
|
||||
movq 8(%rsp), %rcx
|
||||
movq (%rsp), %rax
|
||||
addq $0x38, %rsp
|
||||
|
||||
retq
|
||||
END(mcount)
|
||||
|
||||
|
||||
+77
-43
@@ -11,17 +11,18 @@
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/nops.h>
|
||||
|
||||
|
||||
/* Long is fine, even if it is only 4 bytes ;-) */
|
||||
static long *ftrace_nop;
|
||||
static unsigned long *ftrace_nop;
|
||||
|
||||
union ftrace_code_union {
|
||||
char code[MCOUNT_INSN_SIZE];
|
||||
@@ -60,11 +61,7 @@ notrace int
|
||||
ftrace_modify_code(unsigned long ip, unsigned char *old_code,
|
||||
unsigned char *new_code)
|
||||
{
|
||||
unsigned replaced;
|
||||
unsigned old = *(unsigned *)old_code; /* 4 bytes */
|
||||
unsigned new = *(unsigned *)new_code; /* 4 bytes */
|
||||
unsigned char newch = new_code[4];
|
||||
int faulted = 0;
|
||||
unsigned char replaced[MCOUNT_INSN_SIZE];
|
||||
|
||||
/*
|
||||
* Note: Due to modules and __init, code can
|
||||
@@ -72,29 +69,20 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
|
||||
* as well as code changing.
|
||||
*
|
||||
* No real locking needed, this code is run through
|
||||
* kstop_machine.
|
||||
* kstop_machine, or before SMP starts.
|
||||
*/
|
||||
asm volatile (
|
||||
"1: lock\n"
|
||||
" cmpxchg %3, (%2)\n"
|
||||
" jnz 2f\n"
|
||||
" movb %b4, 4(%2)\n"
|
||||
"2:\n"
|
||||
".section .fixup, \"ax\"\n"
|
||||
"3: movl $1, %0\n"
|
||||
" jmp 2b\n"
|
||||
".previous\n"
|
||||
_ASM_EXTABLE(1b, 3b)
|
||||
: "=r"(faulted), "=a"(replaced)
|
||||
: "r"(ip), "r"(new), "c"(newch),
|
||||
"0"(faulted), "a"(old)
|
||||
: "memory");
|
||||
if (__copy_from_user_inatomic(replaced, (char __user *)ip, MCOUNT_INSN_SIZE))
|
||||
return 1;
|
||||
|
||||
if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
|
||||
return 2;
|
||||
|
||||
WARN_ON_ONCE(__copy_to_user_inatomic((char __user *)ip, new_code,
|
||||
MCOUNT_INSN_SIZE));
|
||||
|
||||
sync_core();
|
||||
|
||||
if (replaced != old && replaced != new)
|
||||
faulted = 2;
|
||||
|
||||
return faulted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
notrace int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||
@@ -112,30 +100,76 @@ notrace int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||
|
||||
notrace int ftrace_mcount_set(unsigned long *data)
|
||||
{
|
||||
unsigned long ip = (long)(&mcount_call);
|
||||
unsigned long *addr = data;
|
||||
unsigned char old[MCOUNT_INSN_SIZE], *new;
|
||||
|
||||
/*
|
||||
* Replace the mcount stub with a pointer to the
|
||||
* ip recorder function.
|
||||
*/
|
||||
memcpy(old, &mcount_call, MCOUNT_INSN_SIZE);
|
||||
new = ftrace_call_replace(ip, *addr);
|
||||
*addr = ftrace_modify_code(ip, old, new);
|
||||
|
||||
/* mcount is initialized as a nop */
|
||||
*data = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init ftrace_dyn_arch_init(void *data)
|
||||
{
|
||||
const unsigned char *const *noptable = find_nop_table();
|
||||
extern const unsigned char ftrace_test_p6nop[];
|
||||
extern const unsigned char ftrace_test_nop5[];
|
||||
extern const unsigned char ftrace_test_jmp[];
|
||||
int faulted = 0;
|
||||
|
||||
/* This is running in kstop_machine */
|
||||
/*
|
||||
* There is no good nop for all x86 archs.
|
||||
* We will default to using the P6_NOP5, but first we
|
||||
* will test to make sure that the nop will actually
|
||||
* work on this CPU. If it faults, we will then
|
||||
* go to a lesser efficient 5 byte nop. If that fails
|
||||
* we then just use a jmp as our nop. This isn't the most
|
||||
* efficient nop, but we can not use a multi part nop
|
||||
* since we would then risk being preempted in the middle
|
||||
* of that nop, and if we enabled tracing then, it might
|
||||
* cause a system crash.
|
||||
*
|
||||
* TODO: check the cpuid to determine the best nop.
|
||||
*/
|
||||
asm volatile (
|
||||
"jmp ftrace_test_jmp\n"
|
||||
/* This code needs to stay around */
|
||||
".section .text, \"ax\"\n"
|
||||
"ftrace_test_jmp:"
|
||||
"jmp ftrace_test_p6nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n" /* 2 byte jmp + 3 bytes */
|
||||
"ftrace_test_p6nop:"
|
||||
P6_NOP5
|
||||
"jmp 1f\n"
|
||||
"ftrace_test_nop5:"
|
||||
".byte 0x66,0x66,0x66,0x66,0x90\n"
|
||||
"jmp 1f\n"
|
||||
".previous\n"
|
||||
"1:"
|
||||
".section .fixup, \"ax\"\n"
|
||||
"2: movl $1, %0\n"
|
||||
" jmp ftrace_test_nop5\n"
|
||||
"3: movl $2, %0\n"
|
||||
" jmp 1b\n"
|
||||
".previous\n"
|
||||
_ASM_EXTABLE(ftrace_test_p6nop, 2b)
|
||||
_ASM_EXTABLE(ftrace_test_nop5, 3b)
|
||||
: "=r"(faulted) : "0" (faulted));
|
||||
|
||||
ftrace_mcount_set(data);
|
||||
switch (faulted) {
|
||||
case 0:
|
||||
pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n");
|
||||
ftrace_nop = (unsigned long *)ftrace_test_p6nop;
|
||||
break;
|
||||
case 1:
|
||||
pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n");
|
||||
ftrace_nop = (unsigned long *)ftrace_test_nop5;
|
||||
break;
|
||||
case 2:
|
||||
pr_info("ftrace: converting mcount calls to jmp . + 5\n");
|
||||
ftrace_nop = (unsigned long *)ftrace_test_jmp;
|
||||
break;
|
||||
}
|
||||
|
||||
ftrace_nop = (unsigned long *)noptable[MCOUNT_INSN_SIZE];
|
||||
/* The return code is retured via data */
|
||||
*(unsigned long *)data = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+21
-66
@@ -56,13 +56,6 @@ struct remap_trace {
|
||||
static DEFINE_PER_CPU(struct trap_reason, pf_reason);
|
||||
static DEFINE_PER_CPU(struct mmiotrace_rw, cpu_trace);
|
||||
|
||||
#if 0 /* XXX: no way gather this info anymore */
|
||||
/* Access to this is not per-cpu. */
|
||||
static DEFINE_PER_CPU(atomic_t, dropped);
|
||||
#endif
|
||||
|
||||
static struct dentry *marker_file;
|
||||
|
||||
static DEFINE_MUTEX(mmiotrace_mutex);
|
||||
static DEFINE_SPINLOCK(trace_lock);
|
||||
static atomic_t mmiotrace_enabled;
|
||||
@@ -75,7 +68,7 @@ static LIST_HEAD(trace_list); /* struct remap_trace */
|
||||
* and trace_lock.
|
||||
* - Routines depending on is_enabled() must take trace_lock.
|
||||
* - trace_list users must hold trace_lock.
|
||||
* - is_enabled() guarantees that mmio_trace_record is allowed.
|
||||
* - is_enabled() guarantees that mmio_trace_{rw,mapping} are allowed.
|
||||
* - pre/post callbacks assume the effect of is_enabled() being true.
|
||||
*/
|
||||
|
||||
@@ -97,44 +90,6 @@ static bool is_enabled(void)
|
||||
return atomic_read(&mmiotrace_enabled);
|
||||
}
|
||||
|
||||
#if 0 /* XXX: needs rewrite */
|
||||
/*
|
||||
* Write callback for the debugfs entry:
|
||||
* Read a marker and write it to the mmio trace log
|
||||
*/
|
||||
static ssize_t write_marker(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *event = NULL;
|
||||
struct mm_io_header *headp;
|
||||
ssize_t len = (count > 65535) ? 65535 : count;
|
||||
|
||||
event = kzalloc(sizeof(*headp) + len, GFP_KERNEL);
|
||||
if (!event)
|
||||
return -ENOMEM;
|
||||
|
||||
headp = (struct mm_io_header *)event;
|
||||
headp->type = MMIO_MAGIC | (MMIO_MARKER << MMIO_OPCODE_SHIFT);
|
||||
headp->data_len = len;
|
||||
|
||||
if (copy_from_user(event + sizeof(*headp), buffer, len)) {
|
||||
kfree(event);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_lock_irq(&trace_lock);
|
||||
#if 0 /* XXX: convert this to use tracing */
|
||||
if (is_enabled())
|
||||
relay_write(chan, event, sizeof(*headp) + len);
|
||||
else
|
||||
#endif
|
||||
len = -EINVAL;
|
||||
spin_unlock_irq(&trace_lock);
|
||||
kfree(event);
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void print_pte(unsigned long address)
|
||||
{
|
||||
unsigned int level;
|
||||
@@ -307,8 +262,10 @@ static void ioremap_trace_core(resource_size_t offset, unsigned long size,
|
||||
map.map_id = trace->id;
|
||||
|
||||
spin_lock_irq(&trace_lock);
|
||||
if (!is_enabled())
|
||||
if (!is_enabled()) {
|
||||
kfree(trace);
|
||||
goto not_enabled;
|
||||
}
|
||||
|
||||
mmio_trace_mapping(&map);
|
||||
list_add_tail(&trace->list, &trace_list);
|
||||
@@ -377,6 +334,23 @@ void mmiotrace_iounmap(volatile void __iomem *addr)
|
||||
iounmap_trace_core(addr);
|
||||
}
|
||||
|
||||
int mmiotrace_printk(const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list args;
|
||||
unsigned long flags;
|
||||
va_start(args, fmt);
|
||||
|
||||
spin_lock_irqsave(&trace_lock, flags);
|
||||
if (is_enabled())
|
||||
ret = mmio_trace_printk(fmt, args);
|
||||
spin_unlock_irqrestore(&trace_lock, flags);
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mmiotrace_printk);
|
||||
|
||||
static void clear_trace_list(void)
|
||||
{
|
||||
struct remap_trace *trace;
|
||||
@@ -462,26 +436,12 @@ static void leave_uniprocessor(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* XXX: out of order */
|
||||
static struct file_operations fops_marker = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = write_marker
|
||||
};
|
||||
#endif
|
||||
|
||||
void enable_mmiotrace(void)
|
||||
{
|
||||
mutex_lock(&mmiotrace_mutex);
|
||||
if (is_enabled())
|
||||
goto out;
|
||||
|
||||
#if 0 /* XXX: tracing does not support text entries */
|
||||
marker_file = debugfs_create_file("marker", 0660, dir, NULL,
|
||||
&fops_marker);
|
||||
if (!marker_file)
|
||||
pr_err(NAME "marker file creation failed.\n");
|
||||
#endif
|
||||
|
||||
if (nommiotrace)
|
||||
pr_info(NAME "MMIO tracing disabled.\n");
|
||||
enter_uniprocessor();
|
||||
@@ -506,11 +466,6 @@ void disable_mmiotrace(void)
|
||||
|
||||
clear_trace_list(); /* guarantees: no more kmmio callbacks */
|
||||
leave_uniprocessor();
|
||||
if (marker_file) {
|
||||
debugfs_remove(marker_file);
|
||||
marker_file = NULL;
|
||||
}
|
||||
|
||||
pr_info(NAME "disabled.\n");
|
||||
out:
|
||||
mutex_unlock(&mmiotrace_mutex);
|
||||
|
||||
+84
-37
@@ -79,25 +79,34 @@ static unsigned int mw32[] = { 0xC7 };
|
||||
static unsigned int mw64[] = { 0x89, 0x8B };
|
||||
#endif /* not __i386__ */
|
||||
|
||||
static int skip_prefix(unsigned char *addr, int *shorted, int *enlarged,
|
||||
int *rexr)
|
||||
struct prefix_bits {
|
||||
unsigned shorted:1;
|
||||
unsigned enlarged:1;
|
||||
unsigned rexr:1;
|
||||
unsigned rex:1;
|
||||
};
|
||||
|
||||
static int skip_prefix(unsigned char *addr, struct prefix_bits *prf)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p = addr;
|
||||
*shorted = 0;
|
||||
*enlarged = 0;
|
||||
*rexr = 0;
|
||||
prf->shorted = 0;
|
||||
prf->enlarged = 0;
|
||||
prf->rexr = 0;
|
||||
prf->rex = 0;
|
||||
|
||||
restart:
|
||||
for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) {
|
||||
if (*p == prefix_codes[i]) {
|
||||
if (*p == 0x66)
|
||||
*shorted = 1;
|
||||
prf->shorted = 1;
|
||||
#ifdef __amd64__
|
||||
if ((*p & 0xf8) == 0x48)
|
||||
*enlarged = 1;
|
||||
prf->enlarged = 1;
|
||||
if ((*p & 0xf4) == 0x44)
|
||||
*rexr = 1;
|
||||
prf->rexr = 1;
|
||||
if ((*p & 0xf0) == 0x40)
|
||||
prf->rex = 1;
|
||||
#endif
|
||||
p++;
|
||||
goto restart;
|
||||
@@ -135,12 +144,12 @@ enum reason_type get_ins_type(unsigned long ins_addr)
|
||||
{
|
||||
unsigned int opcode;
|
||||
unsigned char *p;
|
||||
int shorted, enlarged, rexr;
|
||||
struct prefix_bits prf;
|
||||
int i;
|
||||
enum reason_type rv = OTHERS;
|
||||
|
||||
p = (unsigned char *)ins_addr;
|
||||
p += skip_prefix(p, &shorted, &enlarged, &rexr);
|
||||
p += skip_prefix(p, &prf);
|
||||
p += get_opcode(p, &opcode);
|
||||
|
||||
CHECK_OP_TYPE(opcode, reg_rop, REG_READ);
|
||||
@@ -156,10 +165,11 @@ static unsigned int get_ins_reg_width(unsigned long ins_addr)
|
||||
{
|
||||
unsigned int opcode;
|
||||
unsigned char *p;
|
||||
int i, shorted, enlarged, rexr;
|
||||
struct prefix_bits prf;
|
||||
int i;
|
||||
|
||||
p = (unsigned char *)ins_addr;
|
||||
p += skip_prefix(p, &shorted, &enlarged, &rexr);
|
||||
p += skip_prefix(p, &prf);
|
||||
p += get_opcode(p, &opcode);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rw8); i++)
|
||||
@@ -168,7 +178,7 @@ static unsigned int get_ins_reg_width(unsigned long ins_addr)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rw32); i++)
|
||||
if (rw32[i] == opcode)
|
||||
return (shorted ? 2 : (enlarged ? 8 : 4));
|
||||
return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);
|
||||
|
||||
printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
|
||||
return 0;
|
||||
@@ -178,10 +188,11 @@ unsigned int get_ins_mem_width(unsigned long ins_addr)
|
||||
{
|
||||
unsigned int opcode;
|
||||
unsigned char *p;
|
||||
int i, shorted, enlarged, rexr;
|
||||
struct prefix_bits prf;
|
||||
int i;
|
||||
|
||||
p = (unsigned char *)ins_addr;
|
||||
p += skip_prefix(p, &shorted, &enlarged, &rexr);
|
||||
p += skip_prefix(p, &prf);
|
||||
p += get_opcode(p, &opcode);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mw8); i++)
|
||||
@@ -194,11 +205,11 @@ unsigned int get_ins_mem_width(unsigned long ins_addr)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mw32); i++)
|
||||
if (mw32[i] == opcode)
|
||||
return shorted ? 2 : 4;
|
||||
return prf.shorted ? 2 : 4;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mw64); i++)
|
||||
if (mw64[i] == opcode)
|
||||
return shorted ? 2 : (enlarged ? 8 : 4);
|
||||
return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);
|
||||
|
||||
printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
|
||||
return 0;
|
||||
@@ -238,7 +249,7 @@ enum {
|
||||
#endif
|
||||
};
|
||||
|
||||
static unsigned char *get_reg_w8(int no, struct pt_regs *regs)
|
||||
static unsigned char *get_reg_w8(int no, int rex, struct pt_regs *regs)
|
||||
{
|
||||
unsigned char *rv = NULL;
|
||||
|
||||
@@ -255,18 +266,6 @@ static unsigned char *get_reg_w8(int no, struct pt_regs *regs)
|
||||
case arg_DL:
|
||||
rv = (unsigned char *)®s->dx;
|
||||
break;
|
||||
case arg_AH:
|
||||
rv = 1 + (unsigned char *)®s->ax;
|
||||
break;
|
||||
case arg_BH:
|
||||
rv = 1 + (unsigned char *)®s->bx;
|
||||
break;
|
||||
case arg_CH:
|
||||
rv = 1 + (unsigned char *)®s->cx;
|
||||
break;
|
||||
case arg_DH:
|
||||
rv = 1 + (unsigned char *)®s->dx;
|
||||
break;
|
||||
#ifdef __amd64__
|
||||
case arg_R8:
|
||||
rv = (unsigned char *)®s->r8;
|
||||
@@ -294,9 +293,55 @@ static unsigned char *get_reg_w8(int no, struct pt_regs *regs)
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
if (rex) {
|
||||
/*
|
||||
* If REX prefix exists, access low bytes of SI etc.
|
||||
* instead of AH etc.
|
||||
*/
|
||||
switch (no) {
|
||||
case arg_SI:
|
||||
rv = (unsigned char *)®s->si;
|
||||
break;
|
||||
case arg_DI:
|
||||
rv = (unsigned char *)®s->di;
|
||||
break;
|
||||
case arg_BP:
|
||||
rv = (unsigned char *)®s->bp;
|
||||
break;
|
||||
case arg_SP:
|
||||
rv = (unsigned char *)®s->sp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (no) {
|
||||
case arg_AH:
|
||||
rv = 1 + (unsigned char *)®s->ax;
|
||||
break;
|
||||
case arg_BH:
|
||||
rv = 1 + (unsigned char *)®s->bx;
|
||||
break;
|
||||
case arg_CH:
|
||||
rv = 1 + (unsigned char *)®s->cx;
|
||||
break;
|
||||
case arg_DH:
|
||||
rv = 1 + (unsigned char *)®s->dx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rv)
|
||||
printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -368,11 +413,12 @@ unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs)
|
||||
unsigned char mod_rm;
|
||||
int reg;
|
||||
unsigned char *p;
|
||||
int i, shorted, enlarged, rexr;
|
||||
struct prefix_bits prf;
|
||||
int i;
|
||||
unsigned long rv;
|
||||
|
||||
p = (unsigned char *)ins_addr;
|
||||
p += skip_prefix(p, &shorted, &enlarged, &rexr);
|
||||
p += skip_prefix(p, &prf);
|
||||
p += get_opcode(p, &opcode);
|
||||
for (i = 0; i < ARRAY_SIZE(reg_rop); i++)
|
||||
if (reg_rop[i] == opcode) {
|
||||
@@ -392,10 +438,10 @@ unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs)
|
||||
|
||||
do_work:
|
||||
mod_rm = *p;
|
||||
reg = ((mod_rm >> 3) & 0x7) | (rexr << 3);
|
||||
reg = ((mod_rm >> 3) & 0x7) | (prf.rexr << 3);
|
||||
switch (get_ins_reg_width(ins_addr)) {
|
||||
case 1:
|
||||
return *get_reg_w8(reg, regs);
|
||||
return *get_reg_w8(reg, prf.rex, regs);
|
||||
|
||||
case 2:
|
||||
return *(unsigned short *)get_reg_w32(reg, regs);
|
||||
@@ -422,11 +468,12 @@ unsigned long get_ins_imm_val(unsigned long ins_addr)
|
||||
unsigned char mod_rm;
|
||||
unsigned char mod;
|
||||
unsigned char *p;
|
||||
int i, shorted, enlarged, rexr;
|
||||
struct prefix_bits prf;
|
||||
int i;
|
||||
unsigned long rv;
|
||||
|
||||
p = (unsigned char *)ins_addr;
|
||||
p += skip_prefix(p, &shorted, &enlarged, &rexr);
|
||||
p += skip_prefix(p, &prf);
|
||||
p += get_opcode(p, &opcode);
|
||||
for (i = 0; i < ARRAY_SIZE(imm_wop); i++)
|
||||
if (imm_wop[i] == opcode) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mmiotrace.h>
|
||||
|
||||
#define MODULE_NAME "testmmiotrace"
|
||||
|
||||
@@ -13,6 +14,7 @@ MODULE_PARM_DESC(mmio_address, "Start address of the mapping of 16 kB.");
|
||||
static void do_write_test(void __iomem *p)
|
||||
{
|
||||
unsigned int i;
|
||||
mmiotrace_printk("Write test.\n");
|
||||
for (i = 0; i < 256; i++)
|
||||
iowrite8(i, p + i);
|
||||
for (i = 1024; i < (5 * 1024); i += 2)
|
||||
@@ -24,6 +26,7 @@ static void do_write_test(void __iomem *p)
|
||||
static void do_read_test(void __iomem *p)
|
||||
{
|
||||
unsigned int i;
|
||||
mmiotrace_printk("Read test.\n");
|
||||
for (i = 0; i < 256; i++)
|
||||
ioread8(p + i);
|
||||
for (i = 1024; i < (5 * 1024); i += 2)
|
||||
@@ -39,6 +42,7 @@ static void do_test(void)
|
||||
pr_err(MODULE_NAME ": could not ioremap, aborting.\n");
|
||||
return;
|
||||
}
|
||||
mmiotrace_printk("ioremap returned %p.\n", p);
|
||||
do_write_test(p);
|
||||
do_read_test(p);
|
||||
iounmap(p);
|
||||
|
||||
@@ -37,6 +37,13 @@
|
||||
#define MEM_DISCARD(sec) *(.mem##sec)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
||||
#define MCOUNT_REC() VMLINUX_SYMBOL(__start_mcount_loc) = .; \
|
||||
*(__mcount_loc) \
|
||||
VMLINUX_SYMBOL(__stop_mcount_loc) = .;
|
||||
#else
|
||||
#define MCOUNT_REC()
|
||||
#endif
|
||||
|
||||
/* .data section */
|
||||
#define DATA_DATA \
|
||||
@@ -52,7 +59,10 @@
|
||||
. = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__start___markers) = .; \
|
||||
*(__markers) \
|
||||
VMLINUX_SYMBOL(__stop___markers) = .;
|
||||
VMLINUX_SYMBOL(__stop___markers) = .; \
|
||||
VMLINUX_SYMBOL(__start___tracepoints) = .; \
|
||||
*(__tracepoints) \
|
||||
VMLINUX_SYMBOL(__stop___tracepoints) = .;
|
||||
|
||||
#define RO_DATA(align) \
|
||||
. = ALIGN((align)); \
|
||||
@@ -61,6 +71,7 @@
|
||||
*(.rodata) *(.rodata.*) \
|
||||
*(__vermagic) /* Kernel version magic */ \
|
||||
*(__markers_strings) /* Markers: strings */ \
|
||||
*(__tracepoints_strings)/* Tracepoints: strings */ \
|
||||
} \
|
||||
\
|
||||
.rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
|
||||
@@ -188,6 +199,7 @@
|
||||
/* __*init sections */ \
|
||||
__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) { \
|
||||
*(.ref.rodata) \
|
||||
MCOUNT_REC() \
|
||||
DEV_KEEP(init.rodata) \
|
||||
DEV_KEEP(exit.rodata) \
|
||||
CPU_KEEP(init.rodata) \
|
||||
|
||||
@@ -7,6 +7,16 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern void mcount(void);
|
||||
|
||||
static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
{
|
||||
/*
|
||||
* call mcount is "e8 <4 byte offset>"
|
||||
* The addr points to the 4 byte offset and the caller of this
|
||||
* function wants the pointer to e8. Simply subtract one.
|
||||
*/
|
||||
return addr - 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_FTRACE */
|
||||
|
||||
@@ -44,6 +44,8 @@ extern void __chk_io_ptr(const volatile void __iomem *);
|
||||
# error Sorry, your compiler is too old/not recognized.
|
||||
#endif
|
||||
|
||||
#define notrace __attribute__((no_instrument_function))
|
||||
|
||||
/* Intel compiler defines __GNUC__. So we will overwrite implementations
|
||||
* coming from above header files here
|
||||
*/
|
||||
|
||||
+78
-6
@@ -1,10 +1,14 @@
|
||||
#ifndef _LINUX_FTRACE_H
|
||||
#define _LINUX_FTRACE_H
|
||||
|
||||
#ifdef CONFIG_FTRACE
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kallsyms.h>
|
||||
|
||||
#ifdef CONFIG_FTRACE
|
||||
|
||||
extern int ftrace_enabled;
|
||||
extern int
|
||||
@@ -36,6 +40,7 @@ extern void ftrace_stub(unsigned long a0, unsigned long a1);
|
||||
# define register_ftrace_function(ops) do { } while (0)
|
||||
# define unregister_ftrace_function(ops) do { } while (0)
|
||||
# define clear_ftrace_function(ops) do { } while (0)
|
||||
static inline void ftrace_kill_atomic(void) { }
|
||||
#endif /* CONFIG_FTRACE */
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
@@ -76,8 +81,10 @@ extern void mcount_call(void);
|
||||
|
||||
extern int skip_trace(unsigned long ip);
|
||||
|
||||
void ftrace_disable_daemon(void);
|
||||
void ftrace_enable_daemon(void);
|
||||
extern void ftrace_release(void *start, unsigned long size);
|
||||
|
||||
extern void ftrace_disable_daemon(void);
|
||||
extern void ftrace_enable_daemon(void);
|
||||
|
||||
#else
|
||||
# define skip_trace(ip) ({ 0; })
|
||||
@@ -85,6 +92,7 @@ void ftrace_enable_daemon(void);
|
||||
# define ftrace_set_filter(buf, len, reset) do { } while (0)
|
||||
# define ftrace_disable_daemon() do { } while (0)
|
||||
# define ftrace_enable_daemon() do { } while (0)
|
||||
static inline void ftrace_release(void *start, unsigned long size) { }
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
/* totally disable ftrace - can not re-enable after this */
|
||||
@@ -98,9 +106,11 @@ static inline void tracer_disable(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Ftrace disable/restore without lock. Some synchronization mechanism
|
||||
/*
|
||||
* Ftrace disable/restore without lock. Some synchronization mechanism
|
||||
* must be used to prevent ftrace_enabled to be changed between
|
||||
* disable/restore. */
|
||||
* disable/restore.
|
||||
*/
|
||||
static inline int __ftrace_enabled_save(void)
|
||||
{
|
||||
#ifdef CONFIG_FTRACE
|
||||
@@ -157,9 +167,71 @@ static inline void __ftrace_enabled_restore(int enabled)
|
||||
#ifdef CONFIG_TRACING
|
||||
extern void
|
||||
ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3);
|
||||
|
||||
/**
|
||||
* ftrace_printk - printf formatting in the ftrace buffer
|
||||
* @fmt: the printf format for printing
|
||||
*
|
||||
* Note: __ftrace_printk is an internal function for ftrace_printk and
|
||||
* the @ip is passed in via the ftrace_printk macro.
|
||||
*
|
||||
* This function allows a kernel developer to debug fast path sections
|
||||
* that printk is not appropriate for. By scattering in various
|
||||
* printk like tracing in the code, a developer can quickly see
|
||||
* where problems are occurring.
|
||||
*
|
||||
* This is intended as a debugging tool for the developer only.
|
||||
* Please refrain from leaving ftrace_printks scattered around in
|
||||
* your code.
|
||||
*/
|
||||
# define ftrace_printk(fmt...) __ftrace_printk(_THIS_IP_, fmt)
|
||||
extern int
|
||||
__ftrace_printk(unsigned long ip, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
extern void ftrace_dump(void);
|
||||
#else
|
||||
static inline void
|
||||
ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
|
||||
static inline int
|
||||
ftrace_printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 0)));
|
||||
|
||||
static inline int
|
||||
ftrace_printk(const char *fmt, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void ftrace_dump(void) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
||||
extern void ftrace_init(void);
|
||||
extern void ftrace_init_module(unsigned long *start, unsigned long *end);
|
||||
#else
|
||||
static inline void ftrace_init(void) { }
|
||||
static inline void
|
||||
ftrace_init_module(unsigned long *start, unsigned long *end) { }
|
||||
#endif
|
||||
|
||||
|
||||
struct boot_trace {
|
||||
pid_t caller;
|
||||
char func[KSYM_NAME_LEN];
|
||||
int result;
|
||||
unsigned long long duration; /* usecs */
|
||||
ktime_t calltime;
|
||||
ktime_t rettime;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BOOT_TRACER
|
||||
extern void trace_boot(struct boot_trace *it, initcall_t fn);
|
||||
extern void start_boot_trace(void);
|
||||
extern void stop_boot_trace(void);
|
||||
#else
|
||||
static inline void trace_boot(struct boot_trace *it, initcall_t fn) { }
|
||||
static inline void start_boot_trace(void) { }
|
||||
static inline void stop_boot_trace(void) { }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* _LINUX_FTRACE_H */
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
/* These are for everybody (although not all archs will actually
|
||||
discard it in modules) */
|
||||
#define __init __section(.init.text) __cold
|
||||
#define __init __section(.init.text) __cold notrace
|
||||
#define __initdata __section(.init.data)
|
||||
#define __initconst __section(.init.rodata)
|
||||
#define __exitdata __section(.exit.data)
|
||||
|
||||
@@ -496,4 +496,9 @@ struct sysinfo {
|
||||
#define NUMA_BUILD 0
|
||||
#endif
|
||||
|
||||
/* Rebuild everything on CONFIG_FTRACE_MCOUNT_RECORD */
|
||||
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
||||
# define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
* <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
|
||||
* <prasanna@in.ibm.com> added function-return probes.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/smp.h>
|
||||
@@ -47,7 +48,7 @@
|
||||
#define KPROBE_HIT_SSDONE 0x00000008
|
||||
|
||||
/* Attach to insert probes on any functions which should be ignored*/
|
||||
#define __kprobes __attribute__((__section__(".kprobes.text")))
|
||||
#define __kprobes __attribute__((__section__(".kprobes.text"))) notrace
|
||||
|
||||
struct kprobe;
|
||||
struct pt_regs;
|
||||
@@ -256,7 +257,7 @@ void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
|
||||
|
||||
#else /* CONFIG_KPROBES */
|
||||
|
||||
#define __kprobes /**/
|
||||
#define __kprobes notrace
|
||||
struct jprobe;
|
||||
struct kretprobe;
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/linkage.h>
|
||||
|
||||
#define notrace __attribute__((no_instrument_function))
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define CPP_ASMLINKAGE extern "C"
|
||||
#else
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user