The EABI syscall interface for Linux on ARM processors uses the SWI (SoftWare Interrupt instruction) number zero as its way into supervisor mode and the kernel. Unfortunately, that instruction has been in use for more than twenty years by the operating system used by the originators of the ARM, Acorn's RISC OS.
Now, Acorn weren't against looking ahead (I like to think of their software interfaces as forward-compatible, with support for likely developments looking forward many years, or even decades). One example of this was when they defined the new ARM SWI instruction, they included these bits:
Bits 20 - 23
These are used to identify the particular operating system that the SWI expects to be in the machine. All SWIs used under RISC OS have these bits set to zero. Under RISC iX, bit 23 is set to 1 and all other bits are set to zero.
Now, Linux used to stick to this definition, using the number 9 for the OABI, but when they moved to EABI, the operating system bits were quietly dropped and SWI 0 (RISC OS's OS_WriteC - "Writes a character to all of the active output streams") was used.
Now, this has become a bit of a headache for me, because I'm trying to get Linux to run RISC OS programs using the ROLF compatibility library, which provides native Linux implementations for many RISC OS system calls. What I want is for the kernel to signal the application when a SWI is encountered in RISC OS code so that the ROLF routines can be executed in user space and the application (or module) can continue on its merry way.
There are a few ways to approach this:
- Check the personality of the process for each SWI executed
- Redefine the EABI to insist on SWI 0x009fxxxx as the kernel entry SWI (and treat all other SWIs as an illegal instruction or use a special signal code)
- Make OABI the standard interface
- Use a similar mechanism to the x86 emulator to generate Linux code from the RISC OS code, which won't execute any RISC OS SWIs
- Make the personality implementation more object-oriented and allow each process to determine how it should handle SWIs, Unknown instructions, data aborts, etc.
Option 1 will work, but will slow down all system calls even more than just moving back to OABI.
Option 2 will make some existing programs incompatible with the kernel, although not if they just use libc to make system calls, or are recompiled against a new unistd.h.
Option 3 would be a step backward for Linux (and support will probably be phased out over time). Also, it suffers from the same incompatibilities as option 2.
Option 4 will be fully compatible and would allow running of old 26-bit applications but would be much more work and probably quite a lot slower.
Option 5 would be cool, but probably too high impact.
Jan Rinze likes 1, I prefer 2, but I'll probably go with whichever produces a working solution first!