summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Menzel <pmenzel@molgen.mpg.de>2019-06-24 18:44:33 +0200
committerPhilipp Deppenwiese <zaolin.daisuki@gmail.com>2020-07-05 19:56:09 +0000
commit6663ad99cf36f53f454defc8f7e87eb2e7495255 (patch)
tree818e3c711d8c316c96915dff63da535f139cff7d
parentd9c6862809ca95712e18b967a1fefc24cb607a06 (diff)
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>
-rw-r--r--Documentation/arch/x86/index.md2
-rw-r--r--src/arch/x86/exception.c31
-rw-r--r--src/arch/x86/idt.S63
-rw-r--r--src/arch/x86/include/arch/registers.h59
4 files changed, 128 insertions, 27 deletions
diff --git a/Documentation/arch/x86/index.md b/Documentation/arch/x86/index.md
index 462e7e6c6e..536dea3951 100644
--- a/Documentation/arch/x86/index.md
+++ b/Documentation/arch/x86/index.md
@@ -42,7 +42,7 @@ At the moment *$n* is 4, which results in identity mapping the lower 4 GiB.
* 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 46ba370cdf..318a219ac9 100644
--- a/src/arch/x86/exception.c
+++ b/src/arch/x86/exception.c
@@ -489,12 +489,38 @@ void x86_exception(struct eregs *info)
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 @@ void x86_exception(struct eregs *info)
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 a15ccbb132..6807056fe3 100644
--- a/src/arch/x86/idt.S
+++ b/src/arch/x86/idt.S
@@ -109,40 +109,75 @@ vec19:
.global int_hand
int_hand:
- /* At this point, on x86-32, on the stack there is:
- * 0(%esp) vector
- * 4(%esp) error code
- * 8(%esp) eip
- * 12(%esp) cs
- * 16(%esp) eflags
- */
#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
- /* 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 */
+ /* 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
- pop %rax /* Drop the pointer */
+
+ /* Restore stack pointer from backup */
+ mov %rbp, %rsp
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 */
+ 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
+ * 8(%esp) eip
+ * 12(%esp) cs
+ * 16(%esp) eflags
+ */
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 256053c9b0..5f8f9becd3 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)