Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

draft PR for gaining insight into what is needed for Go 1.17 calling conventions; DO NOT MERGE #104

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions kernel/asm_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ TEXT ·rt0(SB), NOSPLIT, $0-0
SUBQ $0x10, SP
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)

// NOTE: the SSE instruction set must be initialized prior to invoking the
// first Go function, since any transition from asm -> Go will be handled by
// an autogenerated Go function wrapper for the given function (e.g.
// kernel.preinit<autogenerated>). The autogenerated function invokes
// `xorps %xmm15, %xmm15` which crashes the machine unless the FPU has been
// initialized.
CALL ·sseInit(SB)

// NOTE: the fs segment register must be set prior to invoking the first Go
// function, since any transition from asm -> Go will be handled by an
// autogenerated Go function wrapper for the given function (e.g.
// kernel.preinit<autogenerated>). The autogenerated function invokes
// `%fs:0xfffffffffffffff8,%r14` which crashes the machine unless the fs
// segment register has been set.
CALL ·initFakeFS(SB)

CALL ·preinit(SB)
INT $3

Expand All @@ -27,6 +44,24 @@ TEXT ·go_entry(SB), NOSPLIT, $0
ADDQ $8, SP
JMP _rt0_amd64_linux(SB)

// initFakeFS initializes a valid fake %fs segment register as required by the
// <autogenerated> function wrappers of the Go 1.17 calling convention
// (see icexin/eggos#100) when invoked before kernel.thread0Init.
TEXT ·initFakeFS(SB), NOSPLIT, $0
// HACK: just use a memory pointer on the stack that we are unlikely to
// overwrite untill we run thread0Init, at which point, %fs will be set to
// its real value.
SUBQ $100000, SP // TODO: figure out a better way to handle %fs, use a memory address that will never be used before by other instructions before thread0Init.

MOVL $0xc0000100, CX // _MSR_FS_BASE
MOVL SP, AX // low, just to get a valid address to.
//ADDL $0x3, AX // low, set lower 2 bits to prevent EIO error
MOVL $0x0, DX // high
WRMSR

ADDQ $100000, SP
RET

// sseInit initializes the SSE instruction set.
TEXT ·sseInit(SB), NOSPLIT, $0
MOVL CR0, AX
Expand Down
2 changes: 1 addition & 1 deletion kernel/simd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func cpuid(fn, cx uint32) (eax, ebx, ecx, edx uint32)

//go:nosplit
func simdInit() {
sseInit()
//sseInit() // NOTE: invoked from asm (instead of Go) to support <autogenerated> function wrappers introduced in Go 1.17.

// init for avx
// first check avx function
Expand Down
8 changes: 8 additions & 0 deletions kernel/trap.s
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,13 @@ TEXT ·trapret(SB), NOSPLIT, $0

ADDQ $16, SP // skip trapno and errcode

ADDQ $8, SP // NOTE: skip return address of <autogenerated> function (added in Go 1.17).

// Dump of assembler code for function github.com/icexin/eggos/kernel.trapret<autogenerated>:
// => 0x00000000002bbf60 <+0>: call 0x2b9e40 <github.com/icexin/eggos/kernel.trapret>
// 0x00000000002bbf65 <+5>: xorps %xmm15,%xmm15
// 0x00000000002bbf69 <+9>: mov %fs:0xfffffffffffffff8,%r14
// 0x00000000002bbf72 <+18>: ret

IRETQ