197 lines
6.8 KiB
C++
197 lines
6.8 KiB
C++
// exception.cc
|
|
// Entry point into the Nachos kernel from user programs.
|
|
// There are two kinds of things that can cause control to
|
|
// transfer back to here from user code:
|
|
//
|
|
// syscall -- The user code explicitly requests to call a procedure
|
|
// in the Nachos kernel. Right now, the only function we support is
|
|
// "Halt".
|
|
//
|
|
// exceptions -- The user code does something that the CPU can't handle.
|
|
// For instance, accessing memory that doesn't exist, arithmetic errors,
|
|
// etc.
|
|
//
|
|
// Interrupts (which can also cause control to transfer from user
|
|
// code into the Nachos kernel) are handled elsewhere.
|
|
//
|
|
// For now, this only handles the Halt() system call.
|
|
// Everything else core dumps.
|
|
//
|
|
// Copyright (c) 1992-1996 The Regents of the University of California.
|
|
// All rights reserved. See copyright.h for copyright notice and limitation
|
|
// of liability and disclaimer of warranty provisions.
|
|
|
|
#include "copyright.h"
|
|
#include "main.h"
|
|
#include "syscall.h"
|
|
#include "ksyscall.h"
|
|
//----------------------------------------------------------------------
|
|
// ExceptionHandler
|
|
// Entry point into the Nachos kernel. Called when a user program
|
|
// is executing, and either does a syscall, or generates an addressing
|
|
// or arithmetic exception.
|
|
//
|
|
// For system calls, the following is the calling convention:
|
|
//
|
|
// system call code -- r2
|
|
// arg1 -- r4
|
|
// arg2 -- r5
|
|
// arg3 -- r6
|
|
// arg4 -- r7
|
|
//
|
|
// 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!)
|
|
//
|
|
// "which" is the kind of exception. The list of possible exceptions
|
|
// is in machine.h.
|
|
//----------------------------------------------------------------------
|
|
|
|
void
|
|
ExceptionHandler(ExceptionType which)
|
|
{
|
|
int type = kernel->machine->ReadRegister(2);
|
|
int val;
|
|
int status, exit, threadID, programID;
|
|
int fd, size;
|
|
DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n");
|
|
switch (which) {
|
|
case SyscallException:
|
|
switch (type) {
|
|
case SC_Halt:
|
|
DEBUG(dbgSys, "Shutdown, initiated by user program.\n");
|
|
SysHalt();
|
|
cout << "in exception\n";
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
case SC_MSG:
|
|
DEBUG(dbgSys, "Message received.\n");
|
|
val = kernel->machine->ReadRegister(4);
|
|
{
|
|
char* msg = &(kernel->machine->mainMemory[val]);
|
|
cout << msg << endl;
|
|
}
|
|
SysHalt();
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
case SC_PrintInt:
|
|
val = kernel->machine->ReadRegister(4);
|
|
SysPrintInt(val);
|
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
return;
|
|
case SC_Create:
|
|
val = kernel->machine->ReadRegister(4);
|
|
{
|
|
char* filename = &(kernel->machine->mainMemory[val]);
|
|
//cout << filename << endl;
|
|
status = SysCreate(filename);
|
|
kernel->machine->WriteRegister(2, (int)status);
|
|
}
|
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
return;
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
case SC_Open:
|
|
val = kernel->machine->ReadRegister(4);
|
|
{
|
|
char* filename = &(kernel->machine->mainMemory[val]);
|
|
//cout << filename << endl;
|
|
fd = SysOpen(filename);
|
|
kernel->machine->WriteRegister(2, (int)fd);
|
|
}
|
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
return;
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
case SC_Write:
|
|
val = kernel->machine->ReadRegister(4);
|
|
size = kernel->machine->ReadRegister(5);
|
|
fd = kernel->machine->ReadRegister(6);
|
|
{
|
|
char* buffer = &(kernel->machine->mainMemory[val]);
|
|
size = SysWrite(buffer, size, fd);
|
|
kernel->machine->WriteRegister(2, (int)size);
|
|
}
|
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
return;
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
case SC_Close:
|
|
fd = kernel->machine->ReadRegister(4);
|
|
{
|
|
val = SysClose(fd);
|
|
kernel->machine->WriteRegister(2, (int)val);
|
|
}
|
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
return;
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
case SC_Read:
|
|
val = kernel->machine->ReadRegister(4);
|
|
size = kernel->machine->ReadRegister(5);
|
|
fd = kernel->machine->ReadRegister(6);
|
|
{
|
|
char* buffer = &(kernel->machine->mainMemory[val]);
|
|
size = SysRead(buffer, size, fd);
|
|
kernel->machine->WriteRegister(2, (int)size);
|
|
}
|
|
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
|
|
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg) + 4);
|
|
return;
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
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);
|
|
}
|
|
cout << "result is " << result << "\n";
|
|
return;
|
|
ASSERTNOTREACHED();
|
|
break;
|
|
case SC_Exit:
|
|
DEBUG(dbgAddr, "Program exit\n");
|
|
val = kernel->machine->ReadRegister(4);
|
|
cout << "return value:" << val << endl;
|
|
kernel->currentThread->Finish();
|
|
break;
|
|
default:
|
|
cerr << "Unexpected system call " << type << "\n";
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
cerr << "Unexpected user mode exception " << (int)which << "\n";
|
|
break;
|
|
}
|
|
ASSERTNOTREACHED();
|
|
}
|
|
|