diff options
-rw-r--r-- | arch/x86/mm/kmmio.c | 27 | ||||
-rw-r--r-- | arch/x86/mm/mmio-mod.c | 2 | ||||
-rw-r--r-- | include/linux/mmiotrace.h | 2 |
3 files changed, 26 insertions, 5 deletions
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index a769d1a2d93b..256ce643b0ba 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c | |||
@@ -311,7 +311,12 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs) | |||
311 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); | 311 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); |
312 | 312 | ||
313 | if (!ctx->active) { | 313 | if (!ctx->active) { |
314 | pr_debug("kmmio: spurious debug trap on CPU %d.\n", | 314 | /* |
315 | * debug traps without an active context are due to either | ||
316 | * something external causing them (f.e. using a debugger while | ||
317 | * mmio tracing enabled), or erroneous behaviour | ||
318 | */ | ||
319 | pr_warning("kmmio: unexpected debug trap on CPU %d.\n", | ||
315 | smp_processor_id()); | 320 | smp_processor_id()); |
316 | goto out; | 321 | goto out; |
317 | } | 322 | } |
@@ -529,8 +534,8 @@ void unregister_kmmio_probe(struct kmmio_probe *p) | |||
529 | } | 534 | } |
530 | EXPORT_SYMBOL(unregister_kmmio_probe); | 535 | EXPORT_SYMBOL(unregister_kmmio_probe); |
531 | 536 | ||
532 | static int kmmio_die_notifier(struct notifier_block *nb, unsigned long val, | 537 | static int |
533 | void *args) | 538 | kmmio_die_notifier(struct notifier_block *nb, unsigned long val, void *args) |
534 | { | 539 | { |
535 | struct die_args *arg = args; | 540 | struct die_args *arg = args; |
536 | 541 | ||
@@ -545,11 +550,23 @@ static struct notifier_block nb_die = { | |||
545 | .notifier_call = kmmio_die_notifier | 550 | .notifier_call = kmmio_die_notifier |
546 | }; | 551 | }; |
547 | 552 | ||
548 | static int __init init_kmmio(void) | 553 | int kmmio_init(void) |
549 | { | 554 | { |
550 | int i; | 555 | int i; |
556 | |||
551 | for (i = 0; i < KMMIO_PAGE_TABLE_SIZE; i++) | 557 | for (i = 0; i < KMMIO_PAGE_TABLE_SIZE; i++) |
552 | INIT_LIST_HEAD(&kmmio_page_table[i]); | 558 | INIT_LIST_HEAD(&kmmio_page_table[i]); |
559 | |||
553 | return register_die_notifier(&nb_die); | 560 | return register_die_notifier(&nb_die); |
554 | } | 561 | } |
555 | fs_initcall(init_kmmio); /* should be before device_initcall() */ | 562 | |
563 | void kmmio_cleanup(void) | ||
564 | { | ||
565 | int i; | ||
566 | |||
567 | unregister_die_notifier(&nb_die); | ||
568 | for (i = 0; i < KMMIO_PAGE_TABLE_SIZE; i++) { | ||
569 | WARN_ONCE(!list_empty(&kmmio_page_table[i]), | ||
570 | KERN_ERR "kmmio_page_table not empty at cleanup, any further tracing will leak memory.\n"); | ||
571 | } | ||
572 | } | ||
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index c9342ed8b402..132772a8ec57 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c | |||
@@ -451,6 +451,7 @@ void enable_mmiotrace(void) | |||
451 | 451 | ||
452 | if (nommiotrace) | 452 | if (nommiotrace) |
453 | pr_info(NAME "MMIO tracing disabled.\n"); | 453 | pr_info(NAME "MMIO tracing disabled.\n"); |
454 | kmmio_init(); | ||
454 | enter_uniprocessor(); | 455 | enter_uniprocessor(); |
455 | spin_lock_irq(&trace_lock); | 456 | spin_lock_irq(&trace_lock); |
456 | atomic_inc(&mmiotrace_enabled); | 457 | atomic_inc(&mmiotrace_enabled); |
@@ -473,6 +474,7 @@ void disable_mmiotrace(void) | |||
473 | 474 | ||
474 | clear_trace_list(); /* guarantees: no more kmmio callbacks */ | 475 | clear_trace_list(); /* guarantees: no more kmmio callbacks */ |
475 | leave_uniprocessor(); | 476 | leave_uniprocessor(); |
477 | kmmio_cleanup(); | ||
476 | pr_info(NAME "disabled.\n"); | 478 | pr_info(NAME "disabled.\n"); |
477 | out: | 479 | out: |
478 | mutex_unlock(&mmiotrace_mutex); | 480 | mutex_unlock(&mmiotrace_mutex); |
diff --git a/include/linux/mmiotrace.h b/include/linux/mmiotrace.h index 3d1b7bde1283..97491f78b08c 100644 --- a/include/linux/mmiotrace.h +++ b/include/linux/mmiotrace.h | |||
@@ -30,6 +30,8 @@ extern unsigned int kmmio_count; | |||
30 | 30 | ||
31 | extern int register_kmmio_probe(struct kmmio_probe *p); | 31 | extern int register_kmmio_probe(struct kmmio_probe *p); |
32 | extern void unregister_kmmio_probe(struct kmmio_probe *p); | 32 | extern void unregister_kmmio_probe(struct kmmio_probe *p); |
33 | extern int kmmio_init(void); | ||
34 | extern void kmmio_cleanup(void); | ||
33 | 35 | ||
34 | #ifdef CONFIG_MMIOTRACE | 36 | #ifdef CONFIG_MMIOTRACE |
35 | /* kmmio is active by some kmmio_probes? */ | 37 | /* kmmio is active by some kmmio_probes? */ |