Add partial aarch64 support to libuser#566
Add partial aarch64 support to libuser#566leo60228 wants to merge 10 commits intosunriseos:masterfrom
Conversation
aarch64 requires syscall numbers be immediates, so a standard function can't be used here.
This was created by diffing the i386 JSON with i686-unknown-linux-gnu, and applying relevant changes to aarch64-unknown-linux-gnu.
|
I've implemented a syscall stub, it was easier than I thought. |
| tls | ||
| } | ||
|
|
||
| /// Get a pointer to this thread's [TLS] region pointed to by `fs`, translated to the flat-memory model. |
| /// | ||
| /// The routine to call and its argument are expected to be found in this `ThreadContext`. | ||
| #[cfg(not(target_arch = "x86"))] | ||
| extern fn thread_trampoline(thread_context_addr: usize) -> ! { |
There was a problem hiding this comment.
almost certainly not valid for aarch64.
This deserves a huge
// todo: figure out aarch64 elf TLS
| eax: usize, | ||
| ebx: usize, | ||
| ecx: usize, | ||
| edx: usize, | ||
| esi: usize, | ||
| edi: usize, | ||
| ebp: usize, |
There was a problem hiding this comment.
@roblabla , I need your confirmation on this, but IIRC the sole reason we use a global asm for the syscall is because we need to pass ebp as our sixth argument, but trying to backup+set/restore it in an inline asm block was unfeasible, because Rust needs this register to exit the inline asm block and restore regular context (or something like that).
This struct is only used as an argument to the global asm syscall_iner. This is pretty inefficient, since to do a syscall you must:
- push all 6 arguments on the stack, and call
syscall. (this is standard i386 ABI) syscallcopies those arguments to fill a newRegisterstructure, and callssyscall_innersyscall_innerconsumes this struct, and puts every field in a register.int 0x80syscall_innersaves the return registers state to theRegisterstructure, and returns.
On aarch64, where we have plenty of registers, this whole dance seems unnecessary, and I'd like to see the syscall function simply be a wrapper around a single inline asm instruction, that define its input/output registers properly (e.g. nr -> r0) and let llvm do all the copying for us.
In this context, the Register struct is very i386 specific, and doesn't need to be made generic.
I'd like to hear roblabla's opinion this, but if he agrees with me I'd recommend dropping this commit entirely
| #[cfg(target_arch = "aarch64")] | ||
| asm!( | ||
| "svc $7" | ||
| : "={x0}"(registers.nr), |
There was a problem hiding this comment.
wow, you did exactly what I was discussing in the previous comment 😅
For aarch64, I don't see the need for copying arguments to the Registers struct. Can't you just directly use nr ?
There was a problem hiding this comment.
I thought Registers was in the public API? If it isn't, that's unnecessary.
There was a problem hiding this comment.
It was, but I think that's a mistake, it should be defined only for i386
This reverts commit 253cacd.
This is able to make libuser compile with the included target JSON. It does not yet include a crt0 or syscall stub, though preparations for that have been made (I'm not experienced enough with aarch64 assembly).