summaryrefslogtreecommitdiffstats
path: root/src/arch/x86/lib/c_start.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/lib/c_start.S')
-rw-r--r--src/arch/x86/lib/c_start.S171
1 files changed, 133 insertions, 38 deletions
diff --git a/src/arch/x86/lib/c_start.S b/src/arch/x86/lib/c_start.S
index dbed12377e63..582966bfdc20 100644
--- a/src/arch/x86/lib/c_start.S
+++ b/src/arch/x86/lib/c_start.S
@@ -17,20 +17,30 @@ thread_stacks:
#endif
.section ".text._start", "ax", @progbits
+#ifdef __x86_64__
+ .code64
+#else
.code32
+#endif
.globl _start
.globl __rmodule_entry
__rmodule_entry:
_start:
cli
lgdt %cs:gdtaddr
+#ifndef __x86_64__
ljmp $0x10, $1f
+#endif
1: movl $0x18, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %ss
movl %eax, %fs
movl %eax, %gs
+#ifdef __x86_64__
+ mov $0x48, %ecx
+ call SetCodeSelector
+#endif
post_code(POST_ENTRY_C_START) /* post 13 */
@@ -54,11 +64,11 @@ _start:
#if CONFIG_COOP_MULTITASKING
/* Push the thread pointer. */
- pushl $0
+ push $0
#endif
/* Push the cpu index and struct cpu */
- pushl $0
- pushl $0
+ push $0
+ push $0
/* Initialize the Interrupt Descriptor table */
leal _idt, %edi
@@ -76,7 +86,11 @@ _start:
jne 1b
/* Load the Interrupt descriptor table */
+#ifndef __x86_64__
lidt idtarg
+#else
+ // FIXME port table to x64 - lidt idtarg
+#endif
/*
* Now we are finished. Memory is up, data is copied and
@@ -97,122 +111,150 @@ _start:
jmp .Lhlt
vec0:
- pushl $0 /* error code */
- pushl $0 /* vector */
+ push $0 /* error code */
+ push $0 /* vector */
jmp int_hand
vec1:
- pushl $0 /* error code */
- pushl $1 /* vector */
+ push $0 /* error code */
+ push $1 /* vector */
jmp int_hand
vec2:
- pushl $0 /* error code */
- pushl $2 /* vector */
+ push $0 /* error code */
+ push $2 /* vector */
jmp int_hand
vec3:
- pushl $0 /* error code */
- pushl $3 /* vector */
+ push $0 /* error code */
+ push $3 /* vector */
jmp int_hand
vec4:
- pushl $0 /* error code */
- pushl $4 /* vector */
+ push $0 /* error code */
+ push $4 /* vector */
jmp int_hand
vec5:
- pushl $0 /* error code */
- pushl $5 /* vector */
+ push $0 /* error code */
+ push $5 /* vector */
jmp int_hand
vec6:
- pushl $0 /* error code */
- pushl $6 /* vector */
+ push $0 /* error code */
+ push $6 /* vector */
jmp int_hand
vec7:
- pushl $0 /* error code */
- pushl $7 /* vector */
+ push $0 /* error code */
+ push $7 /* vector */
jmp int_hand
vec8:
/* error code */
- pushl $8 /* vector */
+ push $8 /* vector */
jmp int_hand
.word 0x9090
vec9:
- pushl $0 /* error code */
- pushl $9 /* vector */
+ push $0 /* error code */
+ push $9 /* vector */
jmp int_hand
vec10:
/* error code */
- pushl $10 /* vector */
+ push $10 /* vector */
jmp int_hand
.word 0x9090
vec11:
/* error code */
- pushl $11 /* vector */
+ push $11 /* vector */
jmp int_hand
.word 0x9090
vec12:
/* error code */
- pushl $12 /* vector */
+ push $12 /* vector */
jmp int_hand
.word 0x9090
vec13:
/* error code */
- pushl $13 /* vector */
+ push $13 /* vector */
jmp int_hand
.word 0x9090
vec14:
/* error code */
- pushl $14 /* vector */
+ push $14 /* vector */
jmp int_hand
.word 0x9090
vec15:
- pushl $0 /* error code */
- pushl $15 /* vector */
+ push $0 /* error code */
+ push $15 /* vector */
jmp int_hand
vec16:
- pushl $0 /* error code */
- pushl $16 /* vector */
+ push $0 /* error code */
+ push $16 /* vector */
jmp int_hand
vec17:
/* error code */
- pushl $17 /* vector */
+ push $17 /* vector */
jmp int_hand
.word 0x9090
vec18:
- pushl $0 /* error code */
- pushl $18 /* vector */
+ push $0 /* error code */
+ push $18 /* vector */
jmp int_hand
vec19:
- pushl $0 /* error code */
- pushl $19 /* vector */
+ push $0 /* error code */
+ push $19 /* vector */
jmp int_hand
int_hand:
- /* At this point on the stack there is:
+ /* 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__
+ 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
+
/* Original stack pointer */
leal 32(%esp), %ebp
pushl %ebp
@@ -235,6 +277,7 @@ int_hand:
popl %edi
addl $8, %esp /* pop of the vector and error code */
+#endif
iret
@@ -242,21 +285,33 @@ int_hand:
.globl gdb_stub_breakpoint
gdb_stub_breakpoint:
+#ifdef __x86_64__
+ pop %rax /* Return address */
+ pushfl
+ push %cs
+ push %rax /* Return address */
+ push $0 /* No error code */
+ push $32 /* vector 32 is user defined */
+#else
popl %eax /* Return address */
pushfl
pushl %cs
pushl %eax /* Return address */
pushl $0 /* No error code */
pushl $32 /* vector 32 is user defined */
+#endif
jmp int_hand
-
#endif
.globl gdt, gdt_end, idtarg
gdtaddr:
.word gdt_end - gdt - 1
+#ifdef __x86_64__
+ .quad gdt
+#else
.long gdt /* we know the offset */
+#endif
.data
@@ -287,7 +342,11 @@ gdt:
/* selgdt 0x18, flat data segment */
.word 0xffff, 0x0000
+#ifdef __x86_64__
+ .byte 0x00, 0x92, 0xcf, 0x00
+#else
.byte 0x00, 0x93, 0xcf, 0x00
+#endif
/* selgdt 0x20, unused */
.word 0x0000, 0x0000 /* dummy */
@@ -312,6 +371,12 @@ gdt:
/* selgdt 0x40, flat code segment 16 bit */
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
+
+#ifdef __x86_64__
+ /* selgdt 0x48, flat x64 code segment */
+ .word 0xffff, 0x0000
+ .byte 0x00, 0x9b, 0xaf, 0x00
+#endif
gdt_end:
idtarg:
@@ -322,5 +387,35 @@ _idt:
.fill 20, 8, 0 # idt is uninitialized
_idt_end:
+#ifdef __x86_64__
+SetCodeSelector:
+.intel_syntax noprefix
+
+ # save rsp because iret will align it to a 16 byte boundary
+ mov rdx, rsp
+
+ # use iret to jump to a 64-bit offset in a new code segment
+ # iret will pop cs:rip, flags, then ss:rsp
+ mov ax, ss # need to push ss..
+ push rax # push ss instuction not valid in x64 mode, so use ax
+ push rsp
+ pushfq
+ push rcx # cx is code segment selector from caller
+ mov rax, offset setCodeSelectorLongJump
+ push rax
+
+ # the iret will continue at next instruction, with the new cs value loaded
+ iretq
+
+setCodeSelectorLongJump:
+ # restore rsp, it might not have been 16-byte aligned on entry
+ mov rsp, rdx
+ ret
+.att_syntax prefix
+
+ .previous
+.code64
+#else
.previous
.code32
+#endif