Philipp Deppenwiese has submitted this change. ( https://review.coreboot.org/c/coreboot/+/30117 )
Change subject: arch/x86: Support x86_64 exceptions ......................................................................
arch/x86: Support x86_64 exceptions
* Doesn't affect existing x86_32 code.
Tested on qemu using division by zero. Tested on Lenovo T410 with additional x86_64 patches.
Change-Id: Idd12c90a95cc2989eb9b2a718740a84222193f48 Signed-off-by: Patrick Rudolph siro@das-labor.org Reviewed-on: https://review.coreboot.org/c/coreboot/+/30117 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Raul Rangel rrangel@chromium.org --- M Documentation/arch/x86/index.md M src/arch/x86/exception.c M src/arch/x86/idt.S M src/arch/x86/include/arch/registers.h 4 files changed, 141 insertions(+), 40 deletions(-)
Approvals: build bot (Jenkins): Verified Raul Rangel: Looks good to me, approved
diff --git a/Documentation/arch/x86/index.md b/Documentation/arch/x86/index.md index 462e7e6..536dea3 100644 --- a/Documentation/arch/x86/index.md +++ b/Documentation/arch/x86/index.md @@ -42,7 +42,7 @@ * Fix compilation errors - *DONE* * Fix linker errors - *TODO* * Add x86_64 rmodule support - *DONE* -* Add x86_64 exception handlers - *TODO* +* Add x86_64 exception handlers - *DONE* * Setup page tables for long mode - *DONE* * Add assembly code for long mode - *DONE* * Add assembly code for postcar stage - *TODO* diff --git a/src/arch/x86/exception.c b/src/arch/x86/exception.c index 46ba370..318a219 100644 --- a/src/arch/x86/exception.c +++ b/src/arch/x86/exception.c @@ -489,12 +489,38 @@ put_packet(out_buffer); } #else /* !CONFIG_GDB_STUB */ -#define MDUMP_SIZE 0x80 + int logical_processor = 0;
#if ENV_RAMSTAGE logical_processor = cpu_index(); #endif + u8 *code; +#ifdef __x86_64__ +#define MDUMP_SIZE 0x100 + printk(BIOS_EMERG, + "CPU Index %d - APIC %d Unexpected Exception:\n" + "%lld @ %02llx:%016llx - Halting\n" + "Code: %lld rflags: %016llx cr2: %016llx\n" + "rax: %016llx rbx: %016llx\n" + "rcx: %016llx rdx: %016llx\n" + "rdi: %016llx rsi: %016llx\n" + "rbp: %016llx rsp: %016llx\n" + "r08: %016llx r09: %016llx\n" + "r10: %016llx r11: %016llx\n" + "r12: %016llx r13: %016llx\n" + "r14: %016llx r15: %016llx\n", + logical_processor, (unsigned int)lapicid(), + info->vector, info->cs, info->rip, + info->error_code, info->rflags, read_cr2(), + info->rax, info->rbx, info->rcx, info->rdx, + info->rdi, info->rsi, info->rbp, info->rsp, + info->r8, info->r9, info->r10, info->r11, + info->r12, info->r13, info->r14, info->r15); + code = (u8 *)((uintptr_t)info->rip - (MDUMP_SIZE >> 2)); +#else +#define MDUMP_SIZE 0x80 + printk(BIOS_EMERG, "CPU Index %d - APIC %d Unexpected Exception:" "%d @ %02x:%08x - Halting\n" @@ -506,7 +532,8 @@ info->error_code, info->eflags, read_cr2(), info->eax, info->ebx, info->ecx, info->edx, info->edi, info->esi, info->ebp, info->esp); - u8 *code = (u8 *)((uintptr_t)info->eip - (MDUMP_SIZE >> 1)); + code = (u8 *)((uintptr_t)info->eip - (MDUMP_SIZE >> 1)); +#endif /* Align to 8-byte boundary please, and print eight bytes per row. * This is done to make DRAM burst timing/reordering errors more * evident from the looking at the dump */ diff --git a/src/arch/x86/idt.S b/src/arch/x86/idt.S index a15ccbb..6807056 100644 --- a/src/arch/x86/idt.S +++ b/src/arch/x86/idt.S @@ -109,6 +109,68 @@
.global int_hand int_hand: +#ifdef __x86_64__ + /* At this point, on x86-64, on the stack there is: + * 0(%rsp) vector + * 8(%rsp) error code + * 16(%rsp) rip + * 24(%rsp) cs + * 32(%rsp) rflags + * 40(%rsp) rsp + * 48(%rsp) ss + */ + push %r15 + push %r14 + push %r13 + push %r12 + push %r11 + push %r10 + push %r9 + push %r8 + + push %rdi + push %rsi + push %rbp + + push %rbx + push %rdx + push %rcx + push %rax + + /* Pass pointer to struct as first argument */ + mov %rsp, %rdi + + /* Back up stack pointer */ + mov %rsp, %rbp + + /* Align stack to 16 bytes. */ + and $(~0xf), %rsp + + call x86_exception + + /* Restore stack pointer from backup */ + mov %rbp, %rsp + + pop %rax + pop %rcx + pop %rdx + pop %rbx + + pop %rbp + pop %rsi + pop %rdi + + pop %r8 + pop %r9 + pop %r10 + pop %r11 + pop %r12 + pop %r13 + pop %r14 + pop %r15 + + add $16, %rsp /* pop of the vector and error code */ +#else /* At this point, on x86-32, on the stack there is: * 0(%esp) vector * 4(%esp) error code @@ -116,33 +178,6 @@ * 12(%esp) cs * 16(%esp) eflags */ -#ifdef __x86_64__ - push %rdi - push %rsi - push %rbp - /* Original stack pointer */ - lea 32(%rsp), %rbp - push %rbp - push %rbx - push %rdx - push %rcx - push %rax - - push %rsp /* Pointer to structure on the stack */ - call x86_exception - pop %rax /* Drop the pointer */ - - pop %rax - pop %rcx - pop %rdx - pop %rbx - pop %rbp /* Ignore saved %rsp value */ - pop %rbp - pop %rsi - pop %rdi - - add $8, %rsp /* pop of the vector and error code */ -#else pushl %edi pushl %esi pushl %ebp diff --git a/src/arch/x86/include/arch/registers.h b/src/arch/x86/include/arch/registers.h index 256053c..5f8f9be 100644 --- a/src/arch/x86/include/arch/registers.h +++ b/src/arch/x86/include/arch/registers.h @@ -6,7 +6,7 @@ #if !defined(__ASSEMBLER__) #include <stdint.h>
-#define DOWNTO8(A) \ +#define LONG_DOWNTO8(A) \ union { \ struct { \ union { \ @@ -21,7 +21,7 @@ uint32_t e##A##x; \ } __packed;
-#define DOWNTO16(A) \ +#define LONG_DOWNTO16(A) \ union { \ struct { \ uint16_t A; \ @@ -30,21 +30,60 @@ uint32_t e##A; \ } __packed;
+#define QUAD_DOWNTO8(A) \ + union { \ + LONG_DOWNTO8(A) \ + uint64_t r##A##x; \ + } __packed + +#define QUAD_DOWNTO16(A) \ + union {\ + LONG_DOWNTO16(A) \ + uint64_t r##A; \ + } __packed + +#ifdef __ARCH_x86_64__ struct eregs { - DOWNTO8(a); - DOWNTO8(c); - DOWNTO8(d); - DOWNTO8(b); - DOWNTO16(sp); - DOWNTO16(bp); - DOWNTO16(si); - DOWNTO16(di); + QUAD_DOWNTO8(a); + QUAD_DOWNTO8(c); + QUAD_DOWNTO8(d); + QUAD_DOWNTO8(b); + QUAD_DOWNTO16(bp); + QUAD_DOWNTO16(si); + QUAD_DOWNTO16(di); + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t vector; + uint64_t error_code; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + QUAD_DOWNTO16(sp); + uint64_t ss; +}; +#else +struct eregs { + LONG_DOWNTO8(a); + LONG_DOWNTO8(c); + LONG_DOWNTO8(d); + LONG_DOWNTO8(b); + LONG_DOWNTO16(sp); + LONG_DOWNTO16(bp); + LONG_DOWNTO16(si); + LONG_DOWNTO16(di); uint32_t vector; uint32_t error_code; uint32_t eip; uint32_t cs; uint32_t eflags; }; +#endif #endif // !ASSEMBLER
#if CONFIG(COMPILER_LLVM_CLANG)