lkml.org 
[lkml]   [2012]   [Apr]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [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


    \
     
     \ /
      Last update: 2012-04-19 15:05    [W:5.080 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site