1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00
Achilleas Anagnostopoulos c692bcd329 makefile: rename arch/x86_64 to arch/amd64 and cleanup targets
This change was made to align the arch name with the one used by Go.
The generic "arch/XXX/asm" dir has also been renamed to "arch/XXX/rt0"
to clearly indicate its purpose
2018-06-01 09:02:33 +01:00

201 lines
6.5 KiB
ArmAsm

; vim: set ft=nasm :
%include "constants.inc"
bits 64
section .bss
align 8
; According to the "ELF handling for TLS" document section 3.4.6
; (https://www.akkadia.org/drepper/tls.pdf) for the GNU variant for x86-64,
; fs:0x00 contains a pointer to the TCB. Variables in the TLS are stored
; before the TCB and are accessed using negative offsets from the TCB address.
r0_g_ptr: resq 1
tcb_ptr: resq 1
section .text
;------------------------------------------------------------------------------
; Kernel 64-bit entry point
;
; The 32-bit entrypoint code jumps to this entrypoint after:
; - it has entered long mode and enabled paging
; - it has loaded a 64bit GDT
; - it has set up identity paging for the physical 0-8M region and the
; PAGE_OFFSET to PAGE_OFFSET+8M region.
;------------------------------------------------------------------------------
global _rt0_64_entry
_rt0_64_entry:
call _rt0_install_redirect_trampolines
call _rt0_64_setup_go_runtime_structs
; Call the kernel entry point passing a pointer to the multiboot data
; copied by the 32-bit entry code
extern multiboot_data
extern _kernel_start
extern _kernel_end
extern kernel.Kmain
mov rax, PAGE_OFFSET
push rax
mov rax, _kernel_end - PAGE_OFFSET
push rax
mov rax, _kernel_start - PAGE_OFFSET
push rax
mov rax, multiboot_data
push rax
call kernel.Kmain
; Main should never return; halt the CPU
mov rdi, err_kmain_returned
call write_string
cli
hlt
;------------------------------------------------------------------------------
; Setup m0, g0 and other symbols required for bootstrapping the Go runtime.
; For the definitions of g and m see the Go runtime src: src/runtime/runtime2.go
;------------------------------------------------------------------------------
_rt0_64_setup_go_runtime_structs:
%include "go_asm_offsets.inc" ; generated by tools/offsets
%ifndef SKIP_PAGESIZE_SETUP
; The Go allocator expects this symbol to be set to the system page size
; As the kernel bypasses osinit() this needs to be manually set here.
extern runtime.physPageSize
mov rax, runtime.physPageSize
mov qword [rax], 0x1000 ; 4096
%endif
; Setup r0_g stack limits using the reserved stack
extern stack_top
extern stack_bottom
extern runtime.g0
mov rax, stack_bottom
mov rbx, stack_top
mov rsi, runtime.g0
mov qword [rsi+GO_G_STACK+GO_STACK_LO], rax ; g.stack.lo
mov qword [rsi+GO_G_STACK+GO_STACK_HI], rbx ; g.stack.hi
mov qword [rsi+GO_G_STACKGUARD0], rax ; g.stackguard0
; Link m0 to the g0
extern runtime.m0
mov rbx, runtime.m0
mov qword [rbx+GO_M_CURG], rsi ; m.curg = g0
mov qword [rbx+GO_M_G0], rsi ; m.g0 = g0
mov qword [rsi+GO_G_M], rbx ; g.m = m
; Store the address of g0 in r0_g_ptr
mov rax, r0_g_ptr
mov qword [rax], rsi
; According to the x86-64 ABI requirements fs:0x0 should point to the
; TCB.
mov rax, tcb_ptr
mov qword [rax], rax
; Load 64-bit FS register address
; eax -> lower 32 bits
; edx -> upper 32 bits
mov ecx, 0xc0000100 ; fs_base
mov rsi, tcb_ptr
mov rax, rsi ; lower 32 bits
shr rsi, 32
mov rdx, rsi ; high 32 bits
wrmsr
ret
;------------------------------------------------------------------------------
; Error messages
;------------------------------------------------------------------------------
err_kmain_returned db '[rt0_64] kmain returned', 0
;------------------------------------------------------------------------------
; Write the NULL-terminated string contained in rdi to the screen using white
; text on red background. Assumes that text-mode is enabled and that its
; physical address is 0xb8000.
;------------------------------------------------------------------------------
write_string:
mov rbx,0xb8000
mov ah, 0x4F
.next_char:
mov al, byte[rdi]
test al, al
jz write_string.done
mov word [rbx], ax
add rbx, 2
inc rdi
jmp write_string.next_char
.done:
ret
;------------------------------------------------------------------------------
; Install redirect trampolines. This hack allows us to redirect calls to Go
; runtime functions to the kernel's own implementation without the need to
; export/globalize any symbols. This works by first setting up a redirect table
; (populated by a post-link step) that contains the addresses of the symbol to
; hook and the address where calls to that symbol should be redirected.
;
; This function iterates the redirect table entries and for each entry it
; sets up a trampoline to the dst symbol and overwrites the code in src with
; the 14-byte long _rt0_redirect_trampoline code.
;
; Note: this code modification is only possible because we are currently
; operating in supervisor mode with no memory protection enabled. Under normal
; conditions the .text section should be flagged as read-only.
;------------------------------------------------------------------------------
_rt0_install_redirect_trampolines:
mov rax, _rt0_redirect_table
mov rdx, NUM_REDIRECTS
_rt0_install_redirect_rampolines.next:
mov rdi, [rax] ; the symbol address to hook
mov rbx, [rax+8] ; the symbol to redirect to
; setup trampoline target and copy it to the hooked symbol
mov rsi, _rt0_redirect_trampoline
mov qword [rsi+6], rbx
mov rcx, 14
rep movsb ; copy rcx bytes from rsi to rdi
add rax, 16
dec rdx
jnz _rt0_install_redirect_rampolines.next
ret
;------------------------------------------------------------------------------
; This trampoline exploits rip-relative addressing to allow a jump to a
; 64-bit address without the need to touch any registers. The generated
; code is equivalent to:
;
; jmp [rip+0]
; dq abs_address_to_jump_to
;------------------------------------------------------------------------------
_rt0_redirect_trampoline:
db 0xff ; the first 6 bytes encode a "jmp [rip+0]" instruction
db 0x25
dd 0x00
dq 0x00 ; the absolute address to jump to
;------------------------------------------------------------------------------
; The redirect table is placed in a dedicated section allowing us to easily
; find its offset in the kernel image file. As the VMA addresses of the src
; and target symbols for the redirect are now known in advance we just reserve
; enough space space for the src and dst addresses using the NUM_REDIRECTS
; define which is calculated by the Makefile and passed to nasm.
;------------------------------------------------------------------------------
section .goredirectstbl
_rt0_redirect_table:
%rep NUM_REDIRECTS
dq 0 ; src: address of the symbol we want to redirect
dq 0 ; dst: address of the symbol where calls to src are redirected to
%endrep