0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) "mmiotrace: " fmt
0012
0013 #include <linux/moduleparam.h>
0014 #include <linux/debugfs.h>
0015 #include <linux/slab.h>
0016 #include <linux/uaccess.h>
0017 #include <linux/io.h>
0018 #include <linux/mmiotrace.h>
0019 #include <linux/pgtable.h>
0020 #include <asm/e820/api.h> /* for ISA_START_ADDRESS */
0021 #include <linux/atomic.h>
0022 #include <linux/percpu.h>
0023 #include <linux/cpu.h>
0024
0025 #include "pf_in.h"
0026
0027 struct trap_reason {
0028 unsigned long addr;
0029 unsigned long ip;
0030 enum reason_type type;
0031 int active_traces;
0032 };
0033
0034 struct remap_trace {
0035 struct list_head list;
0036 struct kmmio_probe probe;
0037 resource_size_t phys;
0038 unsigned long id;
0039 };
0040
0041
0042 static DEFINE_PER_CPU(struct trap_reason, pf_reason);
0043 static DEFINE_PER_CPU(struct mmiotrace_rw, cpu_trace);
0044
0045 static DEFINE_MUTEX(mmiotrace_mutex);
0046 static DEFINE_SPINLOCK(trace_lock);
0047 static atomic_t mmiotrace_enabled;
0048 static LIST_HEAD(trace_list);
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 static unsigned long filter_offset;
0063 static bool nommiotrace;
0064 static bool trace_pc;
0065
0066 module_param(filter_offset, ulong, 0);
0067 module_param(nommiotrace, bool, 0);
0068 module_param(trace_pc, bool, 0);
0069
0070 MODULE_PARM_DESC(filter_offset, "Start address of traced mappings.");
0071 MODULE_PARM_DESC(nommiotrace, "Disable actual MMIO tracing.");
0072 MODULE_PARM_DESC(trace_pc, "Record address of faulting instructions.");
0073
0074 static bool is_enabled(void)
0075 {
0076 return atomic_read(&mmiotrace_enabled);
0077 }
0078
0079 static void print_pte(unsigned long address)
0080 {
0081 unsigned int level;
0082 pte_t *pte = lookup_address(address, &level);
0083
0084 if (!pte) {
0085 pr_err("Error in %s: no pte for page 0x%08lx\n",
0086 __func__, address);
0087 return;
0088 }
0089
0090 if (level == PG_LEVEL_2M) {
0091 pr_emerg("4MB pages are not currently supported: 0x%08lx\n",
0092 address);
0093 BUG();
0094 }
0095 pr_info("pte for 0x%lx: 0x%llx 0x%llx\n",
0096 address,
0097 (unsigned long long)pte_val(*pte),
0098 (unsigned long long)pte_val(*pte) & _PAGE_PRESENT);
0099 }
0100
0101
0102
0103
0104
0105 static void die_kmmio_nesting_error(struct pt_regs *regs, unsigned long addr)
0106 {
0107 const struct trap_reason *my_reason = &get_cpu_var(pf_reason);
0108 pr_emerg("unexpected fault for address: 0x%08lx, last fault for address: 0x%08lx\n",
0109 addr, my_reason->addr);
0110 print_pte(addr);
0111 pr_emerg("faulting IP is at %pS\n", (void *)regs->ip);
0112 pr_emerg("last faulting IP was at %pS\n", (void *)my_reason->ip);
0113 #ifdef __i386__
0114 pr_emerg("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
0115 regs->ax, regs->bx, regs->cx, regs->dx);
0116 pr_emerg("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
0117 regs->si, regs->di, regs->bp, regs->sp);
0118 #else
0119 pr_emerg("rax: %016lx rcx: %016lx rdx: %016lx\n",
0120 regs->ax, regs->cx, regs->dx);
0121 pr_emerg("rsi: %016lx rdi: %016lx rbp: %016lx rsp: %016lx\n",
0122 regs->si, regs->di, regs->bp, regs->sp);
0123 #endif
0124 put_cpu_var(pf_reason);
0125 BUG();
0126 }
0127
0128 static void pre(struct kmmio_probe *p, struct pt_regs *regs,
0129 unsigned long addr)
0130 {
0131 struct trap_reason *my_reason = &get_cpu_var(pf_reason);
0132 struct mmiotrace_rw *my_trace = &get_cpu_var(cpu_trace);
0133 const unsigned long instptr = instruction_pointer(regs);
0134 const enum reason_type type = get_ins_type(instptr);
0135 struct remap_trace *trace = p->private;
0136
0137
0138 if (my_reason->active_traces)
0139 die_kmmio_nesting_error(regs, addr);
0140 else
0141 my_reason->active_traces++;
0142
0143 my_reason->type = type;
0144 my_reason->addr = addr;
0145 my_reason->ip = instptr;
0146
0147 my_trace->phys = addr - trace->probe.addr + trace->phys;
0148 my_trace->map_id = trace->id;
0149
0150
0151
0152
0153
0154 if (trace_pc)
0155 my_trace->pc = instptr;
0156 else
0157 my_trace->pc = 0;
0158
0159
0160
0161
0162
0163
0164
0165 switch (type) {
0166 case REG_READ:
0167 my_trace->opcode = MMIO_READ;
0168 my_trace->width = get_ins_mem_width(instptr);
0169 break;
0170 case REG_WRITE:
0171 my_trace->opcode = MMIO_WRITE;
0172 my_trace->width = get_ins_mem_width(instptr);
0173 my_trace->value = get_ins_reg_val(instptr, regs);
0174 break;
0175 case IMM_WRITE:
0176 my_trace->opcode = MMIO_WRITE;
0177 my_trace->width = get_ins_mem_width(instptr);
0178 my_trace->value = get_ins_imm_val(instptr);
0179 break;
0180 default:
0181 {
0182 unsigned char *ip = (unsigned char *)instptr;
0183 my_trace->opcode = MMIO_UNKNOWN_OP;
0184 my_trace->width = 0;
0185 my_trace->value = (*ip) << 16 | *(ip + 1) << 8 |
0186 *(ip + 2);
0187 }
0188 }
0189 put_cpu_var(cpu_trace);
0190 put_cpu_var(pf_reason);
0191 }
0192
0193 static void post(struct kmmio_probe *p, unsigned long condition,
0194 struct pt_regs *regs)
0195 {
0196 struct trap_reason *my_reason = &get_cpu_var(pf_reason);
0197 struct mmiotrace_rw *my_trace = &get_cpu_var(cpu_trace);
0198
0199
0200 my_reason->active_traces--;
0201 if (my_reason->active_traces) {
0202 pr_emerg("unexpected post handler");
0203 BUG();
0204 }
0205
0206 switch (my_reason->type) {
0207 case REG_READ:
0208 my_trace->value = get_ins_reg_val(my_reason->ip, regs);
0209 break;
0210 default:
0211 break;
0212 }
0213
0214 mmio_trace_rw(my_trace);
0215 put_cpu_var(cpu_trace);
0216 put_cpu_var(pf_reason);
0217 }
0218
0219 static void ioremap_trace_core(resource_size_t offset, unsigned long size,
0220 void __iomem *addr)
0221 {
0222 static atomic_t next_id;
0223 struct remap_trace *trace = kmalloc(sizeof(*trace), GFP_KERNEL);
0224
0225 struct mmiotrace_map map = {
0226 .phys = offset,
0227 .virt = (unsigned long)addr,
0228 .len = size,
0229 .opcode = MMIO_PROBE
0230 };
0231
0232 if (!trace) {
0233 pr_err("kmalloc failed in ioremap\n");
0234 return;
0235 }
0236
0237 *trace = (struct remap_trace) {
0238 .probe = {
0239 .addr = (unsigned long)addr,
0240 .len = size,
0241 .pre_handler = pre,
0242 .post_handler = post,
0243 .private = trace
0244 },
0245 .phys = offset,
0246 .id = atomic_inc_return(&next_id)
0247 };
0248 map.map_id = trace->id;
0249
0250 spin_lock_irq(&trace_lock);
0251 if (!is_enabled()) {
0252 kfree(trace);
0253 goto not_enabled;
0254 }
0255
0256 mmio_trace_mapping(&map);
0257 list_add_tail(&trace->list, &trace_list);
0258 if (!nommiotrace)
0259 register_kmmio_probe(&trace->probe);
0260
0261 not_enabled:
0262 spin_unlock_irq(&trace_lock);
0263 }
0264
0265 void mmiotrace_ioremap(resource_size_t offset, unsigned long size,
0266 void __iomem *addr)
0267 {
0268 if (!is_enabled())
0269 return;
0270
0271 pr_debug("ioremap_*(0x%llx, 0x%lx) = %p\n",
0272 (unsigned long long)offset, size, addr);
0273 if ((filter_offset) && (offset != filter_offset))
0274 return;
0275 ioremap_trace_core(offset, size, addr);
0276 }
0277
0278 static void iounmap_trace_core(volatile void __iomem *addr)
0279 {
0280 struct mmiotrace_map map = {
0281 .phys = 0,
0282 .virt = (unsigned long)addr,
0283 .len = 0,
0284 .opcode = MMIO_UNPROBE
0285 };
0286 struct remap_trace *trace;
0287 struct remap_trace *tmp;
0288 struct remap_trace *found_trace = NULL;
0289
0290 pr_debug("Unmapping %p.\n", addr);
0291
0292 spin_lock_irq(&trace_lock);
0293 if (!is_enabled())
0294 goto not_enabled;
0295
0296 list_for_each_entry_safe(trace, tmp, &trace_list, list) {
0297 if ((unsigned long)addr == trace->probe.addr) {
0298 if (!nommiotrace)
0299 unregister_kmmio_probe(&trace->probe);
0300 list_del(&trace->list);
0301 found_trace = trace;
0302 break;
0303 }
0304 }
0305 map.map_id = (found_trace) ? found_trace->id : -1;
0306 mmio_trace_mapping(&map);
0307
0308 not_enabled:
0309 spin_unlock_irq(&trace_lock);
0310 if (found_trace) {
0311 synchronize_rcu();
0312 kfree(found_trace);
0313 }
0314 }
0315
0316 void mmiotrace_iounmap(volatile void __iomem *addr)
0317 {
0318 might_sleep();
0319 if (is_enabled())
0320 iounmap_trace_core(addr);
0321 }
0322
0323 int mmiotrace_printk(const char *fmt, ...)
0324 {
0325 int ret = 0;
0326 va_list args;
0327 unsigned long flags;
0328 va_start(args, fmt);
0329
0330 spin_lock_irqsave(&trace_lock, flags);
0331 if (is_enabled())
0332 ret = mmio_trace_printk(fmt, args);
0333 spin_unlock_irqrestore(&trace_lock, flags);
0334
0335 va_end(args);
0336 return ret;
0337 }
0338 EXPORT_SYMBOL(mmiotrace_printk);
0339
0340 static void clear_trace_list(void)
0341 {
0342 struct remap_trace *trace;
0343 struct remap_trace *tmp;
0344
0345
0346
0347
0348
0349
0350
0351 list_for_each_entry(trace, &trace_list, list) {
0352 pr_notice("purging non-iounmapped trace @0x%08lx, size 0x%lx.\n",
0353 trace->probe.addr, trace->probe.len);
0354 if (!nommiotrace)
0355 unregister_kmmio_probe(&trace->probe);
0356 }
0357 synchronize_rcu();
0358
0359 list_for_each_entry_safe(trace, tmp, &trace_list, list) {
0360 list_del(&trace->list);
0361 kfree(trace);
0362 }
0363 }
0364
0365 #ifdef CONFIG_HOTPLUG_CPU
0366 static cpumask_var_t downed_cpus;
0367
0368 static void enter_uniprocessor(void)
0369 {
0370 int cpu;
0371 int err;
0372
0373 if (!cpumask_available(downed_cpus) &&
0374 !alloc_cpumask_var(&downed_cpus, GFP_KERNEL)) {
0375 pr_notice("Failed to allocate mask\n");
0376 goto out;
0377 }
0378
0379 cpus_read_lock();
0380 cpumask_copy(downed_cpus, cpu_online_mask);
0381 cpumask_clear_cpu(cpumask_first(cpu_online_mask), downed_cpus);
0382 if (num_online_cpus() > 1)
0383 pr_notice("Disabling non-boot CPUs...\n");
0384 cpus_read_unlock();
0385
0386 for_each_cpu(cpu, downed_cpus) {
0387 err = remove_cpu(cpu);
0388 if (!err)
0389 pr_info("CPU%d is down.\n", cpu);
0390 else
0391 pr_err("Error taking CPU%d down: %d\n", cpu, err);
0392 }
0393 out:
0394 if (num_online_cpus() > 1)
0395 pr_warn("multiple CPUs still online, may miss events.\n");
0396 }
0397
0398 static void leave_uniprocessor(void)
0399 {
0400 int cpu;
0401 int err;
0402
0403 if (!cpumask_available(downed_cpus) || cpumask_empty(downed_cpus))
0404 return;
0405 pr_notice("Re-enabling CPUs...\n");
0406 for_each_cpu(cpu, downed_cpus) {
0407 err = add_cpu(cpu);
0408 if (!err)
0409 pr_info("enabled CPU%d.\n", cpu);
0410 else
0411 pr_err("cannot re-enable CPU%d: %d\n", cpu, err);
0412 }
0413 }
0414
0415 #else
0416 static void enter_uniprocessor(void)
0417 {
0418 if (num_online_cpus() > 1)
0419 pr_warn("multiple CPUs are online, may miss events. "
0420 "Suggest booting with maxcpus=1 kernel argument.\n");
0421 }
0422
0423 static void leave_uniprocessor(void)
0424 {
0425 }
0426 #endif
0427
0428 void enable_mmiotrace(void)
0429 {
0430 mutex_lock(&mmiotrace_mutex);
0431 if (is_enabled())
0432 goto out;
0433
0434 if (nommiotrace)
0435 pr_info("MMIO tracing disabled.\n");
0436 kmmio_init();
0437 enter_uniprocessor();
0438 spin_lock_irq(&trace_lock);
0439 atomic_inc(&mmiotrace_enabled);
0440 spin_unlock_irq(&trace_lock);
0441 pr_info("enabled.\n");
0442 out:
0443 mutex_unlock(&mmiotrace_mutex);
0444 }
0445
0446 void disable_mmiotrace(void)
0447 {
0448 mutex_lock(&mmiotrace_mutex);
0449 if (!is_enabled())
0450 goto out;
0451
0452 spin_lock_irq(&trace_lock);
0453 atomic_dec(&mmiotrace_enabled);
0454 BUG_ON(is_enabled());
0455 spin_unlock_irq(&trace_lock);
0456
0457 clear_trace_list();
0458 leave_uniprocessor();
0459 kmmio_cleanup();
0460 pr_info("disabled.\n");
0461 out:
0462 mutex_unlock(&mmiotrace_mutex);
0463 }