Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1031140Ab2HIPkz (ORCPT ); Thu, 9 Aug 2012 11:40:55 -0400 Received: from mail.x86-64.org ([217.9.48.20]:47647 "EHLO mail.x86-64.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1030774Ab2HIPkx (ORCPT ); Thu, 9 Aug 2012 11:40:53 -0400 From: Borislav Petkov To: LKML , linux-arch@vger.kernel.org Cc: Borislav Petkov , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Greg Kroah-Hartman , Arnd Bergmann , Jan Beulich , Frederic Weisbecker , "Paul E. McKenney" , Josh Triplett Subject: [RFC PATCH] sysrq: Show architectural registers Date: Thu, 9 Aug 2012 17:40:46 +0200 Message-Id: <1344526846-31905-1-git-send-email-bp@amd64.org> X-Mailer: git-send-email 1.7.11.rc1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8635 Lines: 251 From: Borislav Petkov One day I was playing with disabling the caches over CR0.CD and I wanted to check the current setting of the CD bit but there wasn't a way to do so from userspace because we #GP when accessing CR0. And then I thought, well, sysrq must have this. And it does: $ echo p > /proc/sysrq-trigger dumps the current registers. However, we don't dump the registers when we can't get the last exception frame through get_irq_regs(). But, there are registers (CR0 included) which aren't in the exception frame and which can be dumped regardless. This patch does exactly that; with it, the output looks like this: [ 1759.206042] SysRq : Show Regs [ 1759.209194] FS: 00007fb1eada3700(0000) GS:ffff880c27c00000(0000) knlGS:0000000000000000 [ 1759.217593] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1759.223554] CR2: 0000000000910390 CR3: 0000001020b48000 CR4: 00000000000007e0 [ 1759.230956] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1759.244974] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 1759.259052] CPU#18: active: 0000000000000000 [ 1759.270539] CPU#18: gen-PMC0 ctrl: 0000030e011afcf6 [ 1759.270543] CPU#18: gen-PMC0 count: 00009007d003b500 [ 1759.270545] CPU#18: gen-PMC0 left: 0000000000000000 [ 1759.270548] CPU#18: gen-PMC1 ctrl: 0000030f059b7efc [ 1759.270550] CPU#18: gen-PMC1 count: 00008003c823b4a0 [ 1759.270552] CPU#18: gen-PMC1 left: 0000000000000000 [ 1759.270555] CPU#18: gen-PMC2 ctrl: 00000104fe97c87c [ 1759.270557] CPU#18: gen-PMC2 count: 00007c6277e7f5fe [ 1759.270560] CPU#18: gen-PMC2 left: 0000000000000000 [ 1759.270562] CPU#18: gen-PMC3 ctrl: 000000040000f0e2 [ 1759.270564] CPU#18: gen-PMC3 count: 0000000000000000 [ 1759.270566] CPU#18: gen-PMC3 left: 0000000000000000 Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Greg Kroah-Hartman Cc: Arnd Bergmann Cc: Jan Beulich Cc: Frederic Weisbecker Cc: "Paul E. McKenney" Cc: Josh Triplett Signed-off-by: Borislav Petkov --- arch/x86/include/asm/bug.h | 3 +++ arch/x86/kernel/process_32.c | 43 ++++++++++++++++++++++------------------ arch/x86/kernel/process_64.c | 47 ++++++++++++++++++++++++-------------------- drivers/tty/sysrq.c | 1 + include/asm-generic/bug.h | 9 +++++++++ 5 files changed, 63 insertions(+), 40 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 11e1152222d0..e60cf51fdfbd 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -35,6 +35,9 @@ do { \ #endif /* !CONFIG_BUG */ +extern void _arch_show_regs(void); +#define _arch_show_regs _arch_show_regs + #include diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 516fa186121b..6b01b6260f5d 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -66,10 +66,32 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return ((unsigned long *)tsk->thread.sp)[3]; } -void __show_regs(struct pt_regs *regs, int all) +void _arch_show_regs(void) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; unsigned long d0, d1, d2, d3, d6, d7; + + cr0 = read_cr0(); + cr2 = read_cr2(); + cr3 = read_cr3(); + cr4 = read_cr4_safe(); + printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", + cr0, cr2, cr3, cr4); + + get_debugreg(d0, 0); + get_debugreg(d1, 1); + get_debugreg(d2, 2); + get_debugreg(d3, 3); + printk(KERN_DEFAULT "DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", + d0, d1, d2, d3); + + get_debugreg(d6, 6); + get_debugreg(d7, 7); + printk(KERN_DEFAULT "DR6: %08lx DR7: %08lx\n", d6, d7); +} + +void __show_regs(struct pt_regs *regs, int all) +{ unsigned long sp; unsigned short ss, gs; @@ -100,24 +122,7 @@ void __show_regs(struct pt_regs *regs, int all) if (!all) return; - cr0 = read_cr0(); - cr2 = read_cr2(); - cr3 = read_cr3(); - cr4 = read_cr4_safe(); - printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", - cr0, cr2, cr3, cr4); - - get_debugreg(d0, 0); - get_debugreg(d1, 1); - get_debugreg(d2, 2); - get_debugreg(d3, 3); - printk(KERN_DEFAULT "DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", - d0, d1, d2, d3); - - get_debugreg(d6, 6); - get_debugreg(d7, 7); - printk(KERN_DEFAULT "DR6: %08lx DR7: %08lx\n", - d6, d7); + _arch_show_regs(); } void release_thread(struct task_struct *dead_task) diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 0a980c9d7cb8..dbe93bae6524 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -54,30 +54,14 @@ asmlinkage extern void ret_from_fork(void); DEFINE_PER_CPU(unsigned long, old_rsp); -/* Prints also some state that isn't saved in the pt_regs */ -void __show_regs(struct pt_regs *regs, int all) +/* Print also some state that isn't saved in the pt_regs */ +void _arch_show_regs(void) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; unsigned long d0, d1, d2, d3, d6, d7; unsigned int fsindex, gsindex; unsigned int ds, cs, es; - show_regs_common(); - printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); - printk_address(regs->ip, 1); - printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, - regs->sp, regs->flags); - printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n", - regs->ax, regs->bx, regs->cx); - printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n", - regs->dx, regs->si, regs->di); - printk(KERN_DEFAULT "RBP: %016lx R08: %016lx R09: %016lx\n", - regs->bp, regs->r8, regs->r9); - printk(KERN_DEFAULT "R10: %016lx R11: %016lx R12: %016lx\n", - regs->r10, regs->r11, regs->r12); - printk(KERN_DEFAULT "R13: %016lx R14: %016lx R15: %016lx\n", - regs->r13, regs->r14, regs->r15); - asm("movl %%ds,%0" : "=r" (ds)); asm("movl %%cs,%0" : "=r" (cs)); asm("movl %%es,%0" : "=r" (es)); @@ -88,9 +72,6 @@ void __show_regs(struct pt_regs *regs, int all) rdmsrl(MSR_GS_BASE, gs); rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); - if (!all) - return; - cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); @@ -113,6 +94,30 @@ void __show_regs(struct pt_regs *regs, int all) printk(KERN_DEFAULT "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); } +void __show_regs(struct pt_regs *regs, int all) +{ + show_regs_common(); + printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); + printk_address(regs->ip, 1); + printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, + regs->sp, regs->flags); + printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n", + regs->ax, regs->bx, regs->cx); + printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n", + regs->dx, regs->si, regs->di); + printk(KERN_DEFAULT "RBP: %016lx R08: %016lx R09: %016lx\n", + regs->bp, regs->r8, regs->r9); + printk(KERN_DEFAULT "R10: %016lx R11: %016lx R12: %016lx\n", + regs->r10, regs->r11, regs->r12); + printk(KERN_DEFAULT "R13: %016lx R14: %016lx R15: %016lx\n", + regs->r13, regs->r14, regs->r15); + + if (!all) + return; + + _arch_show_regs(); +} + void release_thread(struct task_struct *dead_task) { if (dead_task->mm) { diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 05728894a88c..4ad0f884e08e 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -254,6 +254,7 @@ static void sysrq_handle_showregs(int key) struct pt_regs *regs = get_irq_regs(); if (regs) show_regs(regs); + arch_show_regs(); perf_event_print_debug(); } static struct sysrq_key_op sysrq_showregs_op = { diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 7d10f962aa13..e96d6c31c222 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -202,6 +202,15 @@ extern void warn_slowpath_null(const char *file, const int line); # define WARN_ON_SMP(x) ({0;}) #endif +#ifdef _arch_show_regs +static inline void arch_show_regs(void) +{ + _arch_show_regs(); +} +#else +static inline void arch_show_regs(void) { } +#endif + #endif /* __ASSEMBLY__ */ #endif -- 1.7.11.rc1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/