diff options
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/mmio-mod.c | 87 | ||||
-rw-r--r-- | arch/x86/mm/pf_in.c | 121 | ||||
-rw-r--r-- | arch/x86/mm/testmmiotrace.c | 4 |
3 files changed, 109 insertions, 103 deletions
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index 635b50e85581..2c4baa88f2cb 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c | |||
@@ -56,13 +56,6 @@ struct remap_trace { | |||
56 | static DEFINE_PER_CPU(struct trap_reason, pf_reason); | 56 | static DEFINE_PER_CPU(struct trap_reason, pf_reason); |
57 | static DEFINE_PER_CPU(struct mmiotrace_rw, cpu_trace); | 57 | static DEFINE_PER_CPU(struct mmiotrace_rw, cpu_trace); |
58 | 58 | ||
59 | #if 0 /* XXX: no way gather this info anymore */ | ||
60 | /* Access to this is not per-cpu. */ | ||
61 | static DEFINE_PER_CPU(atomic_t, dropped); | ||
62 | #endif | ||
63 | |||
64 | static struct dentry *marker_file; | ||
65 | |||
66 | static DEFINE_MUTEX(mmiotrace_mutex); | 59 | static DEFINE_MUTEX(mmiotrace_mutex); |
67 | static DEFINE_SPINLOCK(trace_lock); | 60 | static DEFINE_SPINLOCK(trace_lock); |
68 | static atomic_t mmiotrace_enabled; | 61 | static atomic_t mmiotrace_enabled; |
@@ -75,7 +68,7 @@ static LIST_HEAD(trace_list); /* struct remap_trace */ | |||
75 | * and trace_lock. | 68 | * and trace_lock. |
76 | * - Routines depending on is_enabled() must take trace_lock. | 69 | * - Routines depending on is_enabled() must take trace_lock. |
77 | * - trace_list users must hold trace_lock. | 70 | * - trace_list users must hold trace_lock. |
78 | * - is_enabled() guarantees that mmio_trace_record is allowed. | 71 | * - is_enabled() guarantees that mmio_trace_{rw,mapping} are allowed. |
79 | * - pre/post callbacks assume the effect of is_enabled() being true. | 72 | * - pre/post callbacks assume the effect of is_enabled() being true. |
80 | */ | 73 | */ |
81 | 74 | ||
@@ -97,44 +90,6 @@ static bool is_enabled(void) | |||
97 | return atomic_read(&mmiotrace_enabled); | 90 | return atomic_read(&mmiotrace_enabled); |
98 | } | 91 | } |
99 | 92 | ||
100 | #if 0 /* XXX: needs rewrite */ | ||
101 | /* | ||
102 | * Write callback for the debugfs entry: | ||
103 | * Read a marker and write it to the mmio trace log | ||
104 | */ | ||
105 | static ssize_t write_marker(struct file *file, const char __user *buffer, | ||
106 | size_t count, loff_t *ppos) | ||
107 | { | ||
108 | char *event = NULL; | ||
109 | struct mm_io_header *headp; | ||
110 | ssize_t len = (count > 65535) ? 65535 : count; | ||
111 | |||
112 | event = kzalloc(sizeof(*headp) + len, GFP_KERNEL); | ||
113 | if (!event) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | headp = (struct mm_io_header *)event; | ||
117 | headp->type = MMIO_MAGIC | (MMIO_MARKER << MMIO_OPCODE_SHIFT); | ||
118 | headp->data_len = len; | ||
119 | |||
120 | if (copy_from_user(event + sizeof(*headp), buffer, len)) { | ||
121 | kfree(event); | ||
122 | return -EFAULT; | ||
123 | } | ||
124 | |||
125 | spin_lock_irq(&trace_lock); | ||
126 | #if 0 /* XXX: convert this to use tracing */ | ||
127 | if (is_enabled()) | ||
128 | relay_write(chan, event, sizeof(*headp) + len); | ||
129 | else | ||
130 | #endif | ||
131 | len = -EINVAL; | ||
132 | spin_unlock_irq(&trace_lock); | ||
133 | kfree(event); | ||
134 | return len; | ||
135 | } | ||
136 | #endif | ||
137 | |||
138 | static void print_pte(unsigned long address) | 93 | static void print_pte(unsigned long address) |
139 | { | 94 | { |
140 | unsigned int level; | 95 | unsigned int level; |
@@ -307,8 +262,10 @@ static void ioremap_trace_core(resource_size_t offset, unsigned long size, | |||
307 | map.map_id = trace->id; | 262 | map.map_id = trace->id; |
308 | 263 | ||
309 | spin_lock_irq(&trace_lock); | 264 | spin_lock_irq(&trace_lock); |
310 | if (!is_enabled()) | 265 | if (!is_enabled()) { |
266 | kfree(trace); | ||
311 | goto not_enabled; | 267 | goto not_enabled; |
268 | } | ||
312 | 269 | ||
313 | mmio_trace_mapping(&map); | 270 | mmio_trace_mapping(&map); |
314 | list_add_tail(&trace->list, &trace_list); | 271 | list_add_tail(&trace->list, &trace_list); |
@@ -377,6 +334,23 @@ void mmiotrace_iounmap(volatile void __iomem *addr) | |||
377 | iounmap_trace_core(addr); | 334 | iounmap_trace_core(addr); |
378 | } | 335 | } |
379 | 336 | ||
337 | int mmiotrace_printk(const char *fmt, ...) | ||
338 | { | ||
339 | int ret = 0; | ||
340 | va_list args; | ||
341 | unsigned long flags; | ||
342 | va_start(args, fmt); | ||
343 | |||
344 | spin_lock_irqsave(&trace_lock, flags); | ||
345 | if (is_enabled()) | ||
346 | ret = mmio_trace_printk(fmt, args); | ||
347 | spin_unlock_irqrestore(&trace_lock, flags); | ||
348 | |||
349 | va_end(args); | ||
350 | return ret; | ||
351 | } | ||
352 | EXPORT_SYMBOL(mmiotrace_printk); | ||
353 | |||
380 | static void clear_trace_list(void) | 354 | static void clear_trace_list(void) |
381 | { | 355 | { |
382 | struct remap_trace *trace; | 356 | struct remap_trace *trace; |
@@ -462,26 +436,12 @@ static void leave_uniprocessor(void) | |||
462 | } | 436 | } |
463 | #endif | 437 | #endif |
464 | 438 | ||
465 | #if 0 /* XXX: out of order */ | ||
466 | static struct file_operations fops_marker = { | ||
467 | .owner = THIS_MODULE, | ||
468 | .write = write_marker | ||
469 | }; | ||
470 | #endif | ||
471 | |||
472 | void enable_mmiotrace(void) | 439 | void enable_mmiotrace(void) |
473 | { | 440 | { |
474 | mutex_lock(&mmiotrace_mutex); | 441 | mutex_lock(&mmiotrace_mutex); |
475 | if (is_enabled()) | 442 | if (is_enabled()) |
476 | goto out; | 443 | goto out; |
477 | 444 | ||
478 | #if 0 /* XXX: tracing does not support text entries */ | ||
479 | marker_file = debugfs_create_file("marker", 0660, dir, NULL, | ||
480 | &fops_marker); | ||
481 | if (!marker_file) | ||
482 | pr_err(NAME "marker file creation failed.\n"); | ||
483 | #endif | ||
484 | |||
485 | if (nommiotrace) | 445 | if (nommiotrace) |
486 | pr_info(NAME "MMIO tracing disabled.\n"); | 446 | pr_info(NAME "MMIO tracing disabled.\n"); |
487 | enter_uniprocessor(); | 447 | enter_uniprocessor(); |
@@ -506,11 +466,6 @@ void disable_mmiotrace(void) | |||
506 | 466 | ||
507 | clear_trace_list(); /* guarantees: no more kmmio callbacks */ | 467 | clear_trace_list(); /* guarantees: no more kmmio callbacks */ |
508 | leave_uniprocessor(); | 468 | leave_uniprocessor(); |
509 | if (marker_file) { | ||
510 | debugfs_remove(marker_file); | ||
511 | marker_file = NULL; | ||
512 | } | ||
513 | |||
514 | pr_info(NAME "disabled.\n"); | 469 | pr_info(NAME "disabled.\n"); |
515 | out: | 470 | out: |
516 | mutex_unlock(&mmiotrace_mutex); | 471 | mutex_unlock(&mmiotrace_mutex); |
diff --git a/arch/x86/mm/pf_in.c b/arch/x86/mm/pf_in.c index efa1911e20ca..df3d5c861cda 100644 --- a/arch/x86/mm/pf_in.c +++ b/arch/x86/mm/pf_in.c | |||
@@ -79,25 +79,34 @@ static unsigned int mw32[] = { 0xC7 }; | |||
79 | static unsigned int mw64[] = { 0x89, 0x8B }; | 79 | static unsigned int mw64[] = { 0x89, 0x8B }; |
80 | #endif /* not __i386__ */ | 80 | #endif /* not __i386__ */ |
81 | 81 | ||
82 | static int skip_prefix(unsigned char *addr, int *shorted, int *enlarged, | 82 | struct prefix_bits { |
83 | int *rexr) | 83 | unsigned shorted:1; |
84 | unsigned enlarged:1; | ||
85 | unsigned rexr:1; | ||
86 | unsigned rex:1; | ||
87 | }; | ||
88 | |||
89 | static int skip_prefix(unsigned char *addr, struct prefix_bits *prf) | ||
84 | { | 90 | { |
85 | int i; | 91 | int i; |
86 | unsigned char *p = addr; | 92 | unsigned char *p = addr; |
87 | *shorted = 0; | 93 | prf->shorted = 0; |
88 | *enlarged = 0; | 94 | prf->enlarged = 0; |
89 | *rexr = 0; | 95 | prf->rexr = 0; |
96 | prf->rex = 0; | ||
90 | 97 | ||
91 | restart: | 98 | restart: |
92 | for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) { | 99 | for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) { |
93 | if (*p == prefix_codes[i]) { | 100 | if (*p == prefix_codes[i]) { |
94 | if (*p == 0x66) | 101 | if (*p == 0x66) |
95 | *shorted = 1; | 102 | prf->shorted = 1; |
96 | #ifdef __amd64__ | 103 | #ifdef __amd64__ |
97 | if ((*p & 0xf8) == 0x48) | 104 | if ((*p & 0xf8) == 0x48) |
98 | *enlarged = 1; | 105 | prf->enlarged = 1; |
99 | if ((*p & 0xf4) == 0x44) | 106 | if ((*p & 0xf4) == 0x44) |
100 | *rexr = 1; | 107 | prf->rexr = 1; |
108 | if ((*p & 0xf0) == 0x40) | ||
109 | prf->rex = 1; | ||
101 | #endif | 110 | #endif |
102 | p++; | 111 | p++; |
103 | goto restart; | 112 | goto restart; |
@@ -135,12 +144,12 @@ enum reason_type get_ins_type(unsigned long ins_addr) | |||
135 | { | 144 | { |
136 | unsigned int opcode; | 145 | unsigned int opcode; |
137 | unsigned char *p; | 146 | unsigned char *p; |
138 | int shorted, enlarged, rexr; | 147 | struct prefix_bits prf; |
139 | int i; | 148 | int i; |
140 | enum reason_type rv = OTHERS; | 149 | enum reason_type rv = OTHERS; |
141 | 150 | ||
142 | p = (unsigned char *)ins_addr; | 151 | p = (unsigned char *)ins_addr; |
143 | p += skip_prefix(p, &shorted, &enlarged, &rexr); | 152 | p += skip_prefix(p, &prf); |
144 | p += get_opcode(p, &opcode); | 153 | p += get_opcode(p, &opcode); |
145 | 154 | ||
146 | CHECK_OP_TYPE(opcode, reg_rop, REG_READ); | 155 | CHECK_OP_TYPE(opcode, reg_rop, REG_READ); |
@@ -156,10 +165,11 @@ static unsigned int get_ins_reg_width(unsigned long ins_addr) | |||
156 | { | 165 | { |
157 | unsigned int opcode; | 166 | unsigned int opcode; |
158 | unsigned char *p; | 167 | unsigned char *p; |
159 | int i, shorted, enlarged, rexr; | 168 | struct prefix_bits prf; |
169 | int i; | ||
160 | 170 | ||
161 | p = (unsigned char *)ins_addr; | 171 | p = (unsigned char *)ins_addr; |
162 | p += skip_prefix(p, &shorted, &enlarged, &rexr); | 172 | p += skip_prefix(p, &prf); |
163 | p += get_opcode(p, &opcode); | 173 | p += get_opcode(p, &opcode); |
164 | 174 | ||
165 | for (i = 0; i < ARRAY_SIZE(rw8); i++) | 175 | for (i = 0; i < ARRAY_SIZE(rw8); i++) |
@@ -168,7 +178,7 @@ static unsigned int get_ins_reg_width(unsigned long ins_addr) | |||
168 | 178 | ||
169 | for (i = 0; i < ARRAY_SIZE(rw32); i++) | 179 | for (i = 0; i < ARRAY_SIZE(rw32); i++) |
170 | if (rw32[i] == opcode) | 180 | if (rw32[i] == opcode) |
171 | return (shorted ? 2 : (enlarged ? 8 : 4)); | 181 | return prf.shorted ? 2 : (prf.enlarged ? 8 : 4); |
172 | 182 | ||
173 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); | 183 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); |
174 | return 0; | 184 | return 0; |
@@ -178,10 +188,11 @@ unsigned int get_ins_mem_width(unsigned long ins_addr) | |||
178 | { | 188 | { |
179 | unsigned int opcode; | 189 | unsigned int opcode; |
180 | unsigned char *p; | 190 | unsigned char *p; |
181 | int i, shorted, enlarged, rexr; | 191 | struct prefix_bits prf; |
192 | int i; | ||
182 | 193 | ||
183 | p = (unsigned char *)ins_addr; | 194 | p = (unsigned char *)ins_addr; |
184 | p += skip_prefix(p, &shorted, &enlarged, &rexr); | 195 | p += skip_prefix(p, &prf); |
185 | p += get_opcode(p, &opcode); | 196 | p += get_opcode(p, &opcode); |
186 | 197 | ||
187 | for (i = 0; i < ARRAY_SIZE(mw8); i++) | 198 | for (i = 0; i < ARRAY_SIZE(mw8); i++) |
@@ -194,11 +205,11 @@ unsigned int get_ins_mem_width(unsigned long ins_addr) | |||
194 | 205 | ||
195 | for (i = 0; i < ARRAY_SIZE(mw32); i++) | 206 | for (i = 0; i < ARRAY_SIZE(mw32); i++) |
196 | if (mw32[i] == opcode) | 207 | if (mw32[i] == opcode) |
197 | return shorted ? 2 : 4; | 208 | return prf.shorted ? 2 : 4; |
198 | 209 | ||
199 | for (i = 0; i < ARRAY_SIZE(mw64); i++) | 210 | for (i = 0; i < ARRAY_SIZE(mw64); i++) |
200 | if (mw64[i] == opcode) | 211 | if (mw64[i] == opcode) |
201 | return shorted ? 2 : (enlarged ? 8 : 4); | 212 | return prf.shorted ? 2 : (prf.enlarged ? 8 : 4); |
202 | 213 | ||
203 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); | 214 | printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode); |
204 | return 0; | 215 | return 0; |
@@ -238,7 +249,7 @@ enum { | |||
238 | #endif | 249 | #endif |
239 | }; | 250 | }; |
240 | 251 | ||
241 | static unsigned char *get_reg_w8(int no, struct pt_regs *regs) | 252 | static unsigned char *get_reg_w8(int no, int rex, struct pt_regs *regs) |
242 | { | 253 | { |
243 | unsigned char *rv = NULL; | 254 | unsigned char *rv = NULL; |
244 | 255 | ||
@@ -255,18 +266,6 @@ static unsigned char *get_reg_w8(int no, struct pt_regs *regs) | |||
255 | case arg_DL: | 266 | case arg_DL: |
256 | rv = (unsigned char *)®s->dx; | 267 | rv = (unsigned char *)®s->dx; |
257 | break; | 268 | break; |
258 | case arg_AH: | ||
259 | rv = 1 + (unsigned char *)®s->ax; | ||
260 | break; | ||
261 | case arg_BH: | ||
262 | rv = 1 + (unsigned char *)®s->bx; | ||
263 | break; | ||
264 | case arg_CH: | ||
265 | rv = 1 + (unsigned char *)®s->cx; | ||
266 | break; | ||
267 | case arg_DH: | ||
268 | rv = 1 + (unsigned char *)®s->dx; | ||
269 | break; | ||
270 | #ifdef __amd64__ | 269 | #ifdef __amd64__ |
271 | case arg_R8: | 270 | case arg_R8: |
272 | rv = (unsigned char *)®s->r8; | 271 | rv = (unsigned char *)®s->r8; |
@@ -294,9 +293,55 @@ static unsigned char *get_reg_w8(int no, struct pt_regs *regs) | |||
294 | break; | 293 | break; |
295 | #endif | 294 | #endif |
296 | default: | 295 | default: |
297 | printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no); | ||
298 | break; | 296 | break; |
299 | } | 297 | } |
298 | |||
299 | if (rv) | ||
300 | return rv; | ||
301 | |||
302 | if (rex) { | ||
303 | /* | ||
304 | * If REX prefix exists, access low bytes of SI etc. | ||
305 | * instead of AH etc. | ||
306 | */ | ||
307 | switch (no) { | ||
308 | case arg_SI: | ||
309 | rv = (unsigned char *)®s->si; | ||
310 | break; | ||
311 | case arg_DI: | ||
312 | rv = (unsigned char *)®s->di; | ||
313 | break; | ||
314 | case arg_BP: | ||
315 | rv = (unsigned char *)®s->bp; | ||
316 | break; | ||
317 | case arg_SP: | ||
318 | rv = (unsigned char *)®s->sp; | ||
319 | break; | ||
320 | default: | ||
321 | break; | ||
322 | } | ||
323 | } else { | ||
324 | switch (no) { | ||
325 | case arg_AH: | ||
326 | rv = 1 + (unsigned char *)®s->ax; | ||
327 | break; | ||
328 | case arg_BH: | ||
329 | rv = 1 + (unsigned char *)®s->bx; | ||
330 | break; | ||
331 | case arg_CH: | ||
332 | rv = 1 + (unsigned char *)®s->cx; | ||
333 | break; | ||
334 | case arg_DH: | ||
335 | rv = 1 + (unsigned char *)®s->dx; | ||
336 | break; | ||
337 | default: | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | if (!rv) | ||
343 | printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no); | ||
344 | |||
300 | return rv; | 345 | return rv; |
301 | } | 346 | } |
302 | 347 | ||
@@ -368,11 +413,12 @@ unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs) | |||
368 | unsigned char mod_rm; | 413 | unsigned char mod_rm; |
369 | int reg; | 414 | int reg; |
370 | unsigned char *p; | 415 | unsigned char *p; |
371 | int i, shorted, enlarged, rexr; | 416 | struct prefix_bits prf; |
417 | int i; | ||
372 | unsigned long rv; | 418 | unsigned long rv; |
373 | 419 | ||
374 | p = (unsigned char *)ins_addr; | 420 | p = (unsigned char *)ins_addr; |
375 | p += skip_prefix(p, &shorted, &enlarged, &rexr); | 421 | p += skip_prefix(p, &prf); |
376 | p += get_opcode(p, &opcode); | 422 | p += get_opcode(p, &opcode); |
377 | for (i = 0; i < ARRAY_SIZE(reg_rop); i++) | 423 | for (i = 0; i < ARRAY_SIZE(reg_rop); i++) |
378 | if (reg_rop[i] == opcode) { | 424 | if (reg_rop[i] == opcode) { |
@@ -392,10 +438,10 @@ unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs) | |||
392 | 438 | ||
393 | do_work: | 439 | do_work: |
394 | mod_rm = *p; | 440 | mod_rm = *p; |
395 | reg = ((mod_rm >> 3) & 0x7) | (rexr << 3); | 441 | reg = ((mod_rm >> 3) & 0x7) | (prf.rexr << 3); |
396 | switch (get_ins_reg_width(ins_addr)) { | 442 | switch (get_ins_reg_width(ins_addr)) { |
397 | case 1: | 443 | case 1: |
398 | return *get_reg_w8(reg, regs); | 444 | return *get_reg_w8(reg, prf.rex, regs); |
399 | 445 | ||
400 | case 2: | 446 | case 2: |
401 | return *(unsigned short *)get_reg_w32(reg, regs); | 447 | return *(unsigned short *)get_reg_w32(reg, regs); |
@@ -422,11 +468,12 @@ unsigned long get_ins_imm_val(unsigned long ins_addr) | |||
422 | unsigned char mod_rm; | 468 | unsigned char mod_rm; |
423 | unsigned char mod; | 469 | unsigned char mod; |
424 | unsigned char *p; | 470 | unsigned char *p; |
425 | int i, shorted, enlarged, rexr; | 471 | struct prefix_bits prf; |
472 | int i; | ||
426 | unsigned long rv; | 473 | unsigned long rv; |
427 | 474 | ||
428 | p = (unsigned char *)ins_addr; | 475 | p = (unsigned char *)ins_addr; |
429 | p += skip_prefix(p, &shorted, &enlarged, &rexr); | 476 | p += skip_prefix(p, &prf); |
430 | p += get_opcode(p, &opcode); | 477 | p += get_opcode(p, &opcode); |
431 | for (i = 0; i < ARRAY_SIZE(imm_wop); i++) | 478 | for (i = 0; i < ARRAY_SIZE(imm_wop); i++) |
432 | if (imm_wop[i] == opcode) { | 479 | if (imm_wop[i] == opcode) { |
diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c index d877c5b423ef..ab50a8d7402c 100644 --- a/arch/x86/mm/testmmiotrace.c +++ b/arch/x86/mm/testmmiotrace.c | |||
@@ -3,6 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/io.h> | 5 | #include <linux/io.h> |
6 | #include <linux/mmiotrace.h> | ||
6 | 7 | ||
7 | #define MODULE_NAME "testmmiotrace" | 8 | #define MODULE_NAME "testmmiotrace" |
8 | 9 | ||
@@ -13,6 +14,7 @@ MODULE_PARM_DESC(mmio_address, "Start address of the mapping of 16 kB."); | |||
13 | static void do_write_test(void __iomem *p) | 14 | static void do_write_test(void __iomem *p) |
14 | { | 15 | { |
15 | unsigned int i; | 16 | unsigned int i; |
17 | mmiotrace_printk("Write test.\n"); | ||
16 | for (i = 0; i < 256; i++) | 18 | for (i = 0; i < 256; i++) |
17 | iowrite8(i, p + i); | 19 | iowrite8(i, p + i); |
18 | for (i = 1024; i < (5 * 1024); i += 2) | 20 | for (i = 1024; i < (5 * 1024); i += 2) |
@@ -24,6 +26,7 @@ static void do_write_test(void __iomem *p) | |||
24 | static void do_read_test(void __iomem *p) | 26 | static void do_read_test(void __iomem *p) |
25 | { | 27 | { |
26 | unsigned int i; | 28 | unsigned int i; |
29 | mmiotrace_printk("Read test.\n"); | ||
27 | for (i = 0; i < 256; i++) | 30 | for (i = 0; i < 256; i++) |
28 | ioread8(p + i); | 31 | ioread8(p + i); |
29 | for (i = 1024; i < (5 * 1024); i += 2) | 32 | for (i = 1024; i < (5 * 1024); i += 2) |
@@ -39,6 +42,7 @@ static void do_test(void) | |||
39 | pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); | 42 | pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); |
40 | return; | 43 | return; |
41 | } | 44 | } |
45 | mmiotrace_printk("ioremap returned %p.\n", p); | ||
42 | do_write_test(p); | 46 | do_write_test(p); |
43 | do_read_test(p); | 47 | do_read_test(p); |
44 | iounmap(p); | 48 | iounmap(p); |