mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
tools: update offsets tool to work with go versions 1.7 - 1.10
Older go versions (1.7.x) specify a fixed page size (_PageSize const) as part of their runtime whereas newer go versions populate the page size at runtime. The kernel asm bootstrap code was written with go 1.8 in mind. As a result it attempts to populate the page size manually which obviously breaks compilation in go 1.7. The offsets tool has been updated to emit the special def "SKIP_PAGESIZE_SETUP" when running under go 1.7 which allows us to perform conditional compilation of the page setup code inside the bootstrap asm code. fixup
This commit is contained in:
@@ -17,17 +17,17 @@ _rt0_idt_desc:
|
||||
resw 1
|
||||
resq 1
|
||||
|
||||
; Allocates space for the IRQ handlers pointers registered by the IRQ package
|
||||
; Allocates space for the IRQ handlers pointers registered by the IRQ package
|
||||
_rt0_irq_handlers resq IDT_ENTRIES
|
||||
|
||||
; 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
|
||||
; 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
|
||||
r0_g_ptr: resq 1
|
||||
tcb_ptr: resq 1
|
||||
|
||||
section .text
|
||||
section .text
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Kernel 64-bit entry point
|
||||
@@ -36,7 +36,7 @@ section .text
|
||||
; - 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.
|
||||
; PAGE_OFFSET to PAGE_OFFSET+8M region.
|
||||
;------------------------------------------------------------------------------
|
||||
global _rt0_64_entry
|
||||
_rt0_64_entry:
|
||||
@@ -50,7 +50,7 @@ _rt0_64_entry:
|
||||
extern _kernel_start
|
||||
extern _kernel_end
|
||||
extern kernel.Kmain
|
||||
|
||||
|
||||
mov rax, PAGE_OFFSET
|
||||
push rax
|
||||
mov rax, _kernel_end - PAGE_OFFSET
|
||||
@@ -60,7 +60,7 @@ _rt0_64_entry:
|
||||
mov rax, multiboot_data
|
||||
push rax
|
||||
call kernel.Kmain
|
||||
|
||||
|
||||
; Main should never return; halt the CPU
|
||||
mov rdi, err_kmain_returned
|
||||
call write_string
|
||||
@@ -75,13 +75,15 @@ _rt0_64_entry:
|
||||
_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 bypass osinit() this needs to be set here.
|
||||
; As the kernel bypasses osinit() this needs to be manually set here.
|
||||
extern runtime.physPageSize
|
||||
mov rax, runtime.physPageSize
|
||||
mov qword [rax], 0x1000 ; 4096
|
||||
|
||||
; Setup r0_g stack limits using the reserved stack
|
||||
%endif
|
||||
|
||||
; Setup r0_g stack limits using the reserved stack
|
||||
extern stack_top
|
||||
extern stack_bottom
|
||||
extern runtime.g0
|
||||
@@ -99,21 +101,21 @@ _rt0_64_setup_go_runtime_structs:
|
||||
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
|
||||
; 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
|
||||
; 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
|
||||
; 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
|
||||
mov rax, rsi ; lower 32 bits
|
||||
shr rsi, 32
|
||||
mov rdx, rsi ; high 32 bits
|
||||
wrmsr
|
||||
@@ -122,26 +124,26 @@ _rt0_64_setup_go_runtime_structs:
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Setup and load IDT. We preload each IDT entry with a pointer to a gate handler
|
||||
; but set it as inactive. The code in irq_amd64 is responsible for enabling
|
||||
; Setup and load IDT. We preload each IDT entry with a pointer to a gate handler
|
||||
; but set it as inactive. The code in irq_amd64 is responsible for enabling
|
||||
; individual IDT entries when handlers are installed.
|
||||
;------------------------------------------------------------------------------
|
||||
_rt0_64_load_idt:
|
||||
mov rax, _rt0_idt_start
|
||||
|
||||
%assign gate_num 0
|
||||
%assign gate_num 0
|
||||
%rep IDT_ENTRIES
|
||||
mov rbx, _rt0_64_gate_entry_%+ gate_num
|
||||
mov word [rax], bx ; gate entry bits 0-15
|
||||
mov word [rax+2], 0x8 ; GDT descriptor
|
||||
mov byte [rax+5], 0x0 ; Mark the entry as NOT present
|
||||
mov byte [rax+5], 0x0 ; Mark the entry as NOT present
|
||||
shr rbx, 16
|
||||
mov word [rax+6], bx ; gate entry bits 16-31
|
||||
shr rbx, 16
|
||||
mov dword [rax+8], ebx ; gate entry bits 32-63
|
||||
|
||||
add rax, 16 ; size of IDT entry
|
||||
%assign gate_num gate_num+1
|
||||
%assign gate_num gate_num+1
|
||||
%endrep
|
||||
mov rax, _rt0_idt_desc
|
||||
mov word [rax], _rt0_idt_end - _rt0_idt_start - 1 ; similar to GDT this must be len(IDT) - 1
|
||||
@@ -152,15 +154,15 @@ ret
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Generate gate entries. Each gate handler pushes the address of the registered
|
||||
; Generate gate entries. Each gate handler pushes the address of the registered
|
||||
; handler to the stack before jumping to a dispatcher function.
|
||||
;
|
||||
; Some exceptions push an error code to the stack after the stack frame. This
|
||||
; code must be popped off the stack before calling iretq. The generated handlers
|
||||
; are aware whether they need to deal with the code or not and jump to the
|
||||
; code must be popped off the stack before calling iretq. The generated handlers
|
||||
; are aware whether they need to deal with the code or not and jump to the
|
||||
; appropriate get dispatcher.
|
||||
;------------------------------------------------------------------------------
|
||||
%assign gate_num 0
|
||||
%assign gate_num 0
|
||||
%rep IDT_ENTRIES
|
||||
extern _rt0_interrupt_handlers
|
||||
_rt0_64_gate_entry_%+ gate_num:
|
||||
@@ -177,13 +179,13 @@ _rt0_64_gate_entry_%+ gate_num:
|
||||
%else
|
||||
jmp _rt0_64_gate_dispatcher_without_code
|
||||
%endif
|
||||
%assign gate_num gate_num+1
|
||||
%assign gate_num gate_num+1
|
||||
%endrep
|
||||
|
||||
%macro save_regs 0
|
||||
push r15
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r13
|
||||
push r12
|
||||
push r11
|
||||
push r10
|
||||
@@ -191,10 +193,10 @@ _rt0_64_gate_entry_%+ gate_num:
|
||||
push r8
|
||||
push rbp
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
push rcx
|
||||
push rbx
|
||||
push rsi
|
||||
push rdx
|
||||
push rcx
|
||||
push rbx
|
||||
push rax
|
||||
%endmacro
|
||||
|
||||
@@ -203,13 +205,13 @@ _rt0_64_gate_entry_%+ gate_num:
|
||||
pop rbx
|
||||
pop rcx
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop rbp
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
@@ -217,14 +219,14 @@ _rt0_64_gate_entry_%+ gate_num:
|
||||
%endmacro
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; This dispatcher is invoked by gate entries that expect a code to be pushed
|
||||
; This dispatcher is invoked by gate entries that expect a code to be pushed
|
||||
; by the CPU to the stack. It performs the following functions:
|
||||
; - save registers
|
||||
; - push pointer to saved regs
|
||||
; - push pointer to stack frame
|
||||
; - read and push exception code
|
||||
; - push pointer to saved regs
|
||||
; - push pointer to stack frame
|
||||
; - read and push exception code
|
||||
; - invoke handler(code, &frame, ®s)
|
||||
; - restore registers
|
||||
; - restore registers
|
||||
; - pop exception code from stack so rsp points to the stack frame
|
||||
;------------------------------------------------------------------------------
|
||||
_rt0_64_gate_dispatcher_with_code:
|
||||
@@ -236,7 +238,7 @@ _rt0_64_gate_dispatcher_with_code:
|
||||
;-----------------|
|
||||
; Exception code | <- needs to be removed from stack before calling iretq
|
||||
;-----------------|
|
||||
; RIP | <- exception frame
|
||||
; RIP | <- exception frame
|
||||
; CS |
|
||||
; RFLAGS |
|
||||
; RSP |
|
||||
@@ -244,12 +246,12 @@ _rt0_64_gate_dispatcher_with_code:
|
||||
;-----------------
|
||||
cld
|
||||
|
||||
; save regs and push a pointer to them
|
||||
; save regs and push a pointer to them
|
||||
save_regs
|
||||
mov rax, rsp ; rax points to saved rax
|
||||
push rax ; push pointer to saved regs
|
||||
|
||||
; push pointer to exception stack frame (we have used 15 qwords for the
|
||||
; push pointer to exception stack frame (we have used 15 qwords for the
|
||||
; saved registers plus one qword for the data pushed by the gate entry
|
||||
; plus one extra qword to jump over the exception code)
|
||||
add rax, 17*8
|
||||
@@ -261,7 +263,7 @@ _rt0_64_gate_dispatcher_with_code:
|
||||
|
||||
call [rsp + 18*8] ; call registered irq handler
|
||||
|
||||
add rsp, 3 * 8 ; unshift the pushed arguments so rsp points to the saved regs
|
||||
add rsp, 3 * 8 ; unshift the pushed arguments so rsp points to the saved regs
|
||||
restore_regs
|
||||
|
||||
add rsp, 16 ; pop handler address and exception code off the stack before returning
|
||||
@@ -271,10 +273,10 @@ _rt0_64_gate_dispatcher_with_code:
|
||||
; This dispatcher is invoked by gate entries that do not use exception codes.
|
||||
; It performs the following functions:
|
||||
; - save registers
|
||||
; - push pointer to saved regs
|
||||
; - push pointer to stack frame
|
||||
; - push pointer to saved regs
|
||||
; - push pointer to stack frame
|
||||
; - invoke handler(&frame, ®s)
|
||||
; - restore registers
|
||||
; - restore registers
|
||||
;------------------------------------------------------------------------------
|
||||
_rt0_64_gate_dispatcher_without_code:
|
||||
; This is how the stack looks like when entering this function:
|
||||
@@ -283,7 +285,7 @@ _rt0_64_gate_dispatcher_without_code:
|
||||
;------------------
|
||||
; handler address | <- pushed by gate_entry_xxx (RSP points here)
|
||||
;-----------------|
|
||||
; RIP | <- exception frame
|
||||
; RIP | <- exception frame
|
||||
; CS |
|
||||
; RFLAGS |
|
||||
; RSP |
|
||||
@@ -291,21 +293,21 @@ _rt0_64_gate_dispatcher_without_code:
|
||||
;-----------------
|
||||
cld
|
||||
|
||||
; save regs and push a pointer to them
|
||||
; save regs and push a pointer to them
|
||||
save_regs
|
||||
mov rax, rsp ; rax points to saved rax
|
||||
push rax ; push pointer to saved regs
|
||||
|
||||
; push pointer to exception stack frame (we have used 15 qwords for the
|
||||
; push pointer to exception stack frame (we have used 15 qwords for the
|
||||
; saved registers plus one qword for the data pushed by the gate entry)
|
||||
add rax, 16*8
|
||||
push rax
|
||||
|
||||
call [rsp + 17*8] ; call registered irq handler
|
||||
|
||||
add rsp, 2 * 8 ; unshift the pushed arguments so rsp points to the saved regs
|
||||
add rsp, 2 * 8 ; unshift the pushed arguments so rsp points to the saved regs
|
||||
restore_regs
|
||||
|
||||
|
||||
add rsp, 8 ; pop handler address off the stack before returning
|
||||
iretq
|
||||
|
||||
@@ -340,13 +342,13 @@ write_string:
|
||||
; 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.
|
||||
; 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.
|
||||
; the 14-byte long _rt0_redirect_trampoline code.
|
||||
;
|
||||
; Note: this code modification is only possible because we are currently
|
||||
; 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.
|
||||
;------------------------------------------------------------------------------
|
||||
@@ -355,7 +357,7 @@ _rt0_install_redirect_trampolines:
|
||||
mov rdx, NUM_REDIRECTS
|
||||
|
||||
_rt0_install_redirect_rampolines.next:
|
||||
mov rdi, [rax] ; the symbol address to hook
|
||||
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
|
||||
@@ -364,15 +366,15 @@ _rt0_install_redirect_rampolines.next:
|
||||
mov rcx, 14
|
||||
rep movsb ; copy rcx bytes from rsi to rdi
|
||||
|
||||
add rax, 16
|
||||
dec rdx
|
||||
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
|
||||
; 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]
|
||||
@@ -380,14 +382,14 @@ _rt0_install_redirect_rampolines.next:
|
||||
;------------------------------------------------------------------------------
|
||||
_rt0_redirect_trampoline:
|
||||
db 0xff ; the first 6 bytes encode a "jmp [rip+0]" instruction
|
||||
db 0x25
|
||||
dd 0x00
|
||||
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
|
||||
; 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
|
||||
; 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.
|
||||
;------------------------------------------------------------------------------
|
||||
@@ -395,7 +397,7 @@ section .goredirectstbl
|
||||
|
||||
_rt0_redirect_table:
|
||||
%rep NUM_REDIRECTS
|
||||
dq 0 ; src: address of the symbol we want to redirect
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user