For this project, you will use a new and improved version of the simulated CPU. The update is a simple one, meant to address a design flaw in the previous CPU.
The change is an introduction of two memory fault registers (MFRs). Upon any faulty memory access, the MMU will place all needed information into these registers instead of into the general registers. Thus, we avoid the problem of interrupts that clobber values in user-addressable registers. Specifically:
On an address allignment interrupt, the offending address will be placed in MFR 0.
On a memory access interrupt, the offending address will be placed in MFR 0. Furthermore, if a load or instruction fetch caused the interrupt, then a 0 is placed in MFR 1; for store operation, a 1 is placed in MFR 1.
You can access the MFRs from the kernel using two new functions in the CPU's interface. Specifically:
void setMFR (unsigned int registerNumber, vMachineWord_t newValue);
Set the MFR register specified by registerNumber to hold the value specified by newValue.
vMachineWord_t getMFR (unsigned int registerNumber);
Get the value in the MFR register specified by registerNumber and return it.
We want the kernel to provide FIFO buffers so that processes can communicate. Specifically, we will allow processes to send values to one another through a pair of system calls:
SEND: A process can select another process (by its PID), and send a given word of data to it. Specifically, register %s1 must contain the PID of the receipient, and register %s2 must contain the word of data.
The FIFO buffer should be a fixed (and small) size -- no more than 4 KB. If the buffer is full, then the kernel must block the calling process until the buffer is not full. Only once the value is placed in the buffer can the process be allowed to resume.
RECV: A process can select to receive data from another process. Note that the process that calls this system call does not need to specify a PID -- it should simply receive the next message sent to it by any process. Upon returning from this system call, the process should see the PID of the sender in register %s1, and the data of the message in register %s2.
If the FIFO buffer of messages to this process is empty, then the process must block until it is not empty.
You can obtain the code for the new virtual machine by unpacking the tarball available in my public directory:
tar -xjvpf ~sfkaplan/public/cs39/VP-v1.3.tar.bz2
Again, the tarball does not include a kernel -- it's just the machine itself. You will have to adapt your kernel from the last assignment for this one.
You must do the following:
Ensure that virtual memory works: Remedy the problems remaining from project 2. Make sure that mapping and swapping are performed correctly.
Implement the SEND and RECV system calls: A process should request these system calls by placing 0x1111000a or 0x1111000b, respectively, in register %s0.
Write a test program: Write a program that forks once. After forking, the parent should send messages to the child. Specifically, the parent should sent the values from 1 to 100. The child, upon receiving these values, should sum them, and that sum should be its result code. Be sure to test this program with a large interrupt period to see that the blocking is performed correctly on a full/empty FIFO buffer.
When your group has completed its project, submit all files as project-3 using the cs39-submit program. Note that this program can take directory names as arguments.