1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00
2017-06-18 09:15:51 +01:00

103 lines
2.9 KiB
ArmAsm

; vim: set ft=nasm :
%include "constants.inc"
section .bss
align 8
r0_g_ptr: resq 1 ; fs:0x00 is a pointer to the current g struct
r0_g:
r0_g_stack_lo: resq 1
r0_g_stack_hi: resq 1
r0_g_stackguard0: resq 1 ; rsp compared to this value in go stack growth prologue
r0_g_stackguard1: resq 1 ; rsp compared to this value in C stack growth prologue
section .text
bits 64
;------------------------------------------------------------------------------
; 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:
; According to the x86_64 ABI, the fs:0 should point to the address of
; the user-space thread structure. The actual TLS structure is located
; just before that (aligned). Go code tries to fetch the address to the
; active go-routine's g struct by accessing fs:-8. What we need to do
; is to setup a mock g0 struct, populate its stack_lo/hi/guard fields
; and then use wrmsr to update the FS register
extern stack_top
extern stack_bottom
; Setup r0_g
mov rax, stack_bottom
mov rbx, stack_top
mov rsi, r0_g
mov qword [rsi+0], rax ; stack_lo
mov qword [rsi+8], rbx ; stack_hi
mov qword [rsi+16], rax ; stackguard0
mov rax, r0_g_ptr
mov qword [rax], rsi
; Load 64-bit FS register address
; rax -> lower 32 bits
; rdx -> upper 32 bits
mov ecx, 0xc0000100 ; fs_base
mov rax, rsi ; lower 32 bits
shr rsi, 32
mov rdx, rsi ; high 32 bits
wrmsr
; 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, _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
;------------------------------------------------------------------------------
; 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