Skip to content

Commit

Permalink
Implement syscall handlers (b), increase PC on syscall (c)
Browse files Browse the repository at this point in the history
Add `handle_not_implemented_SC()` to handle all syscalls
that have not yet implemented. That method will write debug
log and increase the program counter.

Now user test programs don't need to call Halt() at the end
of the program.
  • Loading branch information
leduythuccs committed Oct 7, 2021
1 parent 5f450e9 commit 405be5b
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 53 deletions.
1 change: 1 addition & 0 deletions build_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ cd code/test
make

../build.linux/nachos -x halt
../build.linux/nachos -x test_syscall
13 changes: 10 additions & 3 deletions code/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@
#
# Nachos assumes that the location of the program startup routine (the
# location the kernel jumps to when the program initially starts up)
# is at location 0. This means: start.o must be the first .o passed
# is at location 0. This means: start.o must be the first .o passed
# to ld, in order for the routine "Start" to be loaded at location 0
#
# When you make the test programs, you will see messages like these:
# numsections 3
# numsections 3
# Loading 3 sections:
# ".text", filepos 0xd0, mempos 0x0, size 0x440
# ".data", filepos 0x510, mempos 0x440, size 0x0
Expand Down Expand Up @@ -112,7 +112,7 @@ ifeq ($(hosttype),unknown)
PROGRAMS = unknownhost
else
# change this if you create a new test program!
PROGRAMS = add halt shell matmult sort segments
PROGRAMS = add halt shell matmult sort segments test_syscall
endif

all: $(PROGRAMS)
Expand Down Expand Up @@ -157,6 +157,13 @@ matmult: matmult.o start.o
$(LD) $(LDFLAGS) start.o matmult.o -o matmult.coff
$(COFF2NOFF) matmult.coff matmult

test_syscall.o: test_syscall.c
$(CC) $(CFLAGS) -c test_syscall.c
test_syscall: test_syscall.o start.o
$(LD) $(LDFLAGS) start.o test_syscall.o -o test_syscall.coff
$(COFF2NOFF) test_syscall.coff test_syscall


clean:
$(RM) -f *.o *.ii
$(RM) -f *.coff
Expand Down
13 changes: 6 additions & 7 deletions code/test/start.S
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Start.s
/* Start.s
* Assembly language assist for user programs running on top of Nachos.
*
* Since we don't want to pull in the entire C library, we define
Expand All @@ -9,12 +9,12 @@
#define IN_ASM
#include "syscall.h"

.text
.text
.align 2

/* -------------------------------------------------------------
* __start
* Initialize running a C program, by calling "main".
* Initialize running a C program, by calling "main".
*
* NOTE: This has to be first, so that it gets loaded at location 0.
* The Nachos kernel always starts a program by jumping to location 0.
Expand All @@ -25,7 +25,7 @@
.ent __start
__start:
jal main
move $4,$0
move $4,$0
jal Exit /* if we return from main, exit(0) */
.end __start

Expand All @@ -34,7 +34,7 @@ __start:
* Assembly language assist to make system calls to the Nachos kernel.
* 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
* 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
Expand Down Expand Up @@ -177,11 +177,10 @@ ThreadJoin:
syscall
j $31
.end ThreadJoin

/* dummy function to keep gcc happy */
.globl __main
.ent __main
__main:
j $31
.end __main

12 changes: 12 additions & 0 deletions code/test/test_syscall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* test_syscall.c
* Simple program to test whether the systemcall interface works.
*/

#include "syscall.h"

int main() {
int result = Add(1, 2);
/* Don't need to Halt() anymore because the PC will increase automatically
*/
result = Add(2, 3);
}
124 changes: 81 additions & 43 deletions code/userprog/exception.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,67 @@
// The result of the system call, if any, must be put back into r2.
//
// If you are handling a system call, don't forget to increment the pc
// before returning. (Or else you'll loop making the same system call forever!)
// before returning (by calling move_program_counter()). (Or else you'll loop
// making the same system call forever!)
//
// "which" is the kind of exception. The list of possible exceptions
// is in machine.h.
//----------------------------------------------------------------------

