aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86/gdt_init.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/gdt_init.S')
-rw-r--r--src/arch/x86/gdt_init.S15
1 files changed, 14 insertions, 1 deletions
diff --git a/src/arch/x86/gdt_init.S b/src/arch/x86/gdt_init.S
index 7dd4b94933..1558ac62c8 100644
--- a/src/arch/x86/gdt_init.S
+++ b/src/arch/x86/gdt_init.S
@@ -20,7 +20,20 @@ gdtptr:
.section ".text._gdt64_", "ax", @progbits
.globl gdt_init64
gdt_init64:
- lgdt gdtptr64
+ /* Workaround a bug in the assembler.
+ * The following code doesn't work:
+ * lgdt gdtptr64
+ *
+ * The assembler tries to save memory by using 32bit displacement addressing mode.
+ * Displacements are using signed integers.
+ * This is fine in protected mode, as the negative address points to the correct
+ * address > 2GiB, but in long mode this doesn't work at all.
+ * Tests showed that QEMU can gracefully handle it, but real CPUs can't.
+ *
+ * Use the movabs pseudo instruction to force using a 64bit absolute address.
+ */
+ movabs $gdtptr64, %rax
+ lgdt (%rax)
ret
.previous