Re: [PATCH] x86: optionally show last exception from/to register contents (v2)
On Tuesday 28 August 2007 12:44:31 Jan Beulich wrote: > .. when dumping register state. This is particularly useful when gcc > managed to tail-call optimize an indirect call which happens to hit a > NULL (or otherwise invalid) pointer. I added it, with a warning in the documentation and changelog Also all the other patches except for the #DF one. Thanks. BTW I think there is a reasonable cheap way to avoid the interrupt race: If pda->irqcount was split into two 16bit words and irq entry code increases the upper 16bit word (that should be nearly free because because both are in L1 cache; with some luck the CPU can even dual-issue). Then the traps code could save the irq count early and then in the no_context case disable interrupts, compare and only print LER if there were no interrupts inbetween. -Andi - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents (v2)
On Tuesday 28 August 2007 12:44:31 Jan Beulich wrote: .. when dumping register state. This is particularly useful when gcc managed to tail-call optimize an indirect call which happens to hit a NULL (or otherwise invalid) pointer. I added it, with a warning in the documentation and changelog Also all the other patches except for the #DF one. Thanks. BTW I think there is a reasonable cheap way to avoid the interrupt race: If pda-irqcount was split into two 16bit words and irq entry code increases the upper 16bit word (that should be nearly free because because both are in L1 cache; with some luck the CPU can even dual-issue). Then the traps code could save the irq count early and then in the no_context case disable interrupts, compare and only print LER if there were no interrupts inbetween. -Andi - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86: optionally show last exception from/to register contents (v2)
.. when dumping register state. This is particularly useful when gcc managed to tail-call optimize an indirect call which happens to hit a NULL (or otherwise invalid) pointer. Signed-off-by: Jan Beulich <[EMAIL PROTECTED]> Documentation/kernel-parameters.txt |3 +++ arch/i386/kernel/cpu/amd.c |4 arch/i386/kernel/cpu/common.c |2 ++ arch/i386/kernel/cpu/intel.c| 20 ++-- arch/i386/kernel/traps.c| 35 +++ arch/x86_64/kernel/setup.c | 23 ++- arch/x86_64/kernel/traps.c | 34 ++ include/asm-i386/msr-index.h|3 +++ include/asm-i386/processor.h|4 include/asm-x86_64/msr.h|6 ++ include/asm-x86_64/processor.h |3 +++ 11 files changed, 126 insertions(+), 11 deletions(-) --- linux-2.6.23-rc4/Documentation/kernel-parameters.txt2007-08-28 09:41:55.0 +0200 +++ 2.6.23-rc4-x86-ler/Documentation/kernel-parameters.txt 2007-08-17 09:58:55.0 +0200 @@ -1155,6 +1155,9 @@ and is between 256 and 4096 characters. nolapic_timer [X86-32,APIC] Do not use the local APIC timer. + noler [X86-32/X86-64] Do not print last exception records + with kernel register dumps. + noltlbs [PPC] Do not use large page/tlb entries for kernel lowmem mapping on PPC40x. --- linux-2.6.23-rc4/arch/i386/kernel/cpu/amd.c 2007-08-28 09:41:58.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/cpu/amd.c 2007-08-17 10:02:17.0 +0200 @@ -238,9 +238,13 @@ static void __cpuinit init_amd(struct cp case 0x10: case 0x11: set_bit(X86_FEATURE_K8, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; case 6: set_bit(X86_FEATURE_K7, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; } if (c->x86 >= 6) --- linux-2.6.23-rc4/arch/i386/kernel/cpu/common.c 2007-08-28 09:41:58.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/cpu/common.c2007-08-07 10:42:55.0 +0200 @@ -503,6 +503,8 @@ static void __cpuinit identify_cpu(struc /* Init Machine Check Exception if available. */ mcheck_init(c); + + ler_enable(); } void __init identify_boot_cpu(void) --- linux-2.6.23-rc4/arch/i386/kernel/cpu/intel.c 2007-07-09 01:32:17.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/cpu/intel.c 2007-08-07 10:42:55.0 +0200 @@ -188,15 +188,23 @@ static void __cpuinit init_intel(struct } #endif - if (c->x86 == 15) { + switch (c->x86) { + case 15: set_bit(X86_FEATURE_P4, c->x86_capability); set_bit(X86_FEATURE_SYNC_RDTSC, c->x86_capability); - } - if (c->x86 == 6) + if (c->x86_model >= 0x03) + set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_P4_LER_FROM_LIP; + break; + case 6: set_bit(X86_FEATURE_P3, c->x86_capability); - if ((c->x86 == 0xf && c->x86_model >= 0x03) || - (c->x86 == 0x6 && c->x86_model >= 0x0e)) - set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + if (c->x86_model >= 0x0e) + set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; + break; + } if (cpu_has_ds) { unsigned int l1; --- linux-2.6.23-rc4/arch/i386/kernel/traps.c 2007-08-28 09:41:58.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/traps.c 2007-08-17 14:26:08.0 +0200 @@ -321,6 +321,20 @@ void show_registers(struct pt_regs *regs unsigned int code_len = code_bytes; unsigned char c; + if (oops_in_progress && __get_cpu_var(ler_msr)) { + u32 from, to, hi; + + if (rdmsr_safe(__get_cpu_var(ler_msr), , ) == 0 + && rdmsr_safe(__get_cpu_var(ler_msr) + 1, , ) == 0) { + printk("\n" KERN_EMERG + "last branch before last exception/interrupt\n"); + printk(KERN_EMERG " from %08x", from); + print_symbol(" (%s)\n", from); + printk(KERN_EMERG " to %08x", to); + print_symbol(" (%s)", to); + } else +
[PATCH] x86: optionally show last exception from/to register contents (v2)
.. when dumping register state. This is particularly useful when gcc managed to tail-call optimize an indirect call which happens to hit a NULL (or otherwise invalid) pointer. Signed-off-by: Jan Beulich [EMAIL PROTECTED] Documentation/kernel-parameters.txt |3 +++ arch/i386/kernel/cpu/amd.c |4 arch/i386/kernel/cpu/common.c |2 ++ arch/i386/kernel/cpu/intel.c| 20 ++-- arch/i386/kernel/traps.c| 35 +++ arch/x86_64/kernel/setup.c | 23 ++- arch/x86_64/kernel/traps.c | 34 ++ include/asm-i386/msr-index.h|3 +++ include/asm-i386/processor.h|4 include/asm-x86_64/msr.h|6 ++ include/asm-x86_64/processor.h |3 +++ 11 files changed, 126 insertions(+), 11 deletions(-) --- linux-2.6.23-rc4/Documentation/kernel-parameters.txt2007-08-28 09:41:55.0 +0200 +++ 2.6.23-rc4-x86-ler/Documentation/kernel-parameters.txt 2007-08-17 09:58:55.0 +0200 @@ -1155,6 +1155,9 @@ and is between 256 and 4096 characters. nolapic_timer [X86-32,APIC] Do not use the local APIC timer. + noler [X86-32/X86-64] Do not print last exception records + with kernel register dumps. + noltlbs [PPC] Do not use large page/tlb entries for kernel lowmem mapping on PPC40x. --- linux-2.6.23-rc4/arch/i386/kernel/cpu/amd.c 2007-08-28 09:41:58.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/cpu/amd.c 2007-08-17 10:02:17.0 +0200 @@ -238,9 +238,13 @@ static void __cpuinit init_amd(struct cp case 0x10: case 0x11: set_bit(X86_FEATURE_K8, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; case 6: set_bit(X86_FEATURE_K7, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; } if (c-x86 = 6) --- linux-2.6.23-rc4/arch/i386/kernel/cpu/common.c 2007-08-28 09:41:58.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/cpu/common.c2007-08-07 10:42:55.0 +0200 @@ -503,6 +503,8 @@ static void __cpuinit identify_cpu(struc /* Init Machine Check Exception if available. */ mcheck_init(c); + + ler_enable(); } void __init identify_boot_cpu(void) --- linux-2.6.23-rc4/arch/i386/kernel/cpu/intel.c 2007-07-09 01:32:17.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/cpu/intel.c 2007-08-07 10:42:55.0 +0200 @@ -188,15 +188,23 @@ static void __cpuinit init_intel(struct } #endif - if (c-x86 == 15) { + switch (c-x86) { + case 15: set_bit(X86_FEATURE_P4, c-x86_capability); set_bit(X86_FEATURE_SYNC_RDTSC, c-x86_capability); - } - if (c-x86 == 6) + if (c-x86_model = 0x03) + set_bit(X86_FEATURE_CONSTANT_TSC, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_P4_LER_FROM_LIP; + break; + case 6: set_bit(X86_FEATURE_P3, c-x86_capability); - if ((c-x86 == 0xf c-x86_model = 0x03) || - (c-x86 == 0x6 c-x86_model = 0x0e)) - set_bit(X86_FEATURE_CONSTANT_TSC, c-x86_capability); + if (c-x86_model = 0x0e) + set_bit(X86_FEATURE_CONSTANT_TSC, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; + break; + } if (cpu_has_ds) { unsigned int l1; --- linux-2.6.23-rc4/arch/i386/kernel/traps.c 2007-08-28 09:41:58.0 +0200 +++ 2.6.23-rc4-x86-ler/arch/i386/kernel/traps.c 2007-08-17 14:26:08.0 +0200 @@ -321,6 +321,20 @@ void show_registers(struct pt_regs *regs unsigned int code_len = code_bytes; unsigned char c; + if (oops_in_progress __get_cpu_var(ler_msr)) { + u32 from, to, hi; + + if (rdmsr_safe(__get_cpu_var(ler_msr), from, hi) == 0 +rdmsr_safe(__get_cpu_var(ler_msr) + 1, to, hi) == 0) { + printk(\n KERN_EMERG + last branch before last exception/interrupt\n); + printk(KERN_EMERG from %08x, from); + print_symbol( (%s)\n, from); + printk(KERN_EMERG to %08x, to); + print_symbol( (%s), to); + } else + __get_cpu_var(ler_msr) = 0; +
Re: [PATCH] x86: optionally show last exception from/to register contents
On Mon, 13 Aug 2007 16:21:10 +0200 Andi Kleen wrote: > > I though you did, but since I never saw it appear in any release, I posted > > this one... > > It's a little different (and somewhat hackish I admit) > ftp://firstfloor.org/pub/ak/x86_64/debug/last-branch > It has far more overhead than yours of course. > > The only way to merge something like that would be dynamic > patching and I was never quite motivated for that. > > > So especially with the first concern of yours - is it worth at all rev-ing > > this > > patch to address the other change requests you voiced? > > The patch is useful even with the race, just document somewhere > that it is unreliable (perhaps in the printk itself) and do the > other changes. and add "ler" entry to Documentation/kernel-parameters.txt, please, with what it means. > I would also suggest to enable it by default. --- ~Randy *** Remember to use Documentation/SubmitChecklist when testing your code *** - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
Andi Kleen (on Mon, 13 Aug 2007 15:08:45 +0200) wrote: >On Mon, Aug 13, 2007 at 12:33:05PM +0100, Jan Beulich wrote: > > >> >> if (cpu_has_ds) { >> unsigned int l1; >> --- linux-2.6.23-rc3/arch/i386/kernel/traps.c2007-08-13 >> 08:59:45.0 +0200 >> +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/traps.c 2007-08-07 >> 10:42:55.0 +0200 >> @@ -321,6 +321,13 @@ void show_registers(struct pt_regs *regs >> unsigned int code_len = code_bytes; >> unsigned char c; >> >> +if (__get_cpu_var(ler_msr)) { >> +u32 from, to, hi; >> + >> +rdmsr(__get_cpu_var(ler_msr), from, hi); >> +rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); >> +printk("LER: %08x -> %08x\n", from, to); >> +} > >This seems racy -- AFAIK the MSR will record the last branch >before an interrupt too, and the trap handlers enable interrupts >before coming here. > >Can't think of a good way to avoid that for page fault at least >without impacting interrupt latency or reading the MSR always. KDB used to have a "last branch recording" (lbr) feature. The page fault handler was modified to disable lbr before entering do_page_fault(). Nobody seemed to care about the slight slowdown but also nobody seemed to be using that feature for debugging, we rarely get wild branches into the middle of nowhere. lbr was messy to maintain for very little gain, so I removed it from KDB at 2.6.17-i386-2. - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
> I though you did, but since I never saw it appear in any release, I posted > this one... It's a little different (and somewhat hackish I admit) ftp://firstfloor.org/pub/ak/x86_64/debug/last-branch It has far more overhead than yours of course. The only way to merge something like that would be dynamic patching and I was never quite motivated for that. > So especially with the first concern of yours - is it worth at all rev-ing > this > patch to address the other change requests you voiced? The patch is useful even with the race, just document somewhere that it is unreliable (perhaps in the printk itself) and do the other changes. I would also suggest to enable it by default. -Andi - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
>>> Andi Kleen <[EMAIL PROTECTED]> 13.08.07 15:08 >>> >On Mon, Aug 13, 2007 at 12:33:05PM +0100, Jan Beulich wrote: >> +if (__get_cpu_var(ler_msr)) { >> +u32 from, to, hi; >> + >> +rdmsr(__get_cpu_var(ler_msr), from, hi); >> +rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); >> +printk("LER: %08x -> %08x\n", from, to); >> +} > >This seems racy -- AFAIK the MSR will record the last branch >before an interrupt too, and the trap handlers enable interrupts >before coming here. > >Can't think of a good way to avoid that for page fault at least >without impacting interrupt latency or reading the MSR always. That's the problem. Other than either going through interrupt gates *and* keeping interrupts disabled long enough, there's nothing you can do, except turning of tracing before re-enabling interrupts, which in turn you would likely reject because of the performance overhead of the necessary rdmsr/wrmsr pair. >The other thing is that this should use print_symbol() I considered this, but decided against it due to the address pair being displayed. But I could certainly change that. >> @@ -360,6 +367,18 @@ int is_valid_bugaddr(unsigned long eip) >> return ud2 == 0x0b0f; >> } >> >> +DEFINE_PER_CPU(u32, ler_msr); >> +int ler_enabled = 0; >> + >> +void ler_enable(void) { >> +if (__get_cpu_var(ler_msr)) { >> +u64 debugctl; >> + >> +rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); >> +wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); > >Better use checking_rd/wrmsrl and disable on fail -- often emulators >fake specific CPUs, but don't implement all debugging features. Okay, if you consider emulators important here (this is one of the reasons for having to turn on the feature via command line option). >> +static int __init ler_setup(char *s) >> +{ >> +ler_enabled = 1; >> +return 1; >> +} >> +__setup("ler", ler_setup); > >I don't think the option is very useful. Apart from the above, I assume it's also useful initially to avoid boot problems in case the model->msr mapping isn't fully cooked, yet (obviously I don't have machines with all the different CPU families/models around to test, so the coding of what I wasn't able to test is purely based on the manuals). >BTW I have a patch somewhere to save/report last branch on exception >too, but it never seemed suitable for mainline because of its I though you did, but since I never saw it appear in any release, I posted this one... So especially with the first concern of yours - is it worth at all rev-ing this patch to address the other change requests you voiced? >high overhead. If someone submitted a full BTS driver I would >be tempted though :) That shouldn't be too difficult. Jan - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
On Mon, Aug 13, 2007 at 12:33:05PM +0100, Jan Beulich wrote: > > if (cpu_has_ds) { > unsigned int l1; > --- linux-2.6.23-rc3/arch/i386/kernel/traps.c 2007-08-13 08:59:45.0 > +0200 > +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/traps.c 2007-08-07 > 10:42:55.0 +0200 > @@ -321,6 +321,13 @@ void show_registers(struct pt_regs *regs > unsigned int code_len = code_bytes; > unsigned char c; > > + if (__get_cpu_var(ler_msr)) { > + u32 from, to, hi; > + > + rdmsr(__get_cpu_var(ler_msr), from, hi); > + rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); > + printk("LER: %08x -> %08x\n", from, to); > + } This seems racy -- AFAIK the MSR will record the last branch before an interrupt too, and the trap handlers enable interrupts before coming here. Can't think of a good way to avoid that for page fault at least without impacting interrupt latency or reading the MSR always. The other thing is that this should use print_symbol() > printk("\n" KERN_EMERG "Stack: "); > show_stack_log_lvl(NULL, regs, (unsigned long *)esp, > KERN_EMERG); > > @@ -360,6 +367,18 @@ int is_valid_bugaddr(unsigned long eip) > return ud2 == 0x0b0f; > } > > +DEFINE_PER_CPU(u32, ler_msr); > +int ler_enabled = 0; > + > +void ler_enable(void) { > + if (__get_cpu_var(ler_msr)) { > + u64 debugctl; > + > + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); > + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); Better use checking_rd/wrmsrl and disable on fail -- often emulators fake specific CPUs, but don't implement all debugging features. > +static int __init ler_setup(char *s) > +{ > + ler_enabled = 1; > + return 1; > +} > +__setup("ler", ler_setup); I don't think the option is very useful. BTW I have a patch somewhere to save/report last branch on exception too, but it never seemed suitable for mainline because of its high overhead. If someone submitted a full BTS driver I would be tempted though :) -Andi - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] x86: optionally show last exception from/to register contents
.. when dumping register state. This is particularly useful when gcc managed to tail-call optimize an indirect call which happens to hit a NULL (or otherwise invalid) pointer. Signed-off-by: Jan Beulich <[EMAIL PROTECTED]> arch/i386/kernel/cpu/amd.c |4 arch/i386/kernel/cpu/common.c |2 ++ arch/i386/kernel/cpu/intel.c | 20 ++-- arch/i386/kernel/traps.c | 27 +++ arch/x86_64/kernel/setup.c | 23 ++- arch/x86_64/kernel/traps.c | 27 +++ include/asm-i386/msr-index.h |3 +++ include/asm-i386/processor.h |4 include/asm-x86_64/processor.h |3 +++ 9 files changed, 102 insertions(+), 11 deletions(-) --- linux-2.6.23-rc3/arch/i386/kernel/cpu/amd.c 2007-08-13 08:59:44.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/cpu/amd.c 2007-08-07 10:42:55.0 +0200 @@ -238,9 +238,13 @@ static void __cpuinit init_amd(struct cp case 0x10: case 0x11: set_bit(X86_FEATURE_K8, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; case 6: set_bit(X86_FEATURE_K7, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; } if (c->x86 >= 6) --- linux-2.6.23-rc3/arch/i386/kernel/cpu/common.c 2007-08-13 08:59:44.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/cpu/common.c2007-08-07 10:42:55.0 +0200 @@ -503,6 +503,8 @@ static void __cpuinit identify_cpu(struc /* Init Machine Check Exception if available. */ mcheck_init(c); + + ler_enable(); } void __init identify_boot_cpu(void) --- linux-2.6.23-rc3/arch/i386/kernel/cpu/intel.c 2007-07-09 01:32:17.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/cpu/intel.c 2007-08-07 10:42:55.0 +0200 @@ -188,15 +188,23 @@ static void __cpuinit init_intel(struct } #endif - if (c->x86 == 15) { + switch (c->x86) { + case 15: set_bit(X86_FEATURE_P4, c->x86_capability); set_bit(X86_FEATURE_SYNC_RDTSC, c->x86_capability); - } - if (c->x86 == 6) + if (c->x86_model >= 0x03) + set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_P4_LER_FROM_LIP; + break; + case 6: set_bit(X86_FEATURE_P3, c->x86_capability); - if ((c->x86 == 0xf && c->x86_model >= 0x03) || - (c->x86 == 0x6 && c->x86_model >= 0x0e)) - set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + if (c->x86_model >= 0x0e) + set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; + break; + } if (cpu_has_ds) { unsigned int l1; --- linux-2.6.23-rc3/arch/i386/kernel/traps.c 2007-08-13 08:59:45.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/traps.c 2007-08-07 10:42:55.0 +0200 @@ -321,6 +321,13 @@ void show_registers(struct pt_regs *regs unsigned int code_len = code_bytes; unsigned char c; + if (__get_cpu_var(ler_msr)) { + u32 from, to, hi; + + rdmsr(__get_cpu_var(ler_msr), from, hi); + rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); + printk("LER: %08x -> %08x\n", from, to); + } printk("\n" KERN_EMERG "Stack: "); show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG); @@ -360,6 +367,18 @@ int is_valid_bugaddr(unsigned long eip) return ud2 == 0x0b0f; } +DEFINE_PER_CPU(u32, ler_msr); +int ler_enabled = 0; + +void ler_enable(void) { + if (__get_cpu_var(ler_msr)) { + u64 debugctl; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); + } +} + /* * This is gone through when something in the kernel has done something bad and * is about to be terminated. @@ -846,6 +865,7 @@ fastcall void __kprobes do_debug(struct struct task_struct *tsk = current; get_debugreg(condition, 6); + ler_enable(); if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, SIGTRAP) == NOTIFY_STOP) @@ -1239,3 +1259,10 @@ static int __init code_bytes_setup(char return 1; } __setup("code_bytes=", code_bytes_setup); + +static int __init ler_setup(char *s) +{ + ler_enabled = 1; + return 1; +} +__setup("ler", ler_setup); ---
[PATCH] x86: optionally show last exception from/to register contents
.. when dumping register state. This is particularly useful when gcc managed to tail-call optimize an indirect call which happens to hit a NULL (or otherwise invalid) pointer. Signed-off-by: Jan Beulich [EMAIL PROTECTED] arch/i386/kernel/cpu/amd.c |4 arch/i386/kernel/cpu/common.c |2 ++ arch/i386/kernel/cpu/intel.c | 20 ++-- arch/i386/kernel/traps.c | 27 +++ arch/x86_64/kernel/setup.c | 23 ++- arch/x86_64/kernel/traps.c | 27 +++ include/asm-i386/msr-index.h |3 +++ include/asm-i386/processor.h |4 include/asm-x86_64/processor.h |3 +++ 9 files changed, 102 insertions(+), 11 deletions(-) --- linux-2.6.23-rc3/arch/i386/kernel/cpu/amd.c 2007-08-13 08:59:44.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/cpu/amd.c 2007-08-07 10:42:55.0 +0200 @@ -238,9 +238,13 @@ static void __cpuinit init_amd(struct cp case 0x10: case 0x11: set_bit(X86_FEATURE_K8, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; case 6: set_bit(X86_FEATURE_K7, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; break; } if (c-x86 = 6) --- linux-2.6.23-rc3/arch/i386/kernel/cpu/common.c 2007-08-13 08:59:44.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/cpu/common.c2007-08-07 10:42:55.0 +0200 @@ -503,6 +503,8 @@ static void __cpuinit identify_cpu(struc /* Init Machine Check Exception if available. */ mcheck_init(c); + + ler_enable(); } void __init identify_boot_cpu(void) --- linux-2.6.23-rc3/arch/i386/kernel/cpu/intel.c 2007-07-09 01:32:17.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/cpu/intel.c 2007-08-07 10:42:55.0 +0200 @@ -188,15 +188,23 @@ static void __cpuinit init_intel(struct } #endif - if (c-x86 == 15) { + switch (c-x86) { + case 15: set_bit(X86_FEATURE_P4, c-x86_capability); set_bit(X86_FEATURE_SYNC_RDTSC, c-x86_capability); - } - if (c-x86 == 6) + if (c-x86_model = 0x03) + set_bit(X86_FEATURE_CONSTANT_TSC, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_P4_LER_FROM_LIP; + break; + case 6: set_bit(X86_FEATURE_P3, c-x86_capability); - if ((c-x86 == 0xf c-x86_model = 0x03) || - (c-x86 == 0x6 c-x86_model = 0x0e)) - set_bit(X86_FEATURE_CONSTANT_TSC, c-x86_capability); + if (c-x86_model = 0x0e) + set_bit(X86_FEATURE_CONSTANT_TSC, c-x86_capability); + if (ler_enabled) + __get_cpu_var(ler_msr) = MSR_IA32_LASTINTFROMIP; + break; + } if (cpu_has_ds) { unsigned int l1; --- linux-2.6.23-rc3/arch/i386/kernel/traps.c 2007-08-13 08:59:45.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/traps.c 2007-08-07 10:42:55.0 +0200 @@ -321,6 +321,13 @@ void show_registers(struct pt_regs *regs unsigned int code_len = code_bytes; unsigned char c; + if (__get_cpu_var(ler_msr)) { + u32 from, to, hi; + + rdmsr(__get_cpu_var(ler_msr), from, hi); + rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); + printk(LER: %08x - %08x\n, from, to); + } printk(\n KERN_EMERG Stack: ); show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG); @@ -360,6 +367,18 @@ int is_valid_bugaddr(unsigned long eip) return ud2 == 0x0b0f; } +DEFINE_PER_CPU(u32, ler_msr); +int ler_enabled = 0; + +void ler_enable(void) { + if (__get_cpu_var(ler_msr)) { + u64 debugctl; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); + } +} + /* * This is gone through when something in the kernel has done something bad and * is about to be terminated. @@ -846,6 +865,7 @@ fastcall void __kprobes do_debug(struct struct task_struct *tsk = current; get_debugreg(condition, 6); + ler_enable(); if (notify_die(DIE_DEBUG, debug, regs, condition, error_code, SIGTRAP) == NOTIFY_STOP) @@ -1239,3 +1259,10 @@ static int __init code_bytes_setup(char return 1; } __setup(code_bytes=, code_bytes_setup); + +static int __init ler_setup(char *s) +{ + ler_enabled = 1; + return 1; +} +__setup(ler, ler_setup); --- linux-2.6.23-rc3/arch/x86_64/kernel/setup.c
Re: [PATCH] x86: optionally show last exception from/to register contents
On Mon, Aug 13, 2007 at 12:33:05PM +0100, Jan Beulich wrote: if (cpu_has_ds) { unsigned int l1; --- linux-2.6.23-rc3/arch/i386/kernel/traps.c 2007-08-13 08:59:45.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/traps.c 2007-08-07 10:42:55.0 +0200 @@ -321,6 +321,13 @@ void show_registers(struct pt_regs *regs unsigned int code_len = code_bytes; unsigned char c; + if (__get_cpu_var(ler_msr)) { + u32 from, to, hi; + + rdmsr(__get_cpu_var(ler_msr), from, hi); + rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); + printk(LER: %08x - %08x\n, from, to); + } This seems racy -- AFAIK the MSR will record the last branch before an interrupt too, and the trap handlers enable interrupts before coming here. Can't think of a good way to avoid that for page fault at least without impacting interrupt latency or reading the MSR always. The other thing is that this should use print_symbol() printk(\n KERN_EMERG Stack: ); show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG); @@ -360,6 +367,18 @@ int is_valid_bugaddr(unsigned long eip) return ud2 == 0x0b0f; } +DEFINE_PER_CPU(u32, ler_msr); +int ler_enabled = 0; + +void ler_enable(void) { + if (__get_cpu_var(ler_msr)) { + u64 debugctl; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); Better use checking_rd/wrmsrl and disable on fail -- often emulators fake specific CPUs, but don't implement all debugging features. +static int __init ler_setup(char *s) +{ + ler_enabled = 1; + return 1; +} +__setup(ler, ler_setup); I don't think the option is very useful. BTW I have a patch somewhere to save/report last branch on exception too, but it never seemed suitable for mainline because of its high overhead. If someone submitted a full BTS driver I would be tempted though :) -Andi - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
I though you did, but since I never saw it appear in any release, I posted this one... It's a little different (and somewhat hackish I admit) ftp://firstfloor.org/pub/ak/x86_64/debug/last-branch It has far more overhead than yours of course. The only way to merge something like that would be dynamic patching and I was never quite motivated for that. So especially with the first concern of yours - is it worth at all rev-ing this patch to address the other change requests you voiced? The patch is useful even with the race, just document somewhere that it is unreliable (perhaps in the printk itself) and do the other changes. I would also suggest to enable it by default. -Andi - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
Andi Kleen [EMAIL PROTECTED] 13.08.07 15:08 On Mon, Aug 13, 2007 at 12:33:05PM +0100, Jan Beulich wrote: +if (__get_cpu_var(ler_msr)) { +u32 from, to, hi; + +rdmsr(__get_cpu_var(ler_msr), from, hi); +rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); +printk(LER: %08x - %08x\n, from, to); +} This seems racy -- AFAIK the MSR will record the last branch before an interrupt too, and the trap handlers enable interrupts before coming here. Can't think of a good way to avoid that for page fault at least without impacting interrupt latency or reading the MSR always. That's the problem. Other than either going through interrupt gates *and* keeping interrupts disabled long enough, there's nothing you can do, except turning of tracing before re-enabling interrupts, which in turn you would likely reject because of the performance overhead of the necessary rdmsr/wrmsr pair. The other thing is that this should use print_symbol() I considered this, but decided against it due to the address pair being displayed. But I could certainly change that. @@ -360,6 +367,18 @@ int is_valid_bugaddr(unsigned long eip) return ud2 == 0x0b0f; } +DEFINE_PER_CPU(u32, ler_msr); +int ler_enabled = 0; + +void ler_enable(void) { +if (__get_cpu_var(ler_msr)) { +u64 debugctl; + +rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); +wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 1); Better use checking_rd/wrmsrl and disable on fail -- often emulators fake specific CPUs, but don't implement all debugging features. Okay, if you consider emulators important here (this is one of the reasons for having to turn on the feature via command line option). +static int __init ler_setup(char *s) +{ +ler_enabled = 1; +return 1; +} +__setup(ler, ler_setup); I don't think the option is very useful. Apart from the above, I assume it's also useful initially to avoid boot problems in case the model-msr mapping isn't fully cooked, yet (obviously I don't have machines with all the different CPU families/models around to test, so the coding of what I wasn't able to test is purely based on the manuals). BTW I have a patch somewhere to save/report last branch on exception too, but it never seemed suitable for mainline because of its I though you did, but since I never saw it appear in any release, I posted this one... So especially with the first concern of yours - is it worth at all rev-ing this patch to address the other change requests you voiced? high overhead. If someone submitted a full BTS driver I would be tempted though :) That shouldn't be too difficult. Jan - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
Andi Kleen (on Mon, 13 Aug 2007 15:08:45 +0200) wrote: On Mon, Aug 13, 2007 at 12:33:05PM +0100, Jan Beulich wrote: if (cpu_has_ds) { unsigned int l1; --- linux-2.6.23-rc3/arch/i386/kernel/traps.c2007-08-13 08:59:45.0 +0200 +++ 2.6.23-rc3-x86-ler/arch/i386/kernel/traps.c 2007-08-07 10:42:55.0 +0200 @@ -321,6 +321,13 @@ void show_registers(struct pt_regs *regs unsigned int code_len = code_bytes; unsigned char c; +if (__get_cpu_var(ler_msr)) { +u32 from, to, hi; + +rdmsr(__get_cpu_var(ler_msr), from, hi); +rdmsr(__get_cpu_var(ler_msr) + 1, to, hi); +printk(LER: %08x - %08x\n, from, to); +} This seems racy -- AFAIK the MSR will record the last branch before an interrupt too, and the trap handlers enable interrupts before coming here. Can't think of a good way to avoid that for page fault at least without impacting interrupt latency or reading the MSR always. KDB used to have a last branch recording (lbr) feature. The page fault handler was modified to disable lbr before entering do_page_fault(). Nobody seemed to care about the slight slowdown but also nobody seemed to be using that feature for debugging, we rarely get wild branches into the middle of nowhere. lbr was messy to maintain for very little gain, so I removed it from KDB at 2.6.17-i386-2. - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] x86: optionally show last exception from/to register contents
On Mon, 13 Aug 2007 16:21:10 +0200 Andi Kleen wrote: I though you did, but since I never saw it appear in any release, I posted this one... It's a little different (and somewhat hackish I admit) ftp://firstfloor.org/pub/ak/x86_64/debug/last-branch It has far more overhead than yours of course. The only way to merge something like that would be dynamic patching and I was never quite motivated for that. So especially with the first concern of yours - is it worth at all rev-ing this patch to address the other change requests you voiced? The patch is useful even with the race, just document somewhere that it is unreliable (perhaps in the printk itself) and do the other changes. and add ler entry to Documentation/kernel-parameters.txt, please, with what it means. I would also suggest to enable it by default. --- ~Randy *** Remember to use Documentation/SubmitChecklist when testing your code *** - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/