diff --git a/kernel/asm_amd64.s b/kernel/asm_amd64.s index 9c9e423..1bf3dc7 100644 --- a/kernel/asm_amd64.s +++ b/kernel/asm_amd64.s @@ -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). 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). 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 @@ -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 +// 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 diff --git a/kernel/simd.go b/kernel/simd.go index 59e8fb5..6b87bcd 100644 --- a/kernel/simd.go +++ b/kernel/simd.go @@ -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 function wrappers introduced in Go 1.17. // init for avx // first check avx function diff --git a/kernel/trap.s b/kernel/trap.s index 58135d4..1d374e7 100644 --- a/kernel/trap.s +++ b/kernel/trap.s @@ -57,5 +57,13 @@ TEXT ·trapret(SB), NOSPLIT, $0 ADDQ $16, SP // skip trapno and errcode + ADDQ $8, SP // NOTE: skip return address of function (added in Go 1.17). + + // Dump of assembler code for function github.com/icexin/eggos/kernel.trapret: + // => 0x00000000002bbf60 <+0>: call 0x2b9e40 + // 0x00000000002bbf65 <+5>: xorps %xmm15,%xmm15 + // 0x00000000002bbf69 <+9>: mov %fs:0xfffffffffffffff8,%r14 + // 0x00000000002bbf72 <+18>: ret + IRETQ