aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorPekka Paalanen <pq@iki.fi>2008-05-12 15:20:57 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-24 05:22:24 -0400
commitd61fc44853f46fb002228b18aa5f30db21fcd4ac (patch)
tree14fa9416aeceb7c5d24876c1111f6f2458a1dc7d /arch/x86
parent0fd0e3da4557c479b820b9a4a7afa25b4637ddf2 (diff)
x86: mmiotrace, preview 2
Kconfig.debug, Makefile and testmmiotrace.c style fixes. Use real mutex instead of mutex. Fix failure path in register probe func. kmmio: RCU read-locked over single stepping. Generate mapping id's. Make mmio-mod.c built-in and rewrite its locking. Add debugfs file to enable/disable mmiotracing. kmmio: use irqsave spinlocks. Lots of cleanups in mmio-mod.c Marker file moved from /proc into debugfs. Call mmiotrace entrypoints directly from ioremap.c. Signed-off-by: Pekka Paalanen <pq@iki.fi> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/Kconfig.debug20
-rw-r--r--arch/x86/kernel/mmiotrace/Makefile2
-rw-r--r--arch/x86/kernel/mmiotrace/kmmio.c72
-rw-r--r--arch/x86/kernel/mmiotrace/mmio-mod.c397
-rw-r--r--arch/x86/kernel/mmiotrace/testmmiotrace.c15
-rw-r--r--arch/x86/mm/ioremap.c9
6 files changed, 315 insertions, 200 deletions
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 9491c0ae03a3..aa0d6462b1fc 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -170,22 +170,19 @@ config IOMMU_LEAK
170 170
171config MMIOTRACE_HOOKS 171config MMIOTRACE_HOOKS
172 bool 172 bool
173 default n
174 173
175config MMIOTRACE 174config MMIOTRACE
176 tristate "Memory mapped IO tracing" 175 bool "Memory mapped IO tracing"
177 depends on DEBUG_KERNEL && RELAY && DEBUG_FS 176 depends on DEBUG_KERNEL && RELAY && DEBUG_FS
178 select MMIOTRACE_HOOKS 177 select MMIOTRACE_HOOKS
179 default n 178 default y
180 help 179 help
181 This will build a kernel module called mmiotrace. 180 Mmiotrace traces Memory Mapped I/O access and is meant for
182 Making this a built-in is heavily discouraged. 181 debugging and reverse engineering. It is called from the ioremap
183 182 implementation and works via page faults. A user space program is
184 Mmiotrace traces Memory Mapped I/O access and is meant for debugging 183 required to collect the MMIO data from debugfs files.
185 and reverse engineering. The kernel module offers wrapped 184 Tracing is disabled by default and can be enabled from a debugfs
186 versions of the ioremap family of functions. The driver to be traced 185 file.
187 must be modified to call these wrappers. A user space program is
188 required to collect the MMIO data.
189 186
190 See http://nouveau.freedesktop.org/wiki/MmioTrace 187 See http://nouveau.freedesktop.org/wiki/MmioTrace
191 If you are not helping to develop drivers, say N. 188 If you are not helping to develop drivers, say N.
@@ -193,7 +190,6 @@ config MMIOTRACE
193config MMIOTRACE_TEST 190config MMIOTRACE_TEST
194 tristate "Test module for mmiotrace" 191 tristate "Test module for mmiotrace"
195 depends on MMIOTRACE && m 192 depends on MMIOTRACE && m
196 default n
197 help 193 help
198 This is a dumb module for testing mmiotrace. It is very dangerous 194 This is a dumb module for testing mmiotrace. It is very dangerous
199 as it will write garbage to IO memory starting at a given address. 195 as it will write garbage to IO memory starting at a given address.
diff --git a/arch/x86/kernel/mmiotrace/Makefile b/arch/x86/kernel/mmiotrace/Makefile
index cf1e747b463e..dbcd8d50fb8d 100644
--- a/arch/x86/kernel/mmiotrace/Makefile
+++ b/arch/x86/kernel/mmiotrace/Makefile
@@ -1,4 +1,4 @@
1obj-$(CONFIG_MMIOTRACE_HOOKS) += kmmio.o 1obj-$(CONFIG_MMIOTRACE_HOOKS) += kmmio.o
2obj-$(CONFIG_MMIOTRACE) += mmiotrace.o 2obj-$(CONFIG_MMIOTRACE) += mmiotrace.o
3mmiotrace-objs := pf_in.o mmio-mod.o 3mmiotrace-y := pf_in.o mmio-mod.o
4obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o 4obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o
diff --git a/arch/x86/kernel/mmiotrace/kmmio.c b/arch/x86/kernel/mmiotrace/kmmio.c
index 539a9b19588f..efb467933087 100644
--- a/arch/x86/kernel/mmiotrace/kmmio.c
+++ b/arch/x86/kernel/mmiotrace/kmmio.c
@@ -19,6 +19,7 @@
19#include <linux/preempt.h> 19#include <linux/preempt.h>
20#include <linux/percpu.h> 20#include <linux/percpu.h>
21#include <linux/kdebug.h> 21#include <linux/kdebug.h>
22#include <linux/mutex.h>
22#include <asm/io.h> 23#include <asm/io.h>
23#include <asm/cacheflush.h> 24#include <asm/cacheflush.h>
24#include <asm/errno.h> 25#include <asm/errno.h>
@@ -59,7 +60,7 @@ struct kmmio_context {
59static int kmmio_die_notifier(struct notifier_block *nb, unsigned long val, 60static int kmmio_die_notifier(struct notifier_block *nb, unsigned long val,
60 void *args); 61 void *args);
61 62
62static DECLARE_MUTEX(kmmio_init_mutex); 63static DEFINE_MUTEX(kmmio_init_mutex);
63static DEFINE_SPINLOCK(kmmio_lock); 64static DEFINE_SPINLOCK(kmmio_lock);
64 65
65/* These are protected by kmmio_lock */ 66/* These are protected by kmmio_lock */
@@ -90,7 +91,7 @@ static struct notifier_block nb_die = {
90 */ 91 */
91void reference_kmmio(void) 92void reference_kmmio(void)
92{ 93{
93 down(&kmmio_init_mutex); 94 mutex_lock(&kmmio_init_mutex);
94 spin_lock_irq(&kmmio_lock); 95 spin_lock_irq(&kmmio_lock);
95 if (!kmmio_initialized) { 96 if (!kmmio_initialized) {
96 int i; 97 int i;
@@ -101,7 +102,7 @@ void reference_kmmio(void)
101 } 102 }
102 kmmio_initialized++; 103 kmmio_initialized++;
103 spin_unlock_irq(&kmmio_lock); 104 spin_unlock_irq(&kmmio_lock);
104 up(&kmmio_init_mutex); 105 mutex_unlock(&kmmio_init_mutex);
105} 106}
106EXPORT_SYMBOL_GPL(reference_kmmio); 107EXPORT_SYMBOL_GPL(reference_kmmio);
107 108
@@ -115,7 +116,7 @@ void unreference_kmmio(void)
115{ 116{
116 bool unreg = false; 117 bool unreg = false;
117 118
118 down(&kmmio_init_mutex); 119 mutex_lock(&kmmio_init_mutex);
119 spin_lock_irq(&kmmio_lock); 120 spin_lock_irq(&kmmio_lock);
120 121
121 if (kmmio_initialized == 1) { 122 if (kmmio_initialized == 1) {
@@ -128,7 +129,7 @@ void unreference_kmmio(void)
128 129
129 if (unreg) 130 if (unreg)
130 unregister_die_notifier(&nb_die); /* calls sync_rcu() */ 131 unregister_die_notifier(&nb_die); /* calls sync_rcu() */
131 up(&kmmio_init_mutex); 132 mutex_unlock(&kmmio_init_mutex);
132} 133}
133EXPORT_SYMBOL(unreference_kmmio); 134EXPORT_SYMBOL(unreference_kmmio);
134 135
@@ -244,17 +245,13 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
244 * Preemption is now disabled to prevent process switch during 245 * Preemption is now disabled to prevent process switch during
245 * single stepping. We can only handle one active kmmio trace 246 * single stepping. We can only handle one active kmmio trace
246 * per cpu, so ensure that we finish it before something else 247 * per cpu, so ensure that we finish it before something else
247 * gets to run. 248 * gets to run. We also hold the RCU read lock over single
248 * 249 * stepping to avoid looking up the probe and kmmio_fault_page
249 * XXX what if an interrupt occurs between returning from 250 * again.
250 * do_page_fault() and entering the single-step exception handler?
251 * And that interrupt triggers a kmmio trap?
252 * XXX If we tracing an interrupt service routine or whatever, is
253 * this enough to keep it on the current cpu?
254 */ 251 */
255 preempt_disable(); 252 preempt_disable();
256
257 rcu_read_lock(); 253 rcu_read_lock();
254
258 faultpage = get_kmmio_fault_page(addr); 255 faultpage = get_kmmio_fault_page(addr);
259 if (!faultpage) { 256 if (!faultpage) {
260 /* 257 /*
@@ -287,14 +284,24 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
287 if (ctx->probe && ctx->probe->pre_handler) 284 if (ctx->probe && ctx->probe->pre_handler)
288 ctx->probe->pre_handler(ctx->probe, regs, addr); 285 ctx->probe->pre_handler(ctx->probe, regs, addr);
289 286
287 /*
288 * Enable single-stepping and disable interrupts for the faulting
289 * context. Local interrupts must not get enabled during stepping.
290 */
290 regs->flags |= TF_MASK; 291 regs->flags |= TF_MASK;
291 regs->flags &= ~IF_MASK; 292 regs->flags &= ~IF_MASK;
292 293
293 /* Now we set present bit in PTE and single step. */ 294 /* Now we set present bit in PTE and single step. */
294 disarm_kmmio_fault_page(ctx->fpage->page, NULL); 295 disarm_kmmio_fault_page(ctx->fpage->page, NULL);
295 296
297 /*
298 * If another cpu accesses the same page while we are stepping,
299 * the access will not be caught. It will simply succeed and the
300 * only downside is we lose the event. If this becomes a problem,
301 * the user should drop to single cpu before tracing.
302 */
303
296 put_cpu_var(kmmio_ctx); 304 put_cpu_var(kmmio_ctx);
297 rcu_read_unlock();
298 return 1; 305 return 1;
299 306
300no_kmmio_ctx: 307no_kmmio_ctx:
@@ -313,32 +320,15 @@ no_kmmio:
313static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs) 320static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs)
314{ 321{
315 int ret = 0; 322 int ret = 0;
316 struct kmmio_probe *probe;
317 struct kmmio_fault_page *faultpage;
318 struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); 323 struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx);
319 324
320 if (!ctx->active) 325 if (!ctx->active)
321 goto out; 326 goto out;
322 327
323 rcu_read_lock();
324
325 faultpage = get_kmmio_fault_page(ctx->addr);
326 probe = get_kmmio_probe(ctx->addr);
327 if (faultpage != ctx->fpage || probe != ctx->probe) {
328 /*
329 * The trace setup changed after kmmio_handler() and before
330 * running this respective post handler. User does not want
331 * the result anymore.
332 */
333 ctx->probe = NULL;
334 ctx->fpage = NULL;
335 }
336
337 if (ctx->probe && ctx->probe->post_handler) 328 if (ctx->probe && ctx->probe->post_handler)
338 ctx->probe->post_handler(ctx->probe, condition, regs); 329 ctx->probe->post_handler(ctx->probe, condition, regs);
339 330
340 if (ctx->fpage) 331 arm_kmmio_fault_page(ctx->fpage->page, NULL);
341 arm_kmmio_fault_page(ctx->fpage->page, NULL);
342 332
343 regs->flags &= ~TF_MASK; 333 regs->flags &= ~TF_MASK;
344 regs->flags |= ctx->saved_flags; 334 regs->flags |= ctx->saved_flags;
@@ -346,6 +336,7 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs)
346 /* These were acquired in kmmio_handler(). */ 336 /* These were acquired in kmmio_handler(). */
347 ctx->active--; 337 ctx->active--;
348 BUG_ON(ctx->active); 338 BUG_ON(ctx->active);
339 rcu_read_unlock();
349 preempt_enable_no_resched(); 340 preempt_enable_no_resched();
350 341
351 /* 342 /*
@@ -355,8 +346,6 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs)
355 */ 346 */
356 if (!(regs->flags & TF_MASK)) 347 if (!(regs->flags & TF_MASK))
357 ret = 1; 348 ret = 1;
358
359 rcu_read_unlock();
360out: 349out:
361 put_cpu_var(kmmio_ctx); 350 put_cpu_var(kmmio_ctx);
362 return ret; 351 return ret;
@@ -411,15 +400,16 @@ static void release_kmmio_fault_page(unsigned long page,
411 400
412int register_kmmio_probe(struct kmmio_probe *p) 401int register_kmmio_probe(struct kmmio_probe *p)
413{ 402{
403 unsigned long flags;
414 int ret = 0; 404 int ret = 0;
415 unsigned long size = 0; 405 unsigned long size = 0;
416 406
417 spin_lock_irq(&kmmio_lock); 407 spin_lock_irqsave(&kmmio_lock, flags);
418 kmmio_count++;
419 if (get_kmmio_probe(p->addr)) { 408 if (get_kmmio_probe(p->addr)) {
420 ret = -EEXIST; 409 ret = -EEXIST;
421 goto out; 410 goto out;
422 } 411 }
412 kmmio_count++;
423 list_add_rcu(&p->list, &kmmio_probes); 413 list_add_rcu(&p->list, &kmmio_probes);
424 while (size < p->len) { 414 while (size < p->len) {
425 if (add_kmmio_fault_page(p->addr + size)) 415 if (add_kmmio_fault_page(p->addr + size))
@@ -427,7 +417,7 @@ int register_kmmio_probe(struct kmmio_probe *p)
427 size += PAGE_SIZE; 417 size += PAGE_SIZE;
428 } 418 }
429out: 419out:
430 spin_unlock_irq(&kmmio_lock); 420 spin_unlock_irqrestore(&kmmio_lock, flags);
431 /* 421 /*
432 * XXX: What should I do here? 422 * XXX: What should I do here?
433 * Here was a call to global_flush_tlb(), but it does not exist 423 * Here was a call to global_flush_tlb(), but it does not exist
@@ -478,7 +468,8 @@ static void remove_kmmio_fault_pages(struct rcu_head *head)
478 468
479/* 469/*
480 * Remove a kmmio probe. You have to synchronize_rcu() before you can be 470 * Remove a kmmio probe. You have to synchronize_rcu() before you can be
481 * sure that the callbacks will not be called anymore. 471 * sure that the callbacks will not be called anymore. Only after that
472 * you may actually release your struct kmmio_probe.
482 * 473 *
483 * Unregistering a kmmio fault page has three steps: 474 * Unregistering a kmmio fault page has three steps:
484 * 1. release_kmmio_fault_page() 475 * 1. release_kmmio_fault_page()
@@ -490,18 +481,19 @@ static void remove_kmmio_fault_pages(struct rcu_head *head)
490 */ 481 */
491void unregister_kmmio_probe(struct kmmio_probe *p) 482void unregister_kmmio_probe(struct kmmio_probe *p)
492{ 483{
484 unsigned long flags;
493 unsigned long size = 0; 485 unsigned long size = 0;
494 struct kmmio_fault_page *release_list = NULL; 486 struct kmmio_fault_page *release_list = NULL;
495 struct kmmio_delayed_release *drelease; 487 struct kmmio_delayed_release *drelease;
496 488
497 spin_lock_irq(&kmmio_lock); 489 spin_lock_irqsave(&kmmio_lock, flags);
498 while (size < p->len) { 490 while (size < p->len) {
499 release_kmmio_fault_page(p->addr + size, &release_list); 491 release_kmmio_fault_page(p->addr + size, &release_list);
500 size += PAGE_SIZE; 492 size += PAGE_SIZE;
501 } 493 }
502 list_del_rcu(&p->list); 494 list_del_rcu(&p->list);
503 kmmio_count--; 495 kmmio_count--;
504 spin_unlock_irq(&kmmio_lock); 496 spin_unlock_irqrestore(&kmmio_lock, flags);
505 497
506 drelease = kmalloc(sizeof(*drelease), GFP_ATOMIC); 498 drelease = kmalloc(sizeof(*drelease), GFP_ATOMIC);
507 if (!drelease) { 499 if (!drelease) {
diff --git a/arch/x86/kernel/mmiotrace/mmio-mod.c b/arch/x86/kernel/mmiotrace/mmio-mod.c
index e1a508588f03..738644061e4e 100644
--- a/arch/x86/kernel/mmiotrace/mmio-mod.c
+++ b/arch/x86/kernel/mmiotrace/mmio-mod.c
@@ -19,6 +19,8 @@
19 * 19 *
20 * Derived from the read-mod example from relay-examples by Tom Zanussi. 20 * Derived from the read-mod example from relay-examples by Tom Zanussi.
21 */ 21 */
22#define DEBUG 1
23
22#include <linux/module.h> 24#include <linux/module.h>
23#include <linux/relay.h> 25#include <linux/relay.h>
24#include <linux/debugfs.h> 26#include <linux/debugfs.h>
@@ -34,12 +36,12 @@
34 36
35#include "pf_in.h" 37#include "pf_in.h"
36 38
37/* This app's relay channel files will appear in /debug/mmio-trace */ 39#define NAME "mmiotrace: "
38#define APP_DIR "mmio-trace"
39/* the marker injection file in /proc */
40#define MARKER_FILE "mmio-marker"
41 40
42#define MODULE_NAME "mmiotrace" 41/* This app's relay channel files will appear in /debug/mmio-trace */
42static const char APP_DIR[] = "mmio-trace";
43/* the marker injection file in /debug/APP_DIR */
44static const char MARKER_FILE[] = "mmio-marker";
43 45
44struct trap_reason { 46struct trap_reason {
45 unsigned long addr; 47 unsigned long addr;
@@ -48,6 +50,15 @@ struct trap_reason {
48 int active_traces; 50 int active_traces;
49}; 51};
50 52
53struct remap_trace {
54 struct list_head list;
55 struct kmmio_probe probe;
56 unsigned long phys;
57 unsigned long id;
58};
59
60static const size_t subbuf_size = 256*1024;
61
51/* Accessed per-cpu. */ 62/* Accessed per-cpu. */
52static DEFINE_PER_CPU(struct trap_reason, pf_reason); 63static DEFINE_PER_CPU(struct trap_reason, pf_reason);
53static DEFINE_PER_CPU(struct mm_io_header_rw, cpu_trace); 64static DEFINE_PER_CPU(struct mm_io_header_rw, cpu_trace);
@@ -55,33 +66,53 @@ static DEFINE_PER_CPU(struct mm_io_header_rw, cpu_trace);
55/* Access to this is not per-cpu. */ 66/* Access to this is not per-cpu. */
56static DEFINE_PER_CPU(atomic_t, dropped); 67static DEFINE_PER_CPU(atomic_t, dropped);
57 68
58static struct file_operations mmio_fops = { 69static struct dentry *dir;
59 .owner = THIS_MODULE, 70static struct dentry *enabled_file;
60}; 71static struct dentry *marker_file;
61 72
62static const size_t subbuf_size = 256*1024; 73static DEFINE_MUTEX(mmiotrace_mutex);
74static DEFINE_SPINLOCK(trace_lock);
75static atomic_t mmiotrace_enabled;
76static LIST_HEAD(trace_list); /* struct remap_trace */
63static struct rchan *chan; 77static struct rchan *chan;
64static struct dentry *dir; 78
65static struct proc_dir_entry *proc_marker_file; 79/*
80 * Locking in this file:
81 * - mmiotrace_mutex enforces enable/disable_mmiotrace() critical sections.
82 * - mmiotrace_enabled may be modified only when holding mmiotrace_mutex
83 * and trace_lock.
84 * - Routines depending on is_enabled() must take trace_lock.
85 * - trace_list users must hold trace_lock.
86 * - is_enabled() guarantees that chan is valid.
87 * - pre/post callbacks assume the effect of is_enabled() being true.
88 */
66 89
67/* module parameters */ 90/* module parameters */
68static unsigned int n_subbufs = 32*4; 91static unsigned int n_subbufs = 32*4;
69static unsigned long filter_offset; 92static unsigned long filter_offset;
70static int nommiotrace; 93static int nommiotrace;
71static int ISA_trace; 94static int ISA_trace;
72static int trace_pc; 95static int trace_pc;
96static int enable_now;
73 97
74module_param(n_subbufs, uint, 0); 98module_param(n_subbufs, uint, 0);
75module_param(filter_offset, ulong, 0); 99module_param(filter_offset, ulong, 0);
76module_param(nommiotrace, bool, 0); 100module_param(nommiotrace, bool, 0);
77module_param(ISA_trace, bool, 0); 101module_param(ISA_trace, bool, 0);
78module_param(trace_pc, bool, 0); 102module_param(trace_pc, bool, 0);
103module_param(enable_now, bool, 0);
79 104
80MODULE_PARM_DESC(n_subbufs, "Number of 256kB buffers, default 128."); 105MODULE_PARM_DESC(n_subbufs, "Number of 256kB buffers, default 128.");
81MODULE_PARM_DESC(filter_offset, "Start address of traced mappings."); 106MODULE_PARM_DESC(filter_offset, "Start address of traced mappings.");
82MODULE_PARM_DESC(nommiotrace, "Disable actual MMIO tracing."); 107MODULE_PARM_DESC(nommiotrace, "Disable actual MMIO tracing.");
83MODULE_PARM_DESC(ISA_trace, "Do not exclude the low ISA range."); 108MODULE_PARM_DESC(ISA_trace, "Do not exclude the low ISA range.");
84MODULE_PARM_DESC(trace_pc, "Record address of faulting instructions."); 109MODULE_PARM_DESC(trace_pc, "Record address of faulting instructions.");
110MODULE_PARM_DESC(enable_now, "Start mmiotracing immediately on module load.");
111
112static bool is_enabled(void)
113{
114 return atomic_read(&mmiotrace_enabled);
115}
85 116
86static void record_timestamp(struct mm_io_header *header) 117static void record_timestamp(struct mm_io_header *header)
87{ 118{
@@ -93,15 +124,15 @@ static void record_timestamp(struct mm_io_header *header)
93} 124}
94 125
95/* 126/*
96 * Write callback for the /proc entry: 127 * Write callback for the debugfs entry:
97 * Read a marker and write it to the mmio trace log 128 * Read a marker and write it to the mmio trace log
98 */ 129 */
99static int write_marker(struct file *file, const char __user *buffer, 130static ssize_t write_marker(struct file *file, const char __user *buffer,
100 unsigned long count, void *data) 131 size_t count, loff_t *ppos)
101{ 132{
102 char *event = NULL; 133 char *event = NULL;
103 struct mm_io_header *headp; 134 struct mm_io_header *headp;
104 int len = (count > 65535) ? 65535 : count; 135 ssize_t len = (count > 65535) ? 65535 : count;
105 136
106 event = kzalloc(sizeof(*headp) + len, GFP_KERNEL); 137 event = kzalloc(sizeof(*headp) + len, GFP_KERNEL);
107 if (!event) 138 if (!event)
@@ -117,7 +148,12 @@ static int write_marker(struct file *file, const char __user *buffer,
117 return -EFAULT; 148 return -EFAULT;
118 } 149 }
119 150
120 relay_write(chan, event, sizeof(*headp) + len); 151 spin_lock_irq(&trace_lock);
152 if (is_enabled())
153 relay_write(chan, event, sizeof(*headp) + len);
154 else
155 len = -EINVAL;
156 spin_unlock_irq(&trace_lock);
121 kfree(event); 157 kfree(event);
122 return len; 158 return len;
123} 159}
@@ -128,19 +164,18 @@ static void print_pte(unsigned long address)
128 pte_t *pte = lookup_address(address, &level); 164 pte_t *pte = lookup_address(address, &level);
129 165
130 if (!pte) { 166 if (!pte) {
131 pr_err(MODULE_NAME ": Error in %s: no pte for page 0x%08lx\n", 167 pr_err(NAME "Error in %s: no pte for page 0x%08lx\n",
132 __func__, address); 168 __func__, address);
133 return; 169 return;
134 } 170 }
135 171
136 if (level == PG_LEVEL_2M) { 172 if (level == PG_LEVEL_2M) {
137 pr_emerg(MODULE_NAME ": 4MB pages are not currently " 173 pr_emerg(NAME "4MB pages are not currently supported: "
138 "supported: %lx\n", address); 174 "0x%08lx\n", address);
139 BUG(); 175 BUG();
140 } 176 }
141 pr_info(MODULE_NAME ": pte for 0x%lx: 0x%lx 0x%lx\n", 177 pr_info(NAME "pte for 0x%lx: 0x%lx 0x%lx\n", address, pte_val(*pte),
142 address, pte_val(*pte), 178 pte_val(*pte) & _PAGE_PRESENT);
143 pte_val(*pte) & _PAGE_PRESENT);
144} 179}
145 180
146/* 181/*
@@ -150,22 +185,18 @@ static void print_pte(unsigned long address)
150static void die_kmmio_nesting_error(struct pt_regs *regs, unsigned long addr) 185static void die_kmmio_nesting_error(struct pt_regs *regs, unsigned long addr)
151{ 186{
152 const struct trap_reason *my_reason = &get_cpu_var(pf_reason); 187 const struct trap_reason *my_reason = &get_cpu_var(pf_reason);
153 pr_emerg(MODULE_NAME ": unexpected fault for address: %lx, " 188 pr_emerg(NAME "unexpected fault for address: 0x%08lx, "
154 "last fault for address: %lx\n", 189 "last fault for address: 0x%08lx\n",
155 addr, my_reason->addr); 190 addr, my_reason->addr);
156 print_pte(addr); 191 print_pte(addr);
192 print_symbol(KERN_EMERG "faulting IP is at %s\n", regs->ip);
193 print_symbol(KERN_EMERG "last faulting IP was at %s\n", my_reason->ip);
157#ifdef __i386__ 194#ifdef __i386__
158 print_symbol(KERN_EMERG "faulting EIP is at %s\n", regs->ip);
159 print_symbol(KERN_EMERG "last faulting EIP was at %s\n",
160 my_reason->ip);
161 pr_emerg("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", 195 pr_emerg("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
162 regs->ax, regs->bx, regs->cx, regs->dx); 196 regs->ax, regs->bx, regs->cx, regs->dx);
163 pr_emerg("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", 197 pr_emerg("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
164 regs->si, regs->di, regs->bp, regs->sp); 198 regs->si, regs->di, regs->bp, regs->sp);
165#else 199#else
166 print_symbol(KERN_EMERG "faulting RIP is at %s\n", regs->ip);
167 print_symbol(KERN_EMERG "last faulting RIP was at %s\n",
168 my_reason->ip);
169 pr_emerg("rax: %016lx rcx: %016lx rdx: %016lx\n", 200 pr_emerg("rax: %016lx rcx: %016lx rdx: %016lx\n",
170 regs->ax, regs->cx, regs->dx); 201 regs->ax, regs->cx, regs->dx);
171 pr_emerg("rsi: %016lx rdi: %016lx rbp: %016lx rsp: %016lx\n", 202 pr_emerg("rsi: %016lx rdi: %016lx rbp: %016lx rsp: %016lx\n",
@@ -197,6 +228,10 @@ static void pre(struct kmmio_probe *p, struct pt_regs *regs,
197 my_trace->header.pid = 0; 228 my_trace->header.pid = 0;
198 my_trace->header.data_len = sizeof(struct mm_io_rw); 229 my_trace->header.data_len = sizeof(struct mm_io_rw);
199 my_trace->rw.address = addr; 230 my_trace->rw.address = addr;
231 /*
232 * struct remap_trace *trace = p->user_data;
233 * phys = addr - trace->probe.addr + trace->phys;
234 */
200 235
201 /* 236 /*
202 * Only record the program counter when requested. 237 * Only record the program counter when requested.
@@ -246,15 +281,10 @@ static void post(struct kmmio_probe *p, unsigned long condition,
246 struct trap_reason *my_reason = &get_cpu_var(pf_reason); 281 struct trap_reason *my_reason = &get_cpu_var(pf_reason);
247 struct mm_io_header_rw *my_trace = &get_cpu_var(cpu_trace); 282 struct mm_io_header_rw *my_trace = &get_cpu_var(cpu_trace);
248 283
249 /*
250 * XXX: This might not get called, if the probe is removed while
251 * trace hit is on flight.
252 */
253
254 /* this should always return the active_trace count to 0 */ 284 /* this should always return the active_trace count to 0 */
255 my_reason->active_traces--; 285 my_reason->active_traces--;
256 if (my_reason->active_traces) { 286 if (my_reason->active_traces) {
257 pr_emerg(MODULE_NAME ": unexpected post handler"); 287 pr_emerg(NAME "unexpected post handler");
258 BUG(); 288 BUG();
259 } 289 }
260 290
@@ -284,20 +314,23 @@ static int subbuf_start_handler(struct rchan_buf *buf, void *subbuf,
284 int count; 314 int count;
285 if (relay_buf_full(buf)) { 315 if (relay_buf_full(buf)) {
286 if (atomic_inc_return(drop) == 1) 316 if (atomic_inc_return(drop) == 1)
287 pr_err(MODULE_NAME ": cpu %d buffer full!\n", cpu); 317 pr_err(NAME "cpu %d buffer full!\n", cpu);
288 return 0; 318 return 0;
289 } 319 }
290 count = atomic_read(drop); 320 count = atomic_read(drop);
291 if (count) { 321 if (count) {
292 pr_err(MODULE_NAME ": cpu %d buffer no longer full, " 322 pr_err(NAME "cpu %d buffer no longer full, missed %d events.\n",
293 "missed %d events.\n", 323 cpu, count);
294 cpu, count);
295 atomic_sub(count, drop); 324 atomic_sub(count, drop);
296 } 325 }
297 326
298 return 1; 327 return 1;
299} 328}
300 329
330static struct file_operations mmio_fops = {
331 .owner = THIS_MODULE,
332};
333
301/* file_create() callback. Creates relay file in debugfs. */ 334/* file_create() callback. Creates relay file in debugfs. */
302static struct dentry *create_buf_file_handler(const char *filename, 335static struct dentry *create_buf_file_handler(const char *filename,
303 struct dentry *parent, 336 struct dentry *parent,
@@ -333,34 +366,10 @@ static struct rchan_callbacks relay_callbacks = {
333 .remove_buf_file = remove_buf_file_handler, 366 .remove_buf_file = remove_buf_file_handler,
334}; 367};
335 368
336/* 369static void ioremap_trace_core(unsigned long offset, unsigned long size,
337 * create_channel - creates channel /debug/APP_DIR/cpuXXX
338 * Returns channel on success, NULL otherwise
339 */
340static struct rchan *create_channel(unsigned size, unsigned n)
341{
342 return relay_open("cpu", dir, size, n, &relay_callbacks, NULL);
343}
344
345/* destroy_channel - destroys channel /debug/APP_DIR/cpuXXX */
346static void destroy_channel(void)
347{
348 if (chan) {
349 relay_close(chan);
350 chan = NULL;
351 }
352}
353
354struct remap_trace {
355 struct list_head list;
356 struct kmmio_probe probe;
357};
358static LIST_HEAD(trace_list);
359static DEFINE_SPINLOCK(trace_list_lock);
360
361static void do_ioremap_trace_core(unsigned long offset, unsigned long size,
362 void __iomem *addr) 370 void __iomem *addr)
363{ 371{
372 static atomic_t next_id;
364 struct remap_trace *trace = kmalloc(sizeof(*trace), GFP_KERNEL); 373 struct remap_trace *trace = kmalloc(sizeof(*trace), GFP_KERNEL);
365 struct mm_io_header_map event = { 374 struct mm_io_header_map event = {
366 .header = { 375 .header = {
@@ -380,61 +389,49 @@ static void do_ioremap_trace_core(unsigned long offset, unsigned long size,
380 }; 389 };
381 record_timestamp(&event.header); 390 record_timestamp(&event.header);
382 391
392 if (!trace) {
393 pr_err(NAME "kmalloc failed in ioremap\n");
394 return;
395 }
396
383 *trace = (struct remap_trace) { 397 *trace = (struct remap_trace) {
384 .probe = { 398 .probe = {
385 .addr = (unsigned long)addr, 399 .addr = (unsigned long)addr,
386 .len = size, 400 .len = size,
387 .pre_handler = pre, 401 .pre_handler = pre,
388 .post_handler = post, 402 .post_handler = post,
389 } 403 .user_data = trace
404 },
405 .phys = offset,
406 .id = atomic_inc_return(&next_id)
390 }; 407 };
391 408
409 spin_lock_irq(&trace_lock);
410 if (!is_enabled())
411 goto not_enabled;
412
392 relay_write(chan, &event, sizeof(event)); 413 relay_write(chan, &event, sizeof(event));
393 spin_lock(&trace_list_lock);
394 list_add_tail(&trace->list, &trace_list); 414 list_add_tail(&trace->list, &trace_list);
395 spin_unlock(&trace_list_lock);
396 if (!nommiotrace) 415 if (!nommiotrace)
397 register_kmmio_probe(&trace->probe); 416 register_kmmio_probe(&trace->probe);
417
418not_enabled:
419 spin_unlock_irq(&trace_lock);
398} 420}
399 421
400static void ioremap_trace_core(unsigned long offset, unsigned long size, 422void
401 void __iomem *addr) 423mmiotrace_ioremap(unsigned long offset, unsigned long size, void __iomem *addr)
402{ 424{
403 if ((filter_offset) && (offset != filter_offset)) 425 if (!is_enabled()) /* recheck and proper locking in *_core() */
404 return; 426 return;
405 427
406 /* Don't trace the low PCI/ISA area, it's always mapped.. */ 428 pr_debug(NAME "ioremap_*(0x%lx, 0x%lx) = %p\n", offset, size, addr);
407 if (!ISA_trace && (offset < ISA_END_ADDRESS) && 429 if ((filter_offset) && (offset != filter_offset))
408 (offset + size > ISA_START_ADDRESS)) {
409 pr_notice(MODULE_NAME ": Ignoring map of low PCI/ISA area "
410 "(0x%lx-0x%lx)\n",
411 offset, offset + size);
412 return; 430 return;
413 } 431 ioremap_trace_core(offset, size, addr);
414 do_ioremap_trace_core(offset, size, addr);
415}
416
417void __iomem *ioremap_cache_trace(unsigned long offset, unsigned long size)
418{
419 void __iomem *p = ioremap_cache(offset, size);
420 pr_debug(MODULE_NAME ": ioremap_cache(0x%lx, 0x%lx) = %p\n",
421 offset, size, p);
422 ioremap_trace_core(offset, size, p);
423 return p;
424} 432}
425EXPORT_SYMBOL(ioremap_cache_trace);
426 433
427void __iomem *ioremap_nocache_trace(unsigned long offset, unsigned long size) 434static void iounmap_trace_core(volatile void __iomem *addr)
428{
429 void __iomem *p = ioremap_nocache(offset, size);
430 pr_debug(MODULE_NAME ": ioremap_nocache(0x%lx, 0x%lx) = %p\n",
431 offset, size, p);
432 ioremap_trace_core(offset, size, p);
433 return p;
434}
435EXPORT_SYMBOL(ioremap_nocache_trace);
436
437void iounmap_trace(volatile void __iomem *addr)
438{ 435{
439 struct mm_io_header_map event = { 436 struct mm_io_header_map event = {
440 .header = { 437 .header = {
@@ -454,84 +451,212 @@ void iounmap_trace(volatile void __iomem *addr)
454 }; 451 };
455 struct remap_trace *trace; 452 struct remap_trace *trace;
456 struct remap_trace *tmp; 453 struct remap_trace *tmp;
457 pr_debug(MODULE_NAME ": Unmapping %p.\n", addr); 454 struct remap_trace *found_trace = NULL;
455
456 pr_debug(NAME "Unmapping %p.\n", addr);
458 record_timestamp(&event.header); 457 record_timestamp(&event.header);
459 458
460 spin_lock(&trace_list_lock); 459 spin_lock_irq(&trace_lock);
460 if (!is_enabled())
461 goto not_enabled;
462
461 list_for_each_entry_safe(trace, tmp, &trace_list, list) { 463 list_for_each_entry_safe(trace, tmp, &trace_list, list) {
462 if ((unsigned long)addr == trace->probe.addr) { 464 if ((unsigned long)addr == trace->probe.addr) {
463 if (!nommiotrace) 465 if (!nommiotrace)
464 unregister_kmmio_probe(&trace->probe); 466 unregister_kmmio_probe(&trace->probe);
465 list_del(&trace->list); 467 list_del(&trace->list);
466 kfree(trace); 468 found_trace = trace;
467 break; 469 break;
468 } 470 }
469 } 471 }
470 spin_unlock(&trace_list_lock);
471 relay_write(chan, &event, sizeof(event)); 472 relay_write(chan, &event, sizeof(event));
472 iounmap(addr); 473
474not_enabled:
475 spin_unlock_irq(&trace_lock);
476 if (found_trace) {
477 synchronize_rcu(); /* unregister_kmmio_probe() requirement */
478 kfree(found_trace);
479 }
480}
481
482void mmiotrace_iounmap(volatile void __iomem *addr)
483{
484 might_sleep();
485 if (is_enabled()) /* recheck and proper locking in *_core() */
486 iounmap_trace_core(addr);
473} 487}
474EXPORT_SYMBOL(iounmap_trace);
475 488
476static void clear_trace_list(void) 489static void clear_trace_list(void)
477{ 490{
478 struct remap_trace *trace; 491 struct remap_trace *trace;
479 struct remap_trace *tmp; 492 struct remap_trace *tmp;
480 493
481 spin_lock(&trace_list_lock); 494 /*
482 list_for_each_entry_safe(trace, tmp, &trace_list, list) { 495 * No locking required, because the caller ensures we are in a
483 pr_warning(MODULE_NAME ": purging non-iounmapped " 496 * critical section via mutex, and is_enabled() is false,
497 * i.e. nothing can traverse or modify this list.
498 * Caller also ensures is_enabled() cannot change.
499 */
500 list_for_each_entry(trace, &trace_list, list) {
501 pr_notice(NAME "purging non-iounmapped "
484 "trace @0x%08lx, size 0x%lx.\n", 502 "trace @0x%08lx, size 0x%lx.\n",
485 trace->probe.addr, trace->probe.len); 503 trace->probe.addr, trace->probe.len);
486 if (!nommiotrace) 504 if (!nommiotrace)
487 unregister_kmmio_probe(&trace->probe); 505 unregister_kmmio_probe(&trace->probe);
506 }
507 synchronize_rcu(); /* unregister_kmmio_probe() requirement */
508
509 list_for_each_entry_safe(trace, tmp, &trace_list, list) {
488 list_del(&trace->list); 510 list_del(&trace->list);
489 kfree(trace); 511 kfree(trace);
512 }
513}
514
515static ssize_t read_enabled_file_bool(struct file *file,
516 char __user *user_buf, size_t count, loff_t *ppos)
517{
518 char buf[3];
519
520 if (is_enabled())
521 buf[0] = '1';
522 else
523 buf[0] = '0';
524 buf[1] = '\n';
525 buf[2] = '\0';
526 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
527}
528
529static void enable_mmiotrace(void);
530static void disable_mmiotrace(void);
531
532static ssize_t write_enabled_file_bool(struct file *file,
533 const char __user *user_buf, size_t count, loff_t *ppos)
534{
535 char buf[32];
536 int buf_size = min(count, (sizeof(buf)-1));
537
538 if (copy_from_user(buf, user_buf, buf_size))
539 return -EFAULT;
540
541 switch (buf[0]) {
542 case 'y':
543 case 'Y':
544 case '1':
545 enable_mmiotrace();
546 break;
547 case 'n':
548 case 'N':
549 case '0':
550 disable_mmiotrace();
490 break; 551 break;
491 } 552 }
492 spin_unlock(&trace_list_lock); 553
554 return count;
555}
556
557/* this ripped from kernel/kprobes.c */
558static struct file_operations fops_enabled = {
559 .owner = THIS_MODULE,
560 .read = read_enabled_file_bool,
561 .write = write_enabled_file_bool
562};
563
564static struct file_operations fops_marker = {
565 .owner = THIS_MODULE,
566 .write = write_marker
567};
568
569static void enable_mmiotrace(void)
570{
571 mutex_lock(&mmiotrace_mutex);
572 if (is_enabled())
573 goto out;
574
575 chan = relay_open("cpu", dir, subbuf_size, n_subbufs,
576 &relay_callbacks, NULL);
577 if (!chan) {
578 pr_err(NAME "relay app channel creation failed.\n");
579 goto out;
580 }
581
582 reference_kmmio();
583
584 marker_file = debugfs_create_file("marker", 0660, dir, NULL,
585 &fops_marker);
586 if (!marker_file)
587 pr_err(NAME "marker file creation failed.\n");
588
589 if (nommiotrace)
590 pr_info(NAME "MMIO tracing disabled.\n");
591 if (ISA_trace)
592 pr_warning(NAME "Warning! low ISA range will be traced.\n");
593 spin_lock_irq(&trace_lock);
594 atomic_inc(&mmiotrace_enabled);
595 spin_unlock_irq(&trace_lock);
596 pr_info(NAME "enabled.\n");
597out:
598 mutex_unlock(&mmiotrace_mutex);
599}
600
601static void disable_mmiotrace(void)
602{
603 mutex_lock(&mmiotrace_mutex);
604 if (!is_enabled())
605 goto out;
606
607 spin_lock_irq(&trace_lock);
608 atomic_dec(&mmiotrace_enabled);
609 BUG_ON(is_enabled());
610 spin_unlock_irq(&trace_lock);
611
612 clear_trace_list(); /* guarantees: no more kmmio callbacks */
613 unreference_kmmio();
614 if (marker_file) {
615 debugfs_remove(marker_file);
616 marker_file = NULL;
617 }
618 if (chan) {
619 relay_close(chan);
620 chan = NULL;
621 }
622
623 pr_info(NAME "disabled.\n");
624out:
625 mutex_unlock(&mmiotrace_mutex);
493} 626}
494 627
495static int __init init(void) 628static int __init init(void)
496{ 629{
630 pr_debug(NAME "load...\n");
497 if (n_subbufs < 2) 631 if (n_subbufs < 2)
498 return -EINVAL; 632 return -EINVAL;
499 633
500 dir = debugfs_create_dir(APP_DIR, NULL); 634 dir = debugfs_create_dir(APP_DIR, NULL);
501 if (!dir) { 635 if (!dir) {
502 pr_err(MODULE_NAME ": Couldn't create relay app directory.\n"); 636 pr_err(NAME "Couldn't create relay app directory.\n");
503 return -ENOMEM; 637 return -ENOMEM;
504 } 638 }
505 639
506 chan = create_channel(subbuf_size, n_subbufs); 640 enabled_file = debugfs_create_file("enabled", 0600, dir, NULL,
507 if (!chan) { 641 &fops_enabled);
642 if (!enabled_file) {
643 pr_err(NAME "Couldn't create enabled file.\n");
508 debugfs_remove(dir); 644 debugfs_remove(dir);
509 pr_err(MODULE_NAME ": relay app channel creation failed\n");
510 return -ENOMEM; 645 return -ENOMEM;
511 } 646 }
512 647
513 reference_kmmio(); 648 if (enable_now)
514 649 enable_mmiotrace();
515 proc_marker_file = create_proc_entry(MARKER_FILE, 0, NULL);
516 if (proc_marker_file)
517 proc_marker_file->write_proc = write_marker;
518 650
519 pr_debug(MODULE_NAME ": loaded.\n");
520 if (nommiotrace)
521 pr_info(MODULE_NAME ": MMIO tracing disabled.\n");
522 if (ISA_trace)
523 pr_warning(MODULE_NAME ": Warning! low ISA range will be "
524 "traced.\n");
525 return 0; 651 return 0;
526} 652}
527 653
528static void __exit cleanup(void) 654static void __exit cleanup(void)
529{ 655{
530 pr_debug(MODULE_NAME ": unload...\n"); 656 pr_debug(NAME "unload...\n");
531 clear_trace_list(); 657 if (enabled_file)
532 unreference_kmmio(); 658 debugfs_remove(enabled_file);
533 remove_proc_entry(MARKER_FILE, NULL); 659 disable_mmiotrace();
534 destroy_channel();
535 if (dir) 660 if (dir)
536 debugfs_remove(dir); 661 debugfs_remove(dir);
537} 662}
diff --git a/arch/x86/kernel/mmiotrace/testmmiotrace.c b/arch/x86/kernel/mmiotrace/testmmiotrace.c
index 5ecff578672b..cfa60b227c8d 100644
--- a/arch/x86/kernel/mmiotrace/testmmiotrace.c
+++ b/arch/x86/kernel/mmiotrace/testmmiotrace.c
@@ -4,10 +4,6 @@
4#include <linux/module.h> 4#include <linux/module.h>
5#include <asm/io.h> 5#include <asm/io.h>
6 6
7extern void __iomem *ioremap_nocache_trace(unsigned long offset,
8 unsigned long size);
9extern void iounmap_trace(volatile void __iomem *addr);
10
11#define MODULE_NAME "testmmiotrace" 7#define MODULE_NAME "testmmiotrace"
12 8
13static unsigned long mmio_address; 9static unsigned long mmio_address;
@@ -28,25 +24,24 @@ static void do_write_test(void __iomem *p)
28static void do_read_test(void __iomem *p) 24static void do_read_test(void __iomem *p)
29{ 25{
30 unsigned int i; 26 unsigned int i;
31 volatile unsigned int v;
32 for (i = 0; i < 256; i++) 27 for (i = 0; i < 256; i++)
33 v = ioread8(p + i); 28 ioread8(p + i);
34 for (i = 1024; i < (5 * 1024); i += 2) 29 for (i = 1024; i < (5 * 1024); i += 2)
35 v = ioread16(p + i); 30 ioread16(p + i);
36 for (i = (5 * 1024); i < (16 * 1024); i += 4) 31 for (i = (5 * 1024); i < (16 * 1024); i += 4)
37 v = ioread32(p + i); 32 ioread32(p + i);
38} 33}
39 34
40static void do_test(void) 35static void do_test(void)
41{ 36{
42 void __iomem *p = ioremap_nocache_trace(mmio_address, 0x4000); 37 void __iomem *p = ioremap_nocache(mmio_address, 0x4000);
43 if (!p) { 38 if (!p) {
44 pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); 39 pr_err(MODULE_NAME ": could not ioremap, aborting.\n");
45 return; 40 return;
46 } 41 }
47 do_write_test(p); 42 do_write_test(p);
48 do_read_test(p); 43 do_read_test(p);
49 iounmap_trace(p); 44 iounmap(p);
50} 45}
51 46
52static int __init init(void) 47static int __init init(void)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 71bb3159031a..8927c878544d 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -12,6 +12,7 @@
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/vmalloc.h> 14#include <linux/vmalloc.h>
15#include <linux/mmiotrace.h>
15 16
16#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
17#include <asm/e820.h> 18#include <asm/e820.h>
@@ -126,6 +127,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
126 unsigned long new_prot_val; 127 unsigned long new_prot_val;
127 pgprot_t prot; 128 pgprot_t prot;
128 int retval; 129 int retval;
130 void __iomem *ret_addr;
129 131
130 /* Don't allow wraparound or zero size */ 132 /* Don't allow wraparound or zero size */
131 last_addr = phys_addr + size - 1; 133 last_addr = phys_addr + size - 1;
@@ -233,7 +235,10 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
233 return NULL; 235 return NULL;
234 } 236 }
235 237
236 return (void __iomem *) (vaddr + offset); 238 ret_addr = (void __iomem *) (vaddr + offset);
239 mmiotrace_ioremap(phys_addr, size, ret_addr);
240
241 return ret_addr;
237} 242}
238 243
239/** 244/**
@@ -325,6 +330,8 @@ void iounmap(volatile void __iomem *addr)
325 addr = (volatile void __iomem *) 330 addr = (volatile void __iomem *)
326 (PAGE_MASK & (unsigned long __force)addr); 331 (PAGE_MASK & (unsigned long __force)addr);
327 332
333 mmiotrace_iounmap(addr);
334
328 /* Use the vm area unlocked, assuming the caller 335 /* Use the vm area unlocked, assuming the caller
329 ensures there isn't another iounmap for the same address 336 ensures there isn't another iounmap for the same address
330 in parallel. Reuse of the virtual address is prevented by 337 in parallel. Reuse of the virtual address is prevented by