Messages in this thread | | | Date | Thu, 19 Apr 2012 15:02:40 +0200 | From | Borislav Petkov <> | Subject | Re: [PATCH 4/5] x86-64: Handle exception table entries during early boot |
| |
On Wed, Apr 18, 2012 at 05:16:49PM -0700, H. Peter Anvin wrote: > From: "H. Peter Anvin" <hpa@zytor.com> > > If we get an exception during early boot, walk the exception table to > see if we should intercept it. The main use case for this is to allow > rdmsr_safe()/wrmsr_safe() during CPU initialization. > > Since the exception table is currently sorted at runtime, and fairly > late in startup, this code walks the exception table linearly. We > obviously don't need to worry about modules, however: none have been > loaded at this point. > > In the future it would be better to have the table sorted at compile > time, or even better, turned into a perfect hash. At that point this > code should be changed out from doing a linear search. > --- > arch/x86/include/asm/segment.h | 2 +- > arch/x86/kernel/head_64.S | 72 +++++++++++++++++++++++++++++---------- > 2 files changed, 54 insertions(+), 20 deletions(-) > > diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h > index 58c1e6c..c48a950 100644 > --- a/arch/x86/include/asm/segment.h > +++ b/arch/x86/include/asm/segment.h > @@ -213,7 +213,7 @@ > > #ifdef __KERNEL__ > #ifndef __ASSEMBLY__ > -extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10]; > +extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; > > /* > * Load a segment. Fall back on loading the zero > diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S > index d1e112c..8b89239 100644 > --- a/arch/x86/kernel/head_64.S > +++ b/arch/x86/kernel/head_64.S > @@ -19,6 +19,7 @@ > #include <asm/cache.h> > #include <asm/processor-flags.h> > #include <asm/percpu.h> > +#include <asm/nops.h> > > #ifdef CONFIG_PARAVIRT > #include <asm/asm-offsets.h> > @@ -26,6 +27,7 @@ > #define GET_CR2_INTO(reg) GET_CR2_INTO_RAX ; movq %rax, reg > #else > #define GET_CR2_INTO(reg) movq %cr2, reg > +#define INTERRUPT_RETURN iretq > #endif > > /* we are not able to switch in one step to the final KERNEL ADDRESS SPACE > @@ -271,35 +273,56 @@ bad_address: > jmp bad_address > > .section ".init.text","ax" > -#ifdef CONFIG_EARLY_PRINTK > .globl early_idt_handlers > early_idt_handlers: > + # 56(%rsp) %rflags > + # 48(%rsp) %cs > + # 40(%rsp) %rip > + # 32(%rsp) error code
Just a question about understanding this: I was strugging with the exact interrupt-handler stack layout, so how do you know the exact offsets of rflags, cs et all? I've been staring at our APM v2, p. 144 (http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf) which shows the interrupt stack with error code but it has different offsets than those above:
[Return SS] 40(%rsp) [Return RSP] 32(%rsp) [rFLAGS] 24(%rsp) [CS] 16(%rsp) [RIP] 8(%rsp) [ErrorCode] 0(%rsp)
but I see below that we have room for %rax, %rcx and %rdx on the stack.
Are we doing something different in Linux, or what am I missing?
Thanks.
> i = 0 > .rept NUM_EXCEPTION_VECTORS > - movl $i, %esi > + .if (EXCEPTION_ERRCODE_MASK >> i) & 1 > + ASM_NOP2 > + .else > + pushq $0 # Dummy error code, to make stack frame uniform > + .endif > + pushq $i # 24(%rsp) Vector number > jmp early_idt_handler > i = i + 1 > .endr > -#endif > > ENTRY(early_idt_handler) > -#ifdef CONFIG_EARLY_PRINTK > + cld > + > cmpl $2,early_recursion_flag(%rip) > jz 1f > incl early_recursion_flag(%rip) > - GET_CR2_INTO(%r9) > - xorl %r8d,%r8d # zero for error code > - movl %esi,%ecx # get vector number > - # Test %ecx against mask of vectors that push error code. > - cmpl $31,%ecx > - ja 0f > - movl $1,%eax > - salq %cl,%rax > - testl $EXCEPTION_ERRCODE_MASK,%eax > - je 0f > - popq %r8 # get error code > -0: movq 0(%rsp),%rcx # get ip > - movq 8(%rsp),%rdx # get cs > + > + pushq %rax # 16(%rsp) > + pushq %rcx # 8(%rsp) > + pushq %rdx # 0(%rsp) > + > + cmpl $__KERNEL_CS,48(%rsp) > + jne 10f > + > + movq 40(%rsp),%rax # %rip > + leaq __start___ex_table(%rip),%rcx > + leaq __stop___ex_table(%rip),%rdx > + > +11: > + cmpq (%rcx),%rax > + je 20f # Found an exception entry > + addq $16,%rcx > + cmpq %rdx,%rcx > + jb 11b > + > +10: > +#ifdef CONFIG_EARLY_PRINTK > + GET_CR2_INTO(%r9) # can clobber any volatile register if pv > + movl 32(%rsp),%r8d # error code > + movl 24(%rsp),%esi # vector number > + movl 48(%rsp),%edx # %cs > + movq 40(%rsp),%rcx # %rip > xorl %eax,%eax > leaq early_idt_msg(%rip),%rdi > call early_printk > @@ -308,17 +331,28 @@ ENTRY(early_idt_handler) > call dump_stack > #ifdef CONFIG_KALLSYMS > leaq early_idt_ripmsg(%rip),%rdi > - movq 0(%rsp),%rsi # get rip again > + movq 40(%rsp),%rsi # %rip again > call __print_symbol > #endif > #endif /* EARLY_PRINTK */ > 1: hlt > jmp 1b > > -#ifdef CONFIG_EARLY_PRINTK > +20: # Exception table entry found > + movq 8(%rcx),%rax # exception table target > + movq %rax,40(%rsp) # change %rip on stack > + popq %rdx > + popq %rcx > + popq %rax > + addq $16,%rsp # drop vector number and error code > + decl early_recursion_flag(%rip) > + INTERRUPT_RETURN > + > + .balign 4 > early_recursion_flag: > .long 0 > > +#ifdef CONFIG_EARLY_PRINTK > early_idt_msg: > .asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n" > early_idt_ripmsg: > -- > 1.7.6.5 > >
-- Regards/Gruss, Boris.
Advanced Micro Devices GmbH Einsteinring 24, 85609 Dornach GM: Alberto Bozzo Reg: Dornach, Landkreis Muenchen HRB Nr. 43632 WEEE Registernr: 129 19551
| |