void kmemcheck_show(struct pt_regs *regs) { struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context); BUG_ON(!irqs_disabled()); if (unlikely(data->balance != 0)) { kmemcheck_show_all(); kmemcheck_error_save_bug(regs); data->balance = 0; return; } if (kmemcheck_show_all() == 0) return; ++data->balance; if (!(regs->flags & X86_EFLAGS_TF)) data->flags = regs->flags; regs->flags |= X86_EFLAGS_TF; regs->flags &= ~X86_EFLAGS_IF; }
/* * Called from the #DB handler. */ void kmemcheck_hide(struct pt_regs *regs) { struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context); int n; BUG_ON(!irqs_disabled()); if (unlikely(data->balance != 1)) { kmemcheck_show_all(); kmemcheck_error_save_bug(regs); data->n_addrs = 0; data->balance = 0; if (!(data->flags & X86_EFLAGS_TF)) regs->flags &= ~X86_EFLAGS_TF; if (data->flags & X86_EFLAGS_IF) regs->flags |= X86_EFLAGS_IF; return; } if (kmemcheck_enabled) n = kmemcheck_hide_all(); else n = kmemcheck_show_all(); if (n == 0) return; --data->balance; data->n_addrs = 0; if (!(data->flags & X86_EFLAGS_TF)) regs->flags &= ~X86_EFLAGS_TF; if (data->flags & X86_EFLAGS_IF) regs->flags |= X86_EFLAGS_IF; }
/* * Called from the #PF handler. */ void kmemcheck_show(struct pt_regs *regs) { struct kmemcheck_context *data = &__get_cpu_var(kmemcheck_context); BUG_ON(!irqs_disabled()); if (unlikely(data->balance != 0)) { kmemcheck_show_all(); kmemcheck_error_save_bug(regs); data->balance = 0; return; } /* * None of the addresses actually belonged to kmemcheck. Note that * this is not an error. */ if (kmemcheck_show_all() == 0) return; ++data->balance; /* * The IF needs to be cleared as well, so that the faulting * instruction can run "uninterrupted". Otherwise, we might take * an interrupt and start executing that before we've had a chance * to hide the page again. * * NOTE: In the rare case of multiple faults, we must not override * the original flags: */ if (!(regs->flags & X86_EFLAGS_TF)) data->flags = regs->flags; regs->flags |= X86_EFLAGS_TF; regs->flags &= ~X86_EFLAGS_IF; }