|
Message-ID: <2047231.C4sosBPzcN@sheen> Date: Fri, 29 May 2020 19:03:48 +0000 From: Will Springer <skirmisher@...tonmail.com> To: linuxppc-dev@...ts.ozlabs.org Cc: binutils@...rceware.org, libc-dev@...ts.llvm.org, libc-alpha@...rceware.org, musl@...ts.openwall.com, daniel@...aforge.org, eery@...erfox.es Subject: ppc64le and 32-bit LE userland compatibility Hey all, a couple of us over in #talos-workstation on freenode have been working on an effort to bring up a Linux PowerPC userland that runs in 32-bit little-endian mode, aka ppcle. As far as we can tell, no ABI has ever been designated for this (unless you count the patchset from a decade ago [1]), so it's pretty much uncharted territory as far as Linux is concerned. We want to sync up with libc and the relevant kernel folks to establish the best path forward. The practical application that drove these early developments (as you might expect) is x86 emulation. The box86 project [2] implements a translation layer for ia32 library calls to native architecture ones; this way, emulation overhead is significantly reduced by relying on native libraries where possible (libc, libGL, etc.) instead of emulating an entire x86 userspace. box86 is primarily targeted at ARM, but it can be adapted to other architectures—so long as they match ia32's 32-bit, little-endian nature. Hence the need for a ppcle userland; modern POWER brought ppc64le as a supported configuration, but without a 32-bit equivalent there is no option for a 32/64 multilib environment, as seen with ppc/ppc64 and arm/aarch64. Surprisingly, beyond minor patching of gcc to get crosscompile going, bootstrapping the initial userland was not much of a problem. The work has been done on top of the Void Linux PowerPC project [3], and much of that is now present in its source package tree [4]. The first issue with running the userland came from the ppc32 signal handler forcing BE in the MSR, causing any 32LE process receiving a signal (such as a shell receiving SIGCHLD) to terminate with SIGILL. This was trivially patched, along with enabling the 32-bit vDSO on ppc64le kernels [5]. (Given that this behavior has been in place since 2006, I don't think anyone has been using the kernel in this state to run ppcle userlands.) The next problem concerns the ABI more directly. The failure mode was `file` surfacing EINVAL from pread64 when invoked on an ELF; pread64 was passed a garbage value for `pos`, which didn't appear to be caused by anything in `file`. Initially it seemed as though the 32-bit components of the arg were getting swapped, and we made hacky fixes to glibc and musl to put them in the "right order"; however, we weren't sure if that was the correct approach, or if there were knock-on effects we didn't know about. So we found the relevant compat code path in the kernel, at arch/powerpc/kernel/sys_ppc32.c, where there exists this comment: > /* > * long long munging: > * The 32 bit ABI passes long longs in an odd even register pair. > */ It seems that the opposite is true in LE mode, and something is expecting long longs to start on an even register. I realized this after I tried swapping hi/ lo `u32`s here and didn't see an improvement. I whipped up a patch [6] that switches which syscalls use padding arguments depending on endianness, while hopefully remaining tidy enough to be unobtrusive. (I took some liberties with variable names/types so that the macro could be consistent.) This was enough to fix up the `file` bug. I'm no seasoned kernel hacker, though, and there is still concern over the right way to approach this, whether it should live in the kernel or libc, etc. Frankly, I don't know the ABI structure enough to understand why the register padding has to be different in this case, or what lower-level component is responsible for it. For comparison, I had a look at the mips tree, since it's bi-endian and has a similar 32/64 situation. There is a macro conditional upon endianness that is responsible for munging long longs; it uses __MIPSEB__ and __MIPSEL__ instead of an if/else on the generic __LITTLE_ENDIAN__. Not sure what to make of that. (It also simply swaps registers for LE, unlike what I did for ppc.) Also worth noting is the one other outstanding bug, where the time-related syscalls in the 32-bit vDSO seem to return garbage. It doesn't look like an endian bug to me, and it doesn't affect standard syscalls (which is why if you run `date` on musl it prints the correct time, unlike on glibc). The vDSO time functions are implemented in ppc asm (arch/powerpc/kernel/vdso32/ gettimeofday.S), and I've never touched the stuff, so if anyone has a clue I'm all ears. Again, I'd appreciate feedback on the approach to take here, in order to touch/special-case only the minimum necessary, while keeping the kernel/libc folks happy. Cheers, Will [she/her] (p.s. there is ancillary interest in a ppcle-native kernel as well; that's a good deal more work and not the focus of this message at all, but it is a topic of interest) [1]: https://lwn.net/Articles/408845/ [2]: https://github.com/ptitSeb/box86 [3]: https://voidlinux-ppc.org/ [4]: https://github.com/void-ppc/void-packages [5]: https://gist.github.com/eerykitty/01707dc6bca2be32b4c5e30d15d15dcf [6]: https://gist.github.com/Skirmisher/02891c1a8cafa0ff18b2460933ef4f3c
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.