What does it take to run 64-bit userland software on a 32-bit kernel

32bit64bitkernelmultiarch

On Linux and Windows, I'm used to the situation that I require a 64-bit kernel to have a system with multiarch/WoW where I can run 32-bit and 64-bit software side-by-side.

And then, years ago it blew my mind when someone showed me that MacOS 10.6 Snow Leopard could run 64-bit applications with the kernel in 32-bit mode. This may be largely forgotten now because it was a one-time technology transition. With the hardware ahead of the curve in the mobile space, as far as I know this was never needed in the move to 64-bit for iOS and Android.

My question: What would it take to get the same capability in a 32-bit Linux kernel (i386 or armhf)?

I understand that this probably isn't trivial. If it was, Microsoft could have put the feature into Windows XP 32-bit. What are the general requirements though? Has there ever been a proposed patch or proof-of-concept?

In the embedded world I think this would be especially helpful, as 64-bit support can lag behind for a long time in device drivers.

Best Answer

Running 64-bit applications requires some support from the kernel: the kernel needs to at least set up page tables, interrupt tables etc. as necessary to support running 64-bit code on the CPU, and it needs to save the full 64-bit context when switching between applications (and from applications to the kernel and back). Thus a purely 32-bit kernel can’t support 64-bit userspace.

However a kernel can run 32-bit code in kernel space, while supporting 64-bit code in user space. That involves handling similar to the support required to run 32-bit applications with a 64-bit kernel: basically, the kernel has to support the 64-bit interfaces the applications expect. For example, it has to provide some mechanism for 64-bit code to call into the kernel, and preserve the meaning of the parameters (in both directions).

The question then is whether it’s worth it. On the Mac, and some other systems, a case can be made since supporting 32-bit kernel code means drivers don’t all have to make the switch simultaneously. On Linux the development model is different: anything in the kernel is migrated as necessary when large changes are made, and anything outside the kernel isn’t really supported by the kernel developers. Supporting 32-bit userland with a 64-bit kernel is certainly useful and worth the effort (at least, it was when x86-64 support was added), I’m not sure there’s a case to be made for 64-bit on 32-bit...