Project Goal Set V - Creating Space for Users
This week you will be creating a space for your user processes. For now, there will be only one user process. However, this process will interact with your kernel via the software interrupt 0x80. This will be a big turning point, with lots of fun adventures waiting in the future!
The goals for this part of the project are as follows:
- Implement page table allocation in your kernel.
- Implement a process table.
- Implement the read system call.
- Implement the write system call.
- Implement the exit system call.
- Link a user space executable into your kernel.
- Switch contexts between your kernel and your user process.
This sounds like a lot, but the good news is that a great deal of this will be following xv6's example. Careful study of the xv6 code, and a fair bit of luck, should make this part of the project a breeze!
Page Table Allocation
We are essentially going to steal our page table allocation from xv6. This is effectively all contained within the file kalloc.c. In fact, go ahead and steal that now. I made my own kalloc.h to store prototypes for all of the functions in this file. If you are going with the monolithic header approach (as in xv6's defs.h file), then just add them here. You don't need the structs outside of kalloc.c, so there is no need to copy those definitions.
One thing you will need to do is remove any mention of locking. Later on, we will implement locks, but not yet. You can comment out those sections for now.
Now you need to add this into your kernel's main function. Take a look at how xv6 does this, and mimic what it does. If you succeed, you should have your kernel running with 4k pages and a full fledged method of allocating pages!
(Of course, if you fail it will probably go back to not running at all. Feel relieved if you boot into kernmon!)
Implementing a Process Table
Take a look at xv6's handling of processes. Most notably, take a look at the proc.h and proc.c files. You can likely copy a lot of this, but this will require a bit more care than the page table allocators. Remember, you will only have one CPU, so per-cpu handling will not be needed. Also, we are not yet ready for process scheduling. Our scheduler will be a fair bit different from the one contained here. For now, what we are really interested in is:
Implementing System Calls
Read and write are pretty simple to create. For now, we'll let the file descriptors from the process directly access the file descriptors in the kernel. This will, of course, change. The real trick will be working out how you get information from your process into your system calls. Take a look at how xv6 does this. Is this the same as the Linux system call convention? Which do you want to use? You can take your pick!
Also, note how xv6 determines which system call to invoke. You will want to mimic that in your own system.
Finally, we will be faking the "wait" system call. Really, after exit is completed, we will go ahead and deallocate the process and then drop into kernmon. So if all goes according to plan, when you run your OS, the following will happen:
- Your user process will run.
- After your user process terminates, you will be dropped into kernmon.
(Of course, that's not happening until we get the user process going.)
Linking a User Space executable
We need to create a user application for the next part. I recommend you take the assembly program from your "lesser programs" and put it here. It should use only read write and exit system calls. However, you may need to adapt this to match the calling convention you have selected for your kernel's system calls!
Once you have this adapted, take a look at how xv6 links its init program into the kernel. (This will be done via that -b binary section of the linker call.) You will need to make use of your adaptation of the userinit function to get this going.
You will now need to switch contexts to your process. Study how xv6 does this. Did you make sure your user process has a page table? If not, take care of that now. Once you get it all set up, manually switch to your init process.
If all goes well, your OS will do something like this:
What is your name? Bob Hello, Bob, how are you? ** KERNMON STARTING ** >