fef's blog

2021-11-30

Moving Away From The x86

The world seems to be slowly distancing itself from The x86 in favor of less insane architectures like ARM and, in some cases, even RISC-V. Naturally, as someone who has experienced what systems programming on The x86 is like themself lately, i welcome this shift with open arms (believe me, you really do not want to bootstrap an Intel processor). However, this does not mean we aren’t going to run into major issues. TL;DR: It would be super cool to have an ARM daughter board that pops into one of your x86 tower’s PCIe slots, and use kernel magic to connect the two for native binary compatibility with multiple architectures.

How We Are Currently Handling It

A lot of software is just straight up not available on those platforms at the moment, and some of it never will be, especially the proprietary pieces. Major software companies typically respond to this by pushing application development towards interpreted languages like, in the case of Microsoft, C#. Or they are Apple who, very much in line their tradition, went full bonkers and made Rosetta 2, an x86 to ARM recompiler.

Now, the Open Source community isn’t nearly affected as much by all of this. Most software that is written in languages that produce native binaries can just be compiled for whatever architecture you desire. And by the nature of being open source, those that can’t can at least be adopted by the community. Not to mention that popular open source kernels, most notably Linux, have been ported to just about anything with a processor.

Lame!

The two corporate solutions have problems. Both come with a performance penalty because of the recompilation overhead (JIT in the case of C#, AOT for Rosetta). Also, i don’t find them particularly cool or exciting. You know what would be super cool and exciting, though? Throwing hardware at the problem! Design a daughter board with an ARM processor that you can stick into one of your existing x86 tower’s PCI Express slots and boom, you’re done! This is also what Apple did way back in 1995 with the Power Macintosh 6100/66 by the way, so we know that at least in theory it could work as a viable product. Now, of course it isn’t quite that easy, because you will also need at the very least a kernel that plays along with it.

Introducing GayBSD

If you follow me in the Fediverse or on Bird Site, you might have already gotten wind of that thing currently working on called GayBSD (actually, besides rants about The x86, it’s almost exclusively what i post about these days). It is basically a microkernel that, except for its libc and probably its network stack once that becomes a thing, is written completely from scratch. As the BSD in its name suggests, it is supposed to be a BSD adjacent kernel, and i am in fact aiming for ABI compatibility to FreeBSD in the end. I was already playing with the thought of making it not only a microkernel but also a distributed one, and this seems like the ideal use case: native binary compatibility on multiple architectures! The project is still extremely young; as a matter of fact, i haven’t even reached user space yet. So, i have decided to take the opportunity and leave the core design open to such an extension. It shouldn’t even be that much extra work, since the nature of being a microkernel requires some form of abstract IPC protocol anyway.

But how would this be implemented in practice? My thought is to handle it kind of similar to the way FreeBSD does ABI compatibility to Linux and other kernels. You have a /compat directory that essentially contains system roots for the respective native kernel and architecture (e.g. /compat/x86-freebsd for x86 FreeBSD binaries), and when you execve something the kernel automatically chroots into the respective directory first. The directories inside the sysroot that are supposed to be identical on all architectures (like, pretty much anything besides program binaries) can just be bindings to the actual system root.

This leaves us with only one problem: shared memory. If an ARM program wants to do IPC with an x86 daemon by writing data to shared memory, there might be a mismatch between the data structure on x86 and ARM. I don’t expect this to be a major problem in most cases, because C’s fundamental data types are (as far as i know) the same length on both platforms, but there might still be architecture specific quirks in individual programs. You probably have to try before you can tell for sure. Another, rather obscure situation would be if the daemon was a JIT compiler, in which case the only solution would of course be spawning an entirely new daemon for that specific architecture.

Conclusion

In case you haven’t noticed, this idea hasn’t exactly gotten a lot of time to mature. Yet. But i find it a quite interesting concept and hope you do, too.

If this post got you excited, you are welcome to contribute to GayBSD! The source is available at https://git.bsd.gay/os/kern.git. Just contact me through one of the means in the footer below if you would like to know more.

tags: tech – x86 – arm – kernel – bsd