mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Merge pull request #66 from achilleasa/ensure-kernel-builds-with-different-go-versions
Ensure kernel builds with different go versions
This commit is contained in:
commit
c88c72657d
30
.travis.yml
30
.travis.yml
@ -1,9 +1,29 @@
|
|||||||
language: go
|
language: go
|
||||||
sudo: required
|
sudo: required
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- nasm
|
||||||
|
- binutils-2.26
|
||||||
|
# Compile kernel with various go versions
|
||||||
go:
|
go:
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
- 1.x
|
- 1.x
|
||||||
script:
|
stage: build kernel
|
||||||
- make lint
|
before_install:
|
||||||
- make collect-coverage
|
- export PATH=/usr/lib/binutils-2.26/bin:${PATH}
|
||||||
after_success:
|
script: make kernel
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
|
# Run the tests against the latest go version
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
- stage: run tests
|
||||||
|
go: 1.x
|
||||||
|
script:
|
||||||
|
- make lint
|
||||||
|
- make collect-coverage
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
2
BUILD.md
2
BUILD.md
@ -11,7 +11,7 @@ To compile gopher-os wheh running on Linux you need a fairly recent version of:
|
|||||||
- grub
|
- grub
|
||||||
- nasm
|
- nasm
|
||||||
- gcc (for GNU ld)
|
- gcc (for GNU ld)
|
||||||
- go (1.6+; recommended: 1.8)
|
- go 1.7+
|
||||||
|
|
||||||
The above dependencies can be installed using the appropriate package manager
|
The above dependencies can be installed using the appropriate package manager
|
||||||
for each particular Linux distribution.
|
for each particular Linux distribution.
|
||||||
|
9
Makefile
9
Makefile
@ -22,7 +22,6 @@ FUZZ_PKG_LIST := src/gopheros/device/acpi/aml
|
|||||||
ifeq ($(OS), Linux)
|
ifeq ($(OS), Linux)
|
||||||
export SHELL := /bin/bash -o pipefail
|
export SHELL := /bin/bash -o pipefail
|
||||||
|
|
||||||
|
|
||||||
LD := ld
|
LD := ld
|
||||||
AS := nasm
|
AS := nasm
|
||||||
|
|
||||||
@ -62,11 +61,13 @@ go.o:
|
|||||||
-e "1s|^|export GOOS=$(GOOS)\n|" \
|
-e "1s|^|export GOOS=$(GOOS)\n|" \
|
||||||
-e "1s|^|export GOARCH=$(GOARCH)\n|" \
|
-e "1s|^|export GOARCH=$(GOARCH)\n|" \
|
||||||
-e "1s|^|export GOROOT=$(GOROOT)\n|" \
|
-e "1s|^|export GOROOT=$(GOROOT)\n|" \
|
||||||
-e "1s|^|WORK='$(BUILD_ABS_DIR)'\n|" \
|
-e "1s|^|export CGO_ENABLED=0\n|" \
|
||||||
-e "1s|^|alias pack='$(GO) tool pack'\n|" \
|
-e "1s|^|alias pack='$(GO) tool pack'\n|" \
|
||||||
-e "/^mv/d" \
|
-e "/^mv/d" \
|
||||||
|
-e "/\/buildid/d" \
|
||||||
-e "s|-extld|-tmpdir='$(BUILD_ABS_DIR)' -linkmode=external -extldflags='-nostartfiles -nodefaultlibs -nostdlib -r' -extld|g" \
|
-e "s|-extld|-tmpdir='$(BUILD_ABS_DIR)' -linkmode=external -extldflags='-nostartfiles -nodefaultlibs -nostdlib -r' -extld|g" \
|
||||||
| sh 2>&1 | sed -e "s/^/ | /g"
|
-e 's|$$WORK|$(BUILD_ABS_DIR)|g' \
|
||||||
|
| sh 2>&1 | sed -e "s/^/ | /g"
|
||||||
|
|
||||||
@# build/go.o is a elf32 object file but all go symbols are unexported. Our
|
@# build/go.o is a elf32 object file but all go symbols are unexported. Our
|
||||||
@# asm entrypoint code needs to know the address to 'main.main' so we use
|
@# asm entrypoint code needs to know the address to 'main.main' so we use
|
||||||
@ -105,7 +106,7 @@ $(BUILD_DIR)/go_asm_offsets.inc:
|
|||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
@echo "[tools:offsets] calculating OS/arch-specific offsets for g, m and stack structs"
|
@echo "[tools:offsets] calculating OS/arch-specific offsets for g, m and stack structs"
|
||||||
@GOPATH=$(GOPATH) $(GO) run tools/offsets/offsets.go -target-os $(GOOS) -target-arch $(GOARCH) -go-binary $(GO) -out $@
|
@GOROOT=$(GOROOT) GOPATH=$(GOPATH) $(GO) run tools/offsets/offsets.go -target-os $(GOOS) -target-arch $(GOARCH) -go-binary $(GO) -out $@
|
||||||
|
|
||||||
$(BUILD_DIR)/arch/$(ARCH)/asm/%.o: src/arch/$(ARCH)/asm/%.s
|
$(BUILD_DIR)/arch/$(ARCH)/asm/%.o: src/arch/$(ARCH)/asm/%.s
|
||||||
@mkdir -p $(shell dirname $@)
|
@mkdir -p $(shell dirname $@)
|
||||||
|
11
README.md
11
README.md
@ -4,6 +4,17 @@
|
|||||||
[](https://goreportcard.com/report/github.com/achilleasa/gopher-os)
|
[](https://goreportcard.com/report/github.com/achilleasa/gopher-os)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
|
| Go 1.7.x | Go 1.8.x | Go 1.9.x | Go 1.10.x | Go 1.x |
|
||||||
|
|---------------------|---------------------|---------------------|----------------------|-------------------|
|
||||||
|
| [![go 1.7.x][1]][6] | [![go 1.8.x][2]][6] | [![Go 1.9.x][3]][6] | [![go 1.10.x][4]][6] | [![go 1.x][5]][6] |
|
||||||
|
|
||||||
|
[1]: https://travis-matrix-badges.herokuapp.com/repos/achilleasa/gopher-os/branches/master/1
|
||||||
|
[2]: https://travis-matrix-badges.herokuapp.com/repos/achilleasa/gopher-os/branches/master/2
|
||||||
|
[3]: https://travis-matrix-badges.herokuapp.com/repos/achilleasa/gopher-os/branches/master/3
|
||||||
|
[4]: https://travis-matrix-badges.herokuapp.com/repos/achilleasa/gopher-os/branches/master/4
|
||||||
|
[5]: https://travis-matrix-badges.herokuapp.com/repos/achilleasa/gopher-os/branches/master/5
|
||||||
|
[6]: https://travis-ci.org/achilleasa/gopher-os
|
||||||
|
|
||||||
The goal of this project is to build a 64-bit POSIX-compliant tick-less kernel
|
The goal of this project is to build a 64-bit POSIX-compliant tick-less kernel
|
||||||
with a Linux-compatible syscall implementation using [Go](https://golang.org).
|
with a Linux-compatible syscall implementation using [Go](https://golang.org).
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ bits 64
|
|||||||
global x_cgo_callers
|
global x_cgo_callers
|
||||||
global x_cgo_init
|
global x_cgo_init
|
||||||
global x_cgo_mmap
|
global x_cgo_mmap
|
||||||
|
global x_cgo_munmap
|
||||||
global x_cgo_notify_runtime_init_done
|
global x_cgo_notify_runtime_init_done
|
||||||
global x_cgo_sigaction
|
global x_cgo_sigaction
|
||||||
global x_cgo_thread_start
|
global x_cgo_thread_start
|
||||||
@ -17,6 +18,7 @@ global _cgo_yield
|
|||||||
x_cgo_callers:
|
x_cgo_callers:
|
||||||
x_cgo_init:
|
x_cgo_init:
|
||||||
x_cgo_mmap:
|
x_cgo_mmap:
|
||||||
|
x_cgo_munmap:
|
||||||
x_cgo_notify_runtime_init_done:
|
x_cgo_notify_runtime_init_done:
|
||||||
x_cgo_sigaction:
|
x_cgo_sigaction:
|
||||||
x_cgo_thread_start:
|
x_cgo_thread_start:
|
||||||
|
@ -17,17 +17,17 @@ _rt0_idt_desc:
|
|||||||
resw 1
|
resw 1
|
||||||
resq 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
|
_rt0_irq_handlers resq IDT_ENTRIES
|
||||||
|
|
||||||
; According to the "ELF handling for TLS" document section 3.4.6
|
; 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,
|
; (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.
|
; before the TCB and are accessed using negative offsets from the TCB address.
|
||||||
r0_g_ptr: resq 1
|
r0_g_ptr: resq 1
|
||||||
tcb_ptr: resq 1
|
tcb_ptr: resq 1
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; Kernel 64-bit entry point
|
; Kernel 64-bit entry point
|
||||||
@ -36,7 +36,7 @@ section .text
|
|||||||
; - it has entered long mode and enabled paging
|
; - it has entered long mode and enabled paging
|
||||||
; - it has loaded a 64bit GDT
|
; - it has loaded a 64bit GDT
|
||||||
; - it has set up identity paging for the physical 0-8M region and the
|
; - 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
|
global _rt0_64_entry
|
||||||
_rt0_64_entry:
|
_rt0_64_entry:
|
||||||
@ -50,7 +50,7 @@ _rt0_64_entry:
|
|||||||
extern _kernel_start
|
extern _kernel_start
|
||||||
extern _kernel_end
|
extern _kernel_end
|
||||||
extern kernel.Kmain
|
extern kernel.Kmain
|
||||||
|
|
||||||
mov rax, PAGE_OFFSET
|
mov rax, PAGE_OFFSET
|
||||||
push rax
|
push rax
|
||||||
mov rax, _kernel_end - PAGE_OFFSET
|
mov rax, _kernel_end - PAGE_OFFSET
|
||||||
@ -60,7 +60,7 @@ _rt0_64_entry:
|
|||||||
mov rax, multiboot_data
|
mov rax, multiboot_data
|
||||||
push rax
|
push rax
|
||||||
call kernel.Kmain
|
call kernel.Kmain
|
||||||
|
|
||||||
; Main should never return; halt the CPU
|
; Main should never return; halt the CPU
|
||||||
mov rdi, err_kmain_returned
|
mov rdi, err_kmain_returned
|
||||||
call write_string
|
call write_string
|
||||||
@ -75,13 +75,15 @@ _rt0_64_entry:
|
|||||||
_rt0_64_setup_go_runtime_structs:
|
_rt0_64_setup_go_runtime_structs:
|
||||||
%include "go_asm_offsets.inc" ; generated by tools/offsets
|
%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
|
; 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
|
extern runtime.physPageSize
|
||||||
mov rax, runtime.physPageSize
|
mov rax, runtime.physPageSize
|
||||||
mov qword [rax], 0x1000 ; 4096
|
mov qword [rax], 0x1000 ; 4096
|
||||||
|
%endif
|
||||||
; Setup r0_g stack limits using the reserved stack
|
|
||||||
|
; Setup r0_g stack limits using the reserved stack
|
||||||
extern stack_top
|
extern stack_top
|
||||||
extern stack_bottom
|
extern stack_bottom
|
||||||
extern runtime.g0
|
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 [rbx+GO_M_G0], rsi ; m.g0 = g0
|
||||||
mov qword [rsi+GO_G_M], rbx ; g.m = m
|
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 rax, r0_g_ptr
|
||||||
mov qword [rax], rsi
|
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.
|
; TCB.
|
||||||
mov rax, tcb_ptr
|
mov rax, tcb_ptr
|
||||||
mov qword [rax], rax
|
mov qword [rax], rax
|
||||||
|
|
||||||
; Load 64-bit FS register address
|
; Load 64-bit FS register address
|
||||||
; eax -> lower 32 bits
|
; eax -> lower 32 bits
|
||||||
; edx -> upper 32 bits
|
; edx -> upper 32 bits
|
||||||
mov ecx, 0xc0000100 ; fs_base
|
mov ecx, 0xc0000100 ; fs_base
|
||||||
mov rsi, tcb_ptr
|
mov rsi, tcb_ptr
|
||||||
mov rax, rsi ; lower 32 bits
|
mov rax, rsi ; lower 32 bits
|
||||||
shr rsi, 32
|
shr rsi, 32
|
||||||
mov rdx, rsi ; high 32 bits
|
mov rdx, rsi ; high 32 bits
|
||||||
wrmsr
|
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
|
; 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
|
; but set it as inactive. The code in irq_amd64 is responsible for enabling
|
||||||
; individual IDT entries when handlers are installed.
|
; individual IDT entries when handlers are installed.
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
_rt0_64_load_idt:
|
_rt0_64_load_idt:
|
||||||
mov rax, _rt0_idt_start
|
mov rax, _rt0_idt_start
|
||||||
|
|
||||||
%assign gate_num 0
|
%assign gate_num 0
|
||||||
%rep IDT_ENTRIES
|
%rep IDT_ENTRIES
|
||||||
mov rbx, _rt0_64_gate_entry_%+ gate_num
|
mov rbx, _rt0_64_gate_entry_%+ gate_num
|
||||||
mov word [rax], bx ; gate entry bits 0-15
|
mov word [rax], bx ; gate entry bits 0-15
|
||||||
mov word [rax+2], 0x8 ; GDT descriptor
|
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
|
shr rbx, 16
|
||||||
mov word [rax+6], bx ; gate entry bits 16-31
|
mov word [rax+6], bx ; gate entry bits 16-31
|
||||||
shr rbx, 16
|
shr rbx, 16
|
||||||
mov dword [rax+8], ebx ; gate entry bits 32-63
|
mov dword [rax+8], ebx ; gate entry bits 32-63
|
||||||
|
|
||||||
add rax, 16 ; size of IDT entry
|
add rax, 16 ; size of IDT entry
|
||||||
%assign gate_num gate_num+1
|
%assign gate_num gate_num+1
|
||||||
%endrep
|
%endrep
|
||||||
mov rax, _rt0_idt_desc
|
mov rax, _rt0_idt_desc
|
||||||
mov word [rax], _rt0_idt_end - _rt0_idt_start - 1 ; similar to GDT this must be len(IDT) - 1
|
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.
|
; handler to the stack before jumping to a dispatcher function.
|
||||||
;
|
;
|
||||||
; Some exceptions push an error code to the stack after the stack frame. This
|
; 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
|
; 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
|
; are aware whether they need to deal with the code or not and jump to the
|
||||||
; appropriate get dispatcher.
|
; appropriate get dispatcher.
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
%assign gate_num 0
|
%assign gate_num 0
|
||||||
%rep IDT_ENTRIES
|
%rep IDT_ENTRIES
|
||||||
extern _rt0_interrupt_handlers
|
extern _rt0_interrupt_handlers
|
||||||
_rt0_64_gate_entry_%+ gate_num:
|
_rt0_64_gate_entry_%+ gate_num:
|
||||||
@ -177,13 +179,13 @@ _rt0_64_gate_entry_%+ gate_num:
|
|||||||
%else
|
%else
|
||||||
jmp _rt0_64_gate_dispatcher_without_code
|
jmp _rt0_64_gate_dispatcher_without_code
|
||||||
%endif
|
%endif
|
||||||
%assign gate_num gate_num+1
|
%assign gate_num gate_num+1
|
||||||
%endrep
|
%endrep
|
||||||
|
|
||||||
%macro save_regs 0
|
%macro save_regs 0
|
||||||
push r15
|
push r15
|
||||||
push r14
|
push r14
|
||||||
push r13
|
push r13
|
||||||
push r12
|
push r12
|
||||||
push r11
|
push r11
|
||||||
push r10
|
push r10
|
||||||
@ -191,10 +193,10 @@ _rt0_64_gate_entry_%+ gate_num:
|
|||||||
push r8
|
push r8
|
||||||
push rbp
|
push rbp
|
||||||
push rdi
|
push rdi
|
||||||
push rsi
|
push rsi
|
||||||
push rdx
|
push rdx
|
||||||
push rcx
|
push rcx
|
||||||
push rbx
|
push rbx
|
||||||
push rax
|
push rax
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
@ -203,13 +205,13 @@ _rt0_64_gate_entry_%+ gate_num:
|
|||||||
pop rbx
|
pop rbx
|
||||||
pop rcx
|
pop rcx
|
||||||
pop rdx
|
pop rdx
|
||||||
pop rsi
|
pop rsi
|
||||||
pop rdi
|
pop rdi
|
||||||
pop rbp
|
pop rbp
|
||||||
pop r8
|
pop r8
|
||||||
pop r9
|
pop r9
|
||||||
pop r10
|
pop r10
|
||||||
pop r11
|
pop r11
|
||||||
pop r12
|
pop r12
|
||||||
pop r13
|
pop r13
|
||||||
pop r14
|
pop r14
|
||||||
@ -217,14 +219,14 @@ _rt0_64_gate_entry_%+ gate_num:
|
|||||||
%endmacro
|
%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:
|
; by the CPU to the stack. It performs the following functions:
|
||||||
; - save registers
|
; - save registers
|
||||||
; - push pointer to saved regs
|
; - push pointer to saved regs
|
||||||
; - push pointer to stack frame
|
; - push pointer to stack frame
|
||||||
; - read and push exception code
|
; - read and push exception code
|
||||||
; - invoke handler(code, &frame, ®s)
|
; - invoke handler(code, &frame, ®s)
|
||||||
; - restore registers
|
; - restore registers
|
||||||
; - pop exception code from stack so rsp points to the stack frame
|
; - pop exception code from stack so rsp points to the stack frame
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
_rt0_64_gate_dispatcher_with_code:
|
_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
|
; Exception code | <- needs to be removed from stack before calling iretq
|
||||||
;-----------------|
|
;-----------------|
|
||||||
; RIP | <- exception frame
|
; RIP | <- exception frame
|
||||||
; CS |
|
; CS |
|
||||||
; RFLAGS |
|
; RFLAGS |
|
||||||
; RSP |
|
; RSP |
|
||||||
@ -244,12 +246,12 @@ _rt0_64_gate_dispatcher_with_code:
|
|||||||
;-----------------
|
;-----------------
|
||||||
cld
|
cld
|
||||||
|
|
||||||
; save regs and push a pointer to them
|
; save regs and push a pointer to them
|
||||||
save_regs
|
save_regs
|
||||||
mov rax, rsp ; rax points to saved rax
|
mov rax, rsp ; rax points to saved rax
|
||||||
push rax ; push pointer to saved regs
|
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
|
; saved registers plus one qword for the data pushed by the gate entry
|
||||||
; plus one extra qword to jump over the exception code)
|
; plus one extra qword to jump over the exception code)
|
||||||
add rax, 17*8
|
add rax, 17*8
|
||||||
@ -261,7 +263,7 @@ _rt0_64_gate_dispatcher_with_code:
|
|||||||
|
|
||||||
call [rsp + 18*8] ; call registered irq handler
|
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
|
restore_regs
|
||||||
|
|
||||||
add rsp, 16 ; pop handler address and exception code off the stack before returning
|
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.
|
; This dispatcher is invoked by gate entries that do not use exception codes.
|
||||||
; It performs the following functions:
|
; It performs the following functions:
|
||||||
; - save registers
|
; - save registers
|
||||||
; - push pointer to saved regs
|
; - push pointer to saved regs
|
||||||
; - push pointer to stack frame
|
; - push pointer to stack frame
|
||||||
; - invoke handler(&frame, ®s)
|
; - invoke handler(&frame, ®s)
|
||||||
; - restore registers
|
; - restore registers
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
_rt0_64_gate_dispatcher_without_code:
|
_rt0_64_gate_dispatcher_without_code:
|
||||||
; This is how the stack looks like when entering this function:
|
; 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)
|
; handler address | <- pushed by gate_entry_xxx (RSP points here)
|
||||||
;-----------------|
|
;-----------------|
|
||||||
; RIP | <- exception frame
|
; RIP | <- exception frame
|
||||||
; CS |
|
; CS |
|
||||||
; RFLAGS |
|
; RFLAGS |
|
||||||
; RSP |
|
; RSP |
|
||||||
@ -291,21 +293,21 @@ _rt0_64_gate_dispatcher_without_code:
|
|||||||
;-----------------
|
;-----------------
|
||||||
cld
|
cld
|
||||||
|
|
||||||
; save regs and push a pointer to them
|
; save regs and push a pointer to them
|
||||||
save_regs
|
save_regs
|
||||||
mov rax, rsp ; rax points to saved rax
|
mov rax, rsp ; rax points to saved rax
|
||||||
push rax ; push pointer to saved regs
|
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)
|
; saved registers plus one qword for the data pushed by the gate entry)
|
||||||
add rax, 16*8
|
add rax, 16*8
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
call [rsp + 17*8] ; call registered irq handler
|
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
|
restore_regs
|
||||||
|
|
||||||
add rsp, 8 ; pop handler address off the stack before returning
|
add rsp, 8 ; pop handler address off the stack before returning
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
@ -340,13 +342,13 @@ write_string:
|
|||||||
; runtime functions to the kernel's own implementation without the need to
|
; 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
|
; 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
|
; (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
|
; 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
|
; 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
|
; operating in supervisor mode with no memory protection enabled. Under normal
|
||||||
; conditions the .text section should be flagged as read-only.
|
; conditions the .text section should be flagged as read-only.
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
@ -355,7 +357,7 @@ _rt0_install_redirect_trampolines:
|
|||||||
mov rdx, NUM_REDIRECTS
|
mov rdx, NUM_REDIRECTS
|
||||||
|
|
||||||
_rt0_install_redirect_rampolines.next:
|
_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
|
mov rbx, [rax+8] ; the symbol to redirect to
|
||||||
|
|
||||||
; setup trampoline target and copy it to the hooked symbol
|
; setup trampoline target and copy it to the hooked symbol
|
||||||
@ -364,15 +366,15 @@ _rt0_install_redirect_rampolines.next:
|
|||||||
mov rcx, 14
|
mov rcx, 14
|
||||||
rep movsb ; copy rcx bytes from rsi to rdi
|
rep movsb ; copy rcx bytes from rsi to rdi
|
||||||
|
|
||||||
add rax, 16
|
add rax, 16
|
||||||
dec rdx
|
dec rdx
|
||||||
jnz _rt0_install_redirect_rampolines.next
|
jnz _rt0_install_redirect_rampolines.next
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; This trampoline exploits rip-relative addressing to allow a jump to a
|
; This trampoline exploits rip-relative addressing to allow a jump to a
|
||||||
; 64-bit address without the need to touch any registers. The generated
|
; 64-bit address without the need to touch any registers. The generated
|
||||||
; code is equivalent to:
|
; code is equivalent to:
|
||||||
;
|
;
|
||||||
; jmp [rip+0]
|
; jmp [rip+0]
|
||||||
@ -380,14 +382,14 @@ _rt0_install_redirect_rampolines.next:
|
|||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
_rt0_redirect_trampoline:
|
_rt0_redirect_trampoline:
|
||||||
db 0xff ; the first 6 bytes encode a "jmp [rip+0]" instruction
|
db 0xff ; the first 6 bytes encode a "jmp [rip+0]" instruction
|
||||||
db 0x25
|
db 0x25
|
||||||
dd 0x00
|
dd 0x00
|
||||||
dq 0x00 ; the absolute address to jump to
|
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
|
; 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
|
; enough space space for the src and dst addresses using the NUM_REDIRECTS
|
||||||
; define which is calculated by the Makefile and passed to nasm.
|
; define which is calculated by the Makefile and passed to nasm.
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
@ -395,7 +397,7 @@ section .goredirectstbl
|
|||||||
|
|
||||||
_rt0_redirect_table:
|
_rt0_redirect_table:
|
||||||
%rep NUM_REDIRECTS
|
%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
|
dq 0 ; dst: address of the symbol where calls to src are redirected to
|
||||||
%endrep
|
%endrep
|
||||||
|
|
||||||
|
@ -27,27 +27,6 @@ var (
|
|||||||
prngSeed = 0xdeadc0de
|
prngSeed = 0xdeadc0de
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname algInit runtime.alginit
|
|
||||||
func algInit()
|
|
||||||
|
|
||||||
//go:linkname modulesInit runtime.modulesinit
|
|
||||||
func modulesInit()
|
|
||||||
|
|
||||||
//go:linkname typeLinksInit runtime.typelinksinit
|
|
||||||
func typeLinksInit()
|
|
||||||
|
|
||||||
//go:linkname itabsInit runtime.itabsinit
|
|
||||||
func itabsInit()
|
|
||||||
|
|
||||||
//go:linkname mallocInit runtime.mallocinit
|
|
||||||
func mallocInit()
|
|
||||||
|
|
||||||
//go:linkname mSysStatInc runtime.mSysStatInc
|
|
||||||
func mSysStatInc(*uint64, uintptr)
|
|
||||||
|
|
||||||
//go:linkname procResize runtime.procresize
|
|
||||||
func procResize(int32) uintptr
|
|
||||||
|
|
||||||
// initGoPackages is an alias to main.init which recursively calls the init()
|
// initGoPackages is an alias to main.init which recursively calls the init()
|
||||||
// methods in all imported packages. Unless this function is called, things like
|
// methods in all imported packages. Unless this function is called, things like
|
||||||
// package errors will not be properly initialized causing various problems when
|
// package errors will not be properly initialized causing various problems when
|
||||||
@ -184,7 +163,7 @@ func getRandomData(r []byte) {
|
|||||||
func Init() *kernel.Error {
|
func Init() *kernel.Error {
|
||||||
mallocInitFn()
|
mallocInitFn()
|
||||||
algInitFn() // setup hash implementation for map keys
|
algInitFn() // setup hash implementation for map keys
|
||||||
modulesInitFn() // provides activeModules
|
modulesInitFn() // provides activeModules (go 1.8+)
|
||||||
typeLinksInitFn() // uses maps, activeModules
|
typeLinksInitFn() // uses maps, activeModules
|
||||||
itabsInitFn() // uses activeModules
|
itabsInitFn() // uses activeModules
|
||||||
|
|
||||||
|
30
src/gopheros/kernel/goruntime/bootstrap_go17.go
Normal file
30
src/gopheros/kernel/goruntime/bootstrap_go17.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// +build go1.7,!go1.8
|
||||||
|
|
||||||
|
package goruntime
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe" // required for go:linkname
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname algInit runtime.alginit
|
||||||
|
func algInit()
|
||||||
|
|
||||||
|
//go:linkname typeLinksInit runtime.typelinksinit
|
||||||
|
func typeLinksInit()
|
||||||
|
|
||||||
|
//go:linkname itabsInit runtime.itabsinit
|
||||||
|
func itabsInit()
|
||||||
|
|
||||||
|
//go:linkname mallocInit runtime.mallocinit
|
||||||
|
func mallocInit()
|
||||||
|
|
||||||
|
//go:linkname mSysStatInc runtime.mSysStatInc
|
||||||
|
func mSysStatInc(*uint64, uintptr)
|
||||||
|
|
||||||
|
//go:linkname procResize runtime.procresize
|
||||||
|
func procResize(int32) uintptr
|
||||||
|
|
||||||
|
// modulesInit is defined on go1.8 so just declare an empty
|
||||||
|
// stub for go 1.7 to keep the compiler happy.
|
||||||
|
func modulesInit() {
|
||||||
|
}
|
28
src/gopheros/kernel/goruntime/bootstrap_go18+.go
Normal file
28
src/gopheros/kernel/goruntime/bootstrap_go18+.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
package goruntime
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe" // required for go:linkname
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname algInit runtime.alginit
|
||||||
|
func algInit()
|
||||||
|
|
||||||
|
//go:linkname modulesInit runtime.modulesinit
|
||||||
|
func modulesInit()
|
||||||
|
|
||||||
|
//go:linkname typeLinksInit runtime.typelinksinit
|
||||||
|
func typeLinksInit()
|
||||||
|
|
||||||
|
//go:linkname itabsInit runtime.itabsinit
|
||||||
|
func itabsInit()
|
||||||
|
|
||||||
|
//go:linkname mallocInit runtime.mallocinit
|
||||||
|
func mallocInit()
|
||||||
|
|
||||||
|
//go:linkname mSysStatInc runtime.mSysStatInc
|
||||||
|
func mSysStatInc(*uint64, uintptr)
|
||||||
|
|
||||||
|
//go:linkname procResize runtime.procresize
|
||||||
|
func procResize(int32) uintptr
|
@ -7,6 +7,8 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -30,6 +32,7 @@ func genBuildScript(targetOS, targetArch, goBinary, workDir string) ([]byte, err
|
|||||||
// rebuild the runtime packages.
|
// rebuild the runtime packages.
|
||||||
cmd := exec.Command(goBinary, "build", "-a", "-n")
|
cmd := exec.Command(goBinary, "build", "-a", "-n")
|
||||||
cmd.Dir = workDir
|
cmd.Dir = workDir
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GOROOT=%s", os.Getenv("GOROOT")))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GOOS=%s", targetOS))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GOOS=%s", targetOS))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GOARCH=%s", targetArch))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GOARCH=%s", targetArch))
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
@ -41,13 +44,18 @@ func genBuildScript(targetOS, targetArch, goBinary, workDir string) ([]byte, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func patchBuildScript(script []byte, workDir, targetOS, targetArch, goBinary string) ([]byte, error) {
|
func patchBuildScript(script []byte, workDir, targetOS, targetArch, goBinary string) ([]byte, error) {
|
||||||
lines := strings.Split(string(script), "\n")
|
// Replace $WORK with the workDir location. This is required for executing
|
||||||
|
// build scripts generated by go 1.10
|
||||||
|
lines := strings.Split(
|
||||||
|
strings.Replace(string(script), "$WORK", workDir, -1),
|
||||||
|
"\n",
|
||||||
|
)
|
||||||
|
|
||||||
// Inject os/arch and workdir to the top of the build file
|
// Inject os/arch and workdir to the top of the build file
|
||||||
header := []string{
|
header := []string{
|
||||||
|
fmt.Sprintf("export GOROOT=%s", os.Getenv("GOROOT")),
|
||||||
fmt.Sprintf("export GOOS=%s", targetOS),
|
fmt.Sprintf("export GOOS=%s", targetOS),
|
||||||
fmt.Sprintf("export GOARCH=%s", targetArch),
|
fmt.Sprintf("export GOARCH=%s", targetArch),
|
||||||
fmt.Sprintf("WORK=%q", workDir),
|
|
||||||
fmt.Sprintf("alias pack='%s tool pack'", goBinary),
|
fmt.Sprintf("alias pack='%s tool pack'", goBinary),
|
||||||
}
|
}
|
||||||
lines = append(header, lines...)
|
lines = append(header, lines...)
|
||||||
@ -58,7 +66,7 @@ func patchBuildScript(script []byte, workDir, targetOS, targetArch, goBinary str
|
|||||||
var stopOnNextComment bool
|
var stopOnNextComment bool
|
||||||
for lineIndex := 0; lineIndex < len(lines); lineIndex++ {
|
for lineIndex := 0; lineIndex < len(lines); lineIndex++ {
|
||||||
// Ignore empty comments
|
// Ignore empty comments
|
||||||
if lines[lineIndex] == "#" {
|
if strings.TrimSpace(lines[lineIndex]) == "#" || strings.Contains(lines[lineIndex], "# import") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,8 +105,32 @@ func execBuildScript(script []byte, workDir string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func genAsmIncludes(workDir string) ([]byte, error) {
|
func genAsmIncludes(workDir string) ([]byte, error) {
|
||||||
headers, err := ioutil.ReadFile(fmt.Sprintf("%s/runtime/_obj/go_asm.h", workDir))
|
// Find all generated go_asm.h files and concat their conentents
|
||||||
if err != nil {
|
var (
|
||||||
|
allHeaders, headers []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := filepath.Walk(workDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if filepath.Base(path) != "go_asm.h" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if headers, err = ioutil.ReadFile(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
allHeaders = append(allHeaders, '\n')
|
||||||
|
allHeaders = append(allHeaders, headers...)
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +138,7 @@ func genAsmIncludes(workDir string) ([]byte, error) {
|
|||||||
includes = append(includes, "; vim: set ft=nasm :\n")
|
includes = append(includes, "; vim: set ft=nasm :\n")
|
||||||
includes = append(includes, fmt.Sprintf("; generated by tools/offsets at %v\n", time.Now()))
|
includes = append(includes, fmt.Sprintf("; generated by tools/offsets at %v\n", time.Now()))
|
||||||
|
|
||||||
for _, line := range strings.Split(string(headers), "\n") {
|
for _, line := range strings.Split(string(allHeaders), "\n") {
|
||||||
line = strings.TrimPrefix(line, "#define ")
|
line = strings.TrimPrefix(line, "#define ")
|
||||||
|
|
||||||
// We are only interested in the offsets for the g, m and stack structures
|
// We are only interested in the offsets for the g, m and stack structures
|
||||||
@ -131,6 +163,16 @@ func genAsmIncludes(workDir string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In go 1.7.x, the page size is given by the _PageSize constant whereas in
|
||||||
|
// newer go versions it is specified at runtime and needs to be manually set
|
||||||
|
// by our asm bootstrap code.
|
||||||
|
if strings.Contains(runtime.Version(), "go1.7") {
|
||||||
|
includes = append(includes,
|
||||||
|
"; go 1.7 runtime uses a fixed 4k page size for our target arch so our bootstrap code does not need to do any extra work to set it up",
|
||||||
|
"%define SKIP_PAGESIZE_SETUP 1",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return []byte(strings.Join(includes, "\n")), nil
|
return []byte(strings.Join(includes, "\n")), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user