/**
* Modify program counter
* This code is adapted from `../machine/mipssim.cc`, line 667
**/
void move_program_counter() {
/* set previous programm counter (debugging only)
* similar to: registers[PrevPCReg] = registers[PCReg];*/
kernel->machine->WriteRegister(PrevPCReg,
kernel->machine->ReadRegister(PCReg));

/* set programm counter to next instruction
* similar to: registers[PCReg] = registers[NextPCReg]*/
kernel->machine->WriteRegister(PCReg,
kernel->machine->ReadRegister(NextPCReg));

/* set next programm counter for brach execution
* similar to: registers[NextPCReg] = pcAfter;*/
kernel->machine->WriteRegister(
NextPCReg, kernel->machine->ReadRegister(NextPCReg) + 4);
}

/**
* Handle not implemented syscall
* This method will write the syscall to debug log and increase
* the program counter.
*/
void handle_not_implemented_SC(int type) {
DEBUG(dbgSys, "Not yet implemented syscall " << type << "\n");
return move_program_counter();
}

void handle_SC_Halt() {
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
SysHalt();
ASSERTNOTREACHED();
}

void handle_SC_Add() {
DEBUG(dbgSys, "Add " << kernel->machine->ReadRegister(4) << " + "
<< kernel->machine->ReadRegister(5) << "\n");

/* Process SysAdd Systemcall*/
int result;
result = SysAdd(
/* int op1 */ (int)kernel->machine->ReadRegister(4),
/* int op2 */ (int)kernel->machine->ReadRegister(5));

DEBUG(dbgSys, "Add returning with " << result << "\n");
/* Prepare Result */
kernel->machine->WriteRegister(2, (int)result);

return move_program_counter();
}

void ExceptionHandler(ExceptionType which) {
int type = kernel->machine->ReadRegister(2);

Expand All @@ -57,50 +112,33 @@ void ExceptionHandler(ExceptionType which) {
case SyscallException:
switch (type) {
case SC_Halt:
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");

SysHalt();

ASSERTNOTREACHED();
break;
return handle_SC_Halt();

case SC_Add:
DEBUG(dbgSys,
"Add " << kernel->machine->ReadRegister(4) << " + "
<< kernel->machine->ReadRegister(5) << "\n");

/* Process SysAdd Systemcall*/
int result;
result = SysAdd(
/* int op1 */ (int)kernel->machine->ReadRegister(4),
/* int op2 */ (int)kernel->machine->ReadRegister(5));

DEBUG(dbgSys, "Add returning with " << result << "\n");
/* Prepare Result */
kernel->machine->WriteRegister(2, (int)result);

/* Modify return point */
{
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(
PrevPCReg, kernel->machine->ReadRegister(PCReg));

/* set programm counter to next instruction (all
* Instructions are 4 byte wide)*/
kernel->machine->WriteRegister(
PCReg, kernel->machine->ReadRegister(PCReg) + 4);

/* set next programm counter for brach execution */
kernel->machine->WriteRegister(
NextPCReg,
kernel->machine->ReadRegister(PCReg) + 4);
}

return;

ASSERTNOTREACHED();

break;
return handle_SC_Add();
/**
* Handle all not implemented syscalls
* If you want to write a new handler for syscall:
* - Remove it from this list below
* - Write handle_SC_name()
* - Add new case for SC_name
*/
case SC_Exit:
case SC_Exec:
case SC_Join:
case SC_Create:
case SC_Remove:
case SC_Open:
case SC_Read:
case SC_Write:
case SC_Seek:
case SC_Close:
case SC_ThreadFork:
case SC_ThreadYield:
case SC_ExecV:
case SC_ThreadExit:
case SC_ThreadJoin:
return handle_not_implemented_SC(type);

default:
cerr << "Unexpected system call " << type << "\n";
Expand Down

0 comments on commit 405be5b

Please sign in to comment.