-
Notifications
You must be signed in to change notification settings - Fork 13
Add powerpc64 and mips32 architecture support #170
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
base: main
Are you sure you want to change the base?
Conversation
Add startup code for powerpc64le (ELFv2 ABI) and mipsel (O32 ABI) targets, enabling no_std programs to run on these architectures. PowerPC64 (powerpc64.rs): - _start sets up r2 (TOC pointer) using r12 before calling entry - trap() uses the `trap` instruction - Full thread support scaffolding (clone, thread pointer, TLS) - Relocation support for PIC binaries MIPS32 (mips32.rs): - __start entry point (MIPS convention, not _start) - 8-byte stack alignment with 16-byte O32 save area - trap() uses the `break` instruction - Thread support using rdhwr for thread pointer - Syscall convention: $v0=syscall#, $a0-$a3=args, $a3=error flag Both architectures: - Implement origin-start feature for program startup - Support optimize_for_size feature - Follow existing origin patterns from other architectures Tested with QEMU user-mode emulation (qemu-ppc64le-static, qemu-mipsel-static). Note: QEMU ppc64le has a bug with argv setup for non-glibc binaries, but the startup code itself is correct and works on real hardware.
sunfishcode
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks for contributing these! I have a few comments below, and CI wants a rustfmt.
Also, we should probably mention in README.md that these new targets and also ARM aren't currently tested in CI. I can do that if you prefer though.
| /// MIPS O32 ABI: $sp holds the stack pointer, $a0-$a3 are argument registers. | ||
| /// At entry, argc is at 0($sp), argv at 4($sp), etc. | ||
| // MIPS uses __start as the default entry point, not _start. | ||
| // We provide both names for compatibility. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says that both names are provided, but I only see code the __start defined here. Origin is all about not dragging along old baggage, so if plain __start is enough, then perhaps just the comment should be changed.
| // yet initialized at this point. | ||
| trap(); | ||
| } | ||
| let _ = r0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If r0 isn't needed, can the asm be simplified to avoid having it as an out param?
| ); | ||
| // Note: child_tid handling is simplified here; full implementation would | ||
| // need to push it to the stack frame per O32 calling convention. | ||
| let _ = child_tid; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that CLONE_CHILD_CLEARTID and/or CLONE_CHILD_SETTID are not supported? If so, could we explicitly check for those and fail with ENOTSUP or so, so that they aren't silently ignored?
| asm!( | ||
| "move $a0, {0}", | ||
| ".set noreorder", | ||
| "li $v0, 4283", // __NR_set_thread_area |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it work to import __NR_set_thread_area from linux_raw_sys and use it as a const operand, rather than hard-coding the value here?
This adds startup code for powerpc64le (ELF v2 ABI) and mipsel (O32 ABI).
Two new arch modules: powerpc64.rs and mips32.rs. Each one has the usual set: entry point, trap(), dynamic_table_addr(), relocation helpers, thread support, etc.
The tricky part on PowerPC64 is r2 (TOC pointer) setup. On ELF v2, r12 contains the entry point address at program start, and we need to compute r2 from it before touching any global/static data:
Without this, any access to static data gives EFAULT because r2 is garbage. Syscalls use the
scinstruction with error indicated by the cr0.SO flag (not negative return like x86).MIPS uses
__startas entry point (MIPS convention). The O32 ABI requires a 16-byte argument save area on the stack, and indirect jumps should go through$t9for PIC compatibility. Thread pointer is accessed via the userlocal register:rdhwr $3, $29.I tested with a minimal no_std binary that reads a static variable and exits with code 42. Both architectures work under QEMU user-mode.
I also tested with a larger application (kv) that does file I/O and string formatting. MIPS works fully including argument parsing. PowerPC64 works the same way except for an argv issue - as far as I can tell from various workarounds and debugging, it's the same correct behavior, but there's a QEMU user-mode bug that corrupts the argv array for non-glibc PPC64LE binaries. The argument strings are placed correctly in memory, but the pointer array has NULLs interleaved. This only affects QEMU emulation, not the origin code itself.