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

add support for go1.17 #100

Open
icexin opened this issue Feb 6, 2022 · 2 comments
Open

add support for go1.17 #100

icexin opened this issue Feb 6, 2022 · 2 comments

Comments

@icexin
Copy link
Owner

icexin commented Feb 6, 2022

Go 1.17 implements a new way of passing function arguments and results using registers instead of the stack.

This issue is used to track affected modules and corresponding PRs.

mewmew added a commit to 7i/shorter that referenced this issue Feb 10, 2022
Note: eggos currently requires Go 1.16.

See upstream issue for Go 1.17 support (ref: icexin/eggos#100).
@mewmew
Copy link
Contributor

mewmew commented Feb 10, 2022

I tried generating a "hello world" eggos kernel using Go 1.17, to debug the boot process.

Unexpectedly, it crashes quite early due to ABI changes introduced in Go 1.17.

In particular, the crash occurs in an autogenerated wrapper for kernel.preinit (NOTE: the autogenerated wrapper function is not present in Go 1.16):

Dump of assembler code for function github.com/icexin/eggos/kernel.preinit<autogenerated>:
   0x00000000002bbe40 <+0>:	sub    $0x18,%rsp
   0x00000000002bbe44 <+4>:	mov    %rbp,0x10(%rsp)
   0x00000000002bbe49 <+9>:	lea    0x10(%rsp),%rbp
   0x00000000002bbe4e <+14>:	mov    0x20(%rsp),%rax
   0x00000000002bbe53 <+19>:	mov    0x28(%rsp),%rbx
=> 0x00000000002bbe58 <+24>:	xorps  %xmm15,%xmm15
   0x00000000002bbe5c <+28>:	mov    %fs:0xfffffffffffffff8,%r14
   0x00000000002bbe65 <+37>:	call   0x2b6c40 <github.com/icexin/eggos/kernel.preinit>
   0x00000000002bbe6a <+42>:	mov    0x10(%rsp),%rbp
   0x00000000002bbe6f <+47>:	add    $0x18,%rsp
   0x00000000002bbe73 <+51>:	ret    
End of assembler dump.
(gdb) si
[Inferior 1 (process 1) exited normally]
(gdb) 

The reason for the crash is most likely that the FPU has not yet been initialized; thus causing the instruction xorps %xmm15,%xmm15 to crash.

@mewmew
Copy link
Contributor

mewmew commented Feb 10, 2022

Notes on the new register-based calling convention introduced Go 1.17 ("ABIInternal"), and how gVisor handles it:

google/gvisor@1084106

mewmew added a commit to mewpull/eggos that referenced this issue Feb 12, 2022
…ed> function wrappers of Go 1.17

In Go 1.17, when invoking Go functions from asm, <autogenerated>
function wrappers are generated to handle the conversion from the
old Go ABI (abi0) which is stack based to the new internal
register-based Go ABI (abi1).

The problem is that the <autogenerated> function wrapper assumes
that we are already running in a fully initialized Go environment,
with support for SSE instructions and with a configured %fs segment
register to handle TLS of G.

For context, see the autogenerated function wrapper which is invoked
when calling the Go kernel.preinit function from the asm rt0 function.

	Dump of assembler code for function github.com/icexin/eggos/kernel.preinit<autogenerated>:
		0x00000000002bbe40 <+0>:	sub    $0x18,%rsp
		0x00000000002bbe44 <+4>:	mov    %rbp,0x10(%rsp)
		0x00000000002bbe49 <+9>:	lea    0x10(%rsp),%rbp
		0x00000000002bbe4e <+14>:	mov    0x20(%rsp),%rax
		0x00000000002bbe53 <+19>:	mov    0x28(%rsp),%rbx
	=> 0x00000000002bbe58 <+24>:	xorps  %xmm15,%xmm15
		0x00000000002bbe5c <+28>:	mov    %fs:0xfffffffffffffff8,%r14
		0x00000000002bbe65 <+37>:	call   0x2b6c40 <github.com/icexin/eggos/kernel.preinit>
		0x00000000002bbe6a <+42>:	mov    0x10(%rsp),%rbp
		0x00000000002bbe6f <+47>:	add    $0x18,%rsp
		0x00000000002bbe73 <+51>:	ret

As visible in the disassembly of kernel.preinit<autogenerated>,
the XMM15 register is set to zero using XOR (see offset +24),
which requires SSE instructions to be initialized.

Also, on offset +28, the R14 register is moved into TLS by
using the %fs segment register. R14 store G in Go 1.17.

To handle this case, we need to initialize %fs to a valid memory
location; we use a fake memory location, as no Go routines are
running at this point, and later on %fs will be set when the first
goroutine is started by thread0Init.

Note, this is just a preliminary work to better understand what
we must support to handle Go 1.17. We are most likely _not_ going
to use this code for the final commit to eggos. This is just to
get more intuition into the problem domain.

Updates icexin#100.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants