MMUmbling along
Twas a bit of a slow weekend, still feeling a bit funny from the cold last week and started hung over from a few beers in town on Friday night. Saturday we went to McLaren Vale with a friend and I ended up buying way too much wine as usual. It always seems to taste better the further you go ... And I was pretty wasted by the time we got home and cooked up a BBQ.
When I had time to code I was just re-arranging stuff again. I hadn't really 'interface-ised' the code properly so I needed to finish that off. Plus I decided to move all of the supervisor level code to a different directory and make it run off it's own management structure rather than 'execbase', and to settle on a consistent naming convention for structure members. So lots of killing and yanking lines of code and renaming stuff and mucking about with makefiles.
Last night I nutted out some of the main mechanics of process creation, although I still have a little way to go. I've again (about the 3rd time) written a set of utilities for MMU management but I've decided to go with the page tables allocated directly in kernel space, and I keep track of the virtual and real address of these using separate pointers. For memory pages I don't need to know physical address after i've setup the PTE, so I just track those by index in an array.
I was going to map the whole page table to the last 4MB of memory using the self-referential PDE 'hack', but I decided against it. For one, I need to be able to easily manipulate more than 1 page table if I want to re-map messages between processes. And the overhead of keeping track of the page table virtual addresses is small.
For keeping track of physical pages I just have an array of ints, one for each available page of memory (to make it easy, it will be every page from address 0 to the highest physical address present). For available pages I have a linked list stored inside those ints. And once they've been used they're unlinked and the content becomes a reference count. And I have up to 12 bits I can use to indicate other things if required. I'm thinking the reference counting might be handy for keeping track of shared memory - on the other hand, I may just use globally shared sections to load shared library code into, so it might not be necessary at all. For now, it's also the simplest implementation.
I'm still thinking about the process creation primitives too. Maybe a CreateProc that takes either a function address in the current process, or a loaded ELF image. In the former case, i'll just copy the process and call the function, similar to fork() although there may be more specific argument passing system. With the other case it will 'steal' the pages from the calling process and map them to the new process and kick it off. Might need to allocate the memory in a special range so it can be 'stolen' easily , or do some other sort of magic so it works, or even use a process loader server; in either case the loader would manage the details.
The first is required so I can start some initial in-`rom' processes, and also to implement fork() for some possible future posix layer. The second allows a process to load another one relatively efficiently, and do most of the work in user-space on the callee context.
I will have a separate task creation primitive which basically works like pthread_create does.
And I was thinking about alternative platforms again. I'm still dreading the point where I have to deal with even more fucked up components of the PC architecture like video and sound. I should really bite the bullet and get some sort of ARM platform - they're just not that easy to get around here yet. Maybe I should delve into the PS3 as well.