The routine ExceptionHandler() is the entry point into the kernel for
a trap caused by a user program. This means that the code for all the system
calls you implement should go in that routine.
In order to understand how user programs execute in Nachos, it is crucial to understand the underlying machine architecture that Nachos provides and how user programs access it. A detailed explanation is provided here.
Nachos can run arbitrary user programs as long as they make only those system calls that are understood by Nachos. One difference between the programs executed on UNIX and those executed by Nachos is that UNIX executables are in the coff format whereas the Nachos executables are in the Noff format. Thus, in order to run user programs on Nachos, we first compile them using gcc and then convert them from the coff format to the Noff format. This is done using the coff2noff program which is present in the bin directory.
In order to see how this is done, here are a few statements from the Makefile in the test directory:
halt.o: halt.c $(CC) $(CFLAGS) -c halt.c halt: halt.o start.o $(LD) $(LDFLAGS) start.o halt.o -o halt.coff ../bin/coff2noff halt.coff halt
The above compiles a user program called halt.c . The resulting object file is then linked with another file called start.o to produce a binary called halt.coff . Remember that this will be in the coff format that UNIX uses. Since we want to run halt.c in Nachos, we then invoke the program coff2noff to produce a binary file called halt in the Noff format.
The data structures for the Noff format are
defined in noff.h in the bin directory.
Noff format files consist of four parts.
For each of the last three sections of the file, the Noff header contains information in the following variables:
1 all: halt shell matmult sort 2 start.o: start.s ../userprog/syscall.h 3 $(CPP) $(CPPFLAGS) start.s > strt.s 4 $(AS) $(ASFLAGS) -o start.o strt.s 5 rm strt.s 6 shell.o: shell.c 7 $(CC) $(CFLAGS) -c shell.c 8 shell: shell.o start.o 9 $(LD) $(LDFLAGS) start.o shell.o -o shell.coff 10 ../bin/coff2noff shell.coff shell
The above statements from the Makefile show how to compile shell.c for Nachos. The file start.s contains assembly language code that needs to be executed before the code of each user program's main routine. Thus, for proper execution of shell.c , we need to make sure that the code in start.s resides before that of its main program. (In addition to containing this initialization code, start.s also contains stub modules for invoking system calls .)
Lines 2-5 generate object code for start.s . Lines 6 and 7 generate object code for shell.c . Lines 8 and 9 produce an executable binary. Note that listing start.o before shell.o ensures that the code for start.s resides before that of the main program. Finally, line 10 translates the binary into the Noff format. shell, is thus, an executable ready to execute under Nachos.
To run the test programs in Nachos, use the -x option. For example, to run the test program shell, type nachos -x ../test/shell while in the userprog directory.
A list of options available for running
Nachos is in main.cc.
A list of exceptions that can be raised
within Nachos is in machine.h. The list of
system calls in Nachos is in syscall.h.
FIGURE trap.gif WILL BE HERE.
The actual instructions for making system calls are found in start.s . At runtime, a code indicating the type of system call is placed in register 2 and the syscall instruction is executed. Additional arguments to the system call are placed in registers 4-7, following standard C procedure call linkage conventions. Any return values are expected to be in register 2. The syscall instruction is a trap instruction, meaning the next instruction to be executed is the first instruction is the trap handler. In Nachos, the trap handler is the routine ExceptionHandler() . The following code from start.s shows the how the Halt and Exit system calls are invoked:
1 #include "syscall.h" 2 .text 3 .align 2 4 5 .globl __start 6 .ent __start 7 __start: 8 jal main /* Call the procedure "main" */ 9 move $4,$0 /* R4 gets 0 */ 10 jal Exit /* If we return from main, exit(0) */ 11 .end __start 12 13 .globl Halt 14 .ent Halt 15 Halt: 16 addiu $2,$0,SC_Halt 17 syscall 18 j $31 19 .end Halt 20 21 .globl Exit 22 .ent Exit 23 Exit: 24 addiu $2,$0,SC_Exit 25 syscall 26 j $31 27 .end Exit 28 /* dummy function to keep gcc happy */ 29 .globl __main 30 .ent __main 31 __main: 32 j $31 33 .end __main
Line 8 is the first actual instruction, lines 1-7 being assembler directives. It simply calls the procedure main , in the user program. Lines 9 and 10 are executed whenever the call to main returns, in which case we tell Nachos we are done via the exit system call. Lines 15-18 invoke the Halt system call. Similarly, lines 23-26 invoke the Exit system call. Note the call to the syscall instruction on lines 17 and 25. Also note that the Exit system call normally will not return but a return is provided here anyway.
The routine RaiseException() is
called within the simulator - mipssim.cc and
translate.cc .
Source code in
code/userprog
Lab
Quiz
Last modified on Monday, 29-Mar-99 00:29:55 EST