Nachos Programming Tips (Phase 2) ================================= o Read the project specs carefully! o How is a user program run? This involves the cooporations between Processor, UserKernel, UserProcess, and UThread classes. Nachos has one Processor, one Kernel (UserKernel in this project) and one or more UserProcess'es and UThreads. UThread extends KThread and is used to run the user process. Each UserProcess has a UThread. Note that UserProcess is part of the OS kernel (not the Kernel class) and it contains information and methods for running a user program. A user program is written in C and compiled into a COFF executable. To run a user program, UserProcess allocates memory, loads the executable, initializes the Processor's registers (especially PC and SP), installs the address translation, creates a new UThread for it and forks it off. UThread invokes Processor.run() in its run function. The Processor simulates a real MIPS CPU, including all its registers, the page table, TLB, etc., and interpretes and executes the MIPS instructions contained in the executable. o Bootstrap When Nachos starts up, UserKernel creates a UserProcess and runs a shell program specified in nachos.conf. The shell provides prompt to users via SerialConsole (std I/O). When a user types a command, shell calls the exec system call, which should create a child process to run the user program. If the command is given without `&`, it will be run in the foreground. The shell then waits for this process to finish using the join system call. o How are exceptions generated and handled? When it sees something unusual, the Processor will set appropriate registers and throw a MipsException. In a real OS this will cause the kernel handler to be invoked. In Nachos, the Processor invokes UserKernel via an exceptionHandler that the latter installed in the Processor when it initializes. UserKernel will call find the UserProcess that causes this exception and call its handler. o System calls syscall.h contains the declarations of all system calls as well as the system call codes which is passed to the kernel to tell it which system call to do. System call stubs are in start.s. There is one stub per system call, that places the code for the system call into register r2, and leaves the arguments to the system call alone (in other words, arg1 is in r4, arg2 is in r5, arg3 is in r6, arg4 is in r7). The return value is in r2. This follows the standard C calling convention on the MIPS. When a user program makes a system call such as open, the MIPS cross compiler will generate system call instruction with appropriate registers set. When the Processor executes such an instruction, it will throw a MipsException with cause set to exceptionSyscall. Eventually UserKernel will be invoked to handle it and this is where you implement the system call. o Arguments passing In handling syscalls, all arguments passed to the syscall handlers in UserProcess are integers. If the arguments specified in syscall.h are integers, then the values passed to the handlers will be the arguments themselves. If the arguments specified in syscall.h are addresses (e.g. char*, or int[]), then the corresponding integers passed to your handlers are *virtual* addresses of the corresponding buffers. Note that all syscall handlers in UserProcess return int, which is passed back to user program via a register in Processor. Some syscalls (such as halt) that are specified to be void will just ignore this returned value. Also note that in syscall.h, exit is specified as void exit(int status). The agument is the exit status that needs to be passed to the process's parent when the latter calls join. Since exit is void, you need to come up with a way to pass this exit status to the parent when it returns from join. And remember a process can have multiple children. o Nachos physical memory Physical memory in Nachos is just an array of bytes (in Processor) and you can access it by byte[] memory = Machine.processor().getMemory(); See readVirtualMemory in UserProcess. Note that Nachos is only a simulated OS (and hardware) so the "OS" does not occupy anywhere in that array. It runs in the memory provided by the real OS and the JVM. You can think of the "physical memory" in Nachos as the memory dedicated to running user programs.