diff options
Diffstat (limited to 'src/arch/x86/lib/c_start.S')
-rw-r--r-- | src/arch/x86/lib/c_start.S | 171 |
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 dbed12377e..582966bfdc 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 |