I know what I'm gonna do this winter :P
I recommend the OSDev wiki for a deeper dive but ultimately, implementing processes involves a lot of different moving pieces that need to work.
The most basic process manager would be cooperative, otherwise you'd have to write drivers for some external driver to regularly drive an interrupt.
Cooperative means the program will either print A or B and then call an interrupt into the kernel. The kernel would save the registers and instruction pointer, restore the one of the other program (which prints the opposite of what the first printed; A or B) and do an interrupt return.
This doesn't scale beyond a few processes that you have written yourself very carefully.
Any more competent process management will need to rely on regular timer interrupts, will have to keep track of processes and how much CPU time they got, have a thread to run if nothing else can run, manage processes when they die and has to be able to switch in and out of ring3 for running the actual process. On top of that it has to be performant and efficient, you have only a few hundred opcodes before the latency of your process management becomes too large.
I've been trying to figure out how a powerpc machine is being booted so that I can insert my own 'hello world' OS. Sure there is a BIOS equivalent somewhere in there, but how to figure out how and when to talk to it?
Booting x86 might seem like nothing, but booting some old SPARC for instance seems like black magic to me.
Which sort of PPC machine is it? Have you already managed to get e.g. NetBSD running on it?
Finding the kernel is not as easy as it used to be. You need to read the partition table on the disk. You need to be able to understand the filesystem that the kernel is stored on. This adds a fair bit of complexity.
http://pages.cs.wisc.edu/~remzi/OSTEP/
It's fantastically well-written, yet detailed without being overwhelming.
Disclaimer: I'm definitely not an expert, I'm reading the book to learn.
The correct approach is to use mmap with the MAP_ANON flag (Which interestingly isn't doesn't seem to be fully documented in the Linux documentation...)
Does anyone know these days if the 16-bit boot environment is still "bare metal", or is it inside an UEFI or ACPI hypervisor of some sort?
Real BIOS that boots from 16bit is quite a rarity these days.
Not sure how UEFI's "Compatibility Service Module" works exactly but if it acts like the original BIOS did, it's just a chunk of code that can be called, either by a program or be set as the destination for interrupts.
But there is no "VM exit" mechanism like there is in hypervisors. One thing a hypervisor does is intercept IO address accesses and does them on behalf of the client code (without the code knowing), don't think the CSM is doing this.
My understanding was that the CPU still starts in 16 bit real mode (with an evil hack to sign-extend IP) but that by the time UEFI hands off to code on a hard drive it is in long mode.
Looks very accessible :)
EFI will kill your program if it runs too long unless it disables a lot of the drives by exiting the boot environment.
Additionally, a lot of the EFI structures aren't intuitive or straightforward since they cover a lot of functionality, you'd still write a lot of code, probably more than the non-EFI variant.