new linux standard
Posted: Sun Jul 06, 2025 12:23 am
So based on another post, I want to be able to write Linux apps such that they run under both PDOS-generic and real Linux.
Linux is set in stone, but PDOS-generic isn't. And also I have no problem invalidating all existing Linux apps, including my own. I never agreed on a standard, and if some professor or the POSIX committee or Thomo/Lillee/Richie Rich didn't allow for this 50 years ago or whatever - that's not my fault.
So I'll start with x64, since it is the most complicated. And this is just tentative first thoughts.
PDOS-generic may be running in userspace on Windows x64 with no access to interrupts, so I can't intercept the "syscall" instruction (whatever that is). I instead need all Properly Written (TM) Linux apps to gracefully accept a linux_syscall() callback override which would be part of the PDOS-generic OS structure.
But the app needs to know whether it is running under PDOS-generic or real Linux. And it can't e.g. look at an environment variable by doing a syscall, because syscall may not be allowed - that's the whole point.
So PDOS-generic can call the Linux app (entry point funcptr) with:
funcptr( (void *)(ptrdiff_t)-1, (void *)(ptrdiff_t)-2, (void *)(ptrdiff_t)-3, &OS_BLOCK);
The startup assembler code for the Linux app will push the following registers onto the stack:
rcx, rdx, r8, r9, (these first 4 are MSABI) rdi, rsi
rdi, rsi, rdx, rcx, r8, r9 is Linux calling convention for parameters.
I may wish to use either of those calling conventions depending on what compiler I have available.
I then pass a pointer to the stack to the C startup code, so it can figure out the environment in C instead of assembler.
On real Linux x64, I don't think any of those registers are guaranteed to be anything, so that could be a problem.
But otherwise, I can look for the -1, -2, -3 sequence in either rcx/rdx/r8 or rdi/rsi/rdx so I know that the caller is PDOS-generic and I know where to find the OS pointer and I can do my callbacks instead of real syscalls. If that sequence is not detected, I know it is real Linux and carry on as usual doing syscall, and also I know the location of argc/argv if I am forced to get that from the stack instead of /proc/.../cmdline (I use this so that PDOS/386 has a chance to provide parameters to a Linux app without creating a stupid stack - PDOS/386 handles a real INT 80H).
For 80386, PDOS-generic is still going to do the same call, but now everything is on the stack instead of in registers.
I again have assembler startup code to push the current stack pointer onto the stack as the parameter to the C startup code.
If this is PDOS-generic, the stack will have a return address followed by -1, -2, -3, OS. The OS will have an int80() callback function to override the real INT 80H. ie all Properly Written (TM) Linux apps are expected to call the callback function if the OS (no matter who - maybe real Linux will be updated one day for whatever reason someone has to not want a real interrupt done) tells it (via this mechanism) to do a callback, not a real interrupt.
If this is Linux I will have argc immediately, and I will not be able to differentiate that from a return address.
Real Linux will then have argc, and the value of -2 will not be (reasonably) valid. Possibly I could have an additional -1 parameter to be sure, so perhaps a sequence of -1, -1, -2, OS. Another possibility is to have three -1 to make sure argv[0] is an invalid pointer. Either -1, -1, -1, OS or -1, -1, -1, -2, OS. That last one will cause x64 to spill from registers into the stack, but that can be coped with, and may even be a good thing. Perhaps even having 8 or more parameters would be good for x64 detection purposes.
Whatever the number and value of parameters are, I expect it to be consistent regardless of ARM32/64 x86/x64, so that the PDOS-generic OS can be portable for the PDOS-generic app point of view. If it is acting as a mini Linux clone or mini Atari clone, I can have extra/different callback functions made available, but the PDOS-generic apps remain the same (ie with a view to setting the PDOS-generic API in stone too - PDOS-generic apps need to know to ignore the first x parameters and just get the parameter with the OS structure which contains everything they need).
Just initial thoughts.
Linux is set in stone, but PDOS-generic isn't. And also I have no problem invalidating all existing Linux apps, including my own. I never agreed on a standard, and if some professor or the POSIX committee or Thomo/Lillee/Richie Rich didn't allow for this 50 years ago or whatever - that's not my fault.
So I'll start with x64, since it is the most complicated. And this is just tentative first thoughts.
PDOS-generic may be running in userspace on Windows x64 with no access to interrupts, so I can't intercept the "syscall" instruction (whatever that is). I instead need all Properly Written (TM) Linux apps to gracefully accept a linux_syscall() callback override which would be part of the PDOS-generic OS structure.
But the app needs to know whether it is running under PDOS-generic or real Linux. And it can't e.g. look at an environment variable by doing a syscall, because syscall may not be allowed - that's the whole point.
So PDOS-generic can call the Linux app (entry point funcptr) with:
funcptr( (void *)(ptrdiff_t)-1, (void *)(ptrdiff_t)-2, (void *)(ptrdiff_t)-3, &OS_BLOCK);
The startup assembler code for the Linux app will push the following registers onto the stack:
rcx, rdx, r8, r9, (these first 4 are MSABI) rdi, rsi
rdi, rsi, rdx, rcx, r8, r9 is Linux calling convention for parameters.
I may wish to use either of those calling conventions depending on what compiler I have available.
I then pass a pointer to the stack to the C startup code, so it can figure out the environment in C instead of assembler.
On real Linux x64, I don't think any of those registers are guaranteed to be anything, so that could be a problem.
But otherwise, I can look for the -1, -2, -3 sequence in either rcx/rdx/r8 or rdi/rsi/rdx so I know that the caller is PDOS-generic and I know where to find the OS pointer and I can do my callbacks instead of real syscalls. If that sequence is not detected, I know it is real Linux and carry on as usual doing syscall, and also I know the location of argc/argv if I am forced to get that from the stack instead of /proc/.../cmdline (I use this so that PDOS/386 has a chance to provide parameters to a Linux app without creating a stupid stack - PDOS/386 handles a real INT 80H).
For 80386, PDOS-generic is still going to do the same call, but now everything is on the stack instead of in registers.
I again have assembler startup code to push the current stack pointer onto the stack as the parameter to the C startup code.
If this is PDOS-generic, the stack will have a return address followed by -1, -2, -3, OS. The OS will have an int80() callback function to override the real INT 80H. ie all Properly Written (TM) Linux apps are expected to call the callback function if the OS (no matter who - maybe real Linux will be updated one day for whatever reason someone has to not want a real interrupt done) tells it (via this mechanism) to do a callback, not a real interrupt.
If this is Linux I will have argc immediately, and I will not be able to differentiate that from a return address.
Real Linux will then have argc, and the value of -2 will not be (reasonably) valid. Possibly I could have an additional -1 parameter to be sure, so perhaps a sequence of -1, -1, -2, OS. Another possibility is to have three -1 to make sure argv[0] is an invalid pointer. Either -1, -1, -1, OS or -1, -1, -1, -2, OS. That last one will cause x64 to spill from registers into the stack, but that can be coped with, and may even be a good thing. Perhaps even having 8 or more parameters would be good for x64 detection purposes.
Whatever the number and value of parameters are, I expect it to be consistent regardless of ARM32/64 x86/x64, so that the PDOS-generic OS can be portable for the PDOS-generic app point of view. If it is acting as a mini Linux clone or mini Atari clone, I can have extra/different callback functions made available, but the PDOS-generic apps remain the same (ie with a view to setting the PDOS-generic API in stone too - PDOS-generic apps need to know to ignore the first x parameters and just get the parameter with the OS structure which contains everything they need).
Just initial thoughts.