00001 // exception.cc 00002 // Entry point into the Nachos kernel from user programs. 00003 // There are two kinds of things that can cause control to 00004 // transfer back to here from user code: 00005 // 00006 // syscall -- The user code explicitly requests to call a procedure 00007 // in the Nachos kernel. Right now, the only function we support is 00008 // "Halt". 00009 // 00010 // exceptions -- The user code does something that the CPU can't handle. 00011 // For instance, accessing memory that doesn't exist, arithmetic errors, 00012 // etc. 00013 // 00014 // Interrupts (which can also cause control to transfer from user 00015 // code into the Nachos kernel) are handled elsewhere. 00016 // 00017 // For now, this only handles the Halt() system call. 00018 // Everything else core dumps. 00019 // 00020 // Copyright (c) 1992-1996 The Regents of the University of California. 00021 // All rights reserved. See copyright.h for copyright notice and limitation 00022 // of liability and disclaimer of warranty provisions. 00023 00024 #include "copyright.h" 00025 #include "main.h" 00026 #include "syscall.h" 00027 #include "ksyscall.h" 00028 //---------------------------------------------------------------------- 00029 // ExceptionHandler 00030 // Entry point into the Nachos kernel. Called when a user program 00031 // is executing, and either does a syscall, or generates an addressing 00032 // or arithmetic exception. 00033 // 00034 // For system calls, the following is the calling convention: 00035 // 00036 // system call code -- r2 00037 // arg1 -- r4 00038 // arg2 -- r5 00039 // arg3 -- r6 00040 // arg4 -- r7 00041 // 00042 // The result of the system call, if any, must be put back into r2. 00043 // 00044 // If you are handling a system call, don't forget to increment the pc 00045 // before returning. (Or else you'll loop making the same system call forever!) 00046 // 00047 // "which" is the kind of exception. The list of possible exceptions 00048 // is in machine.h. 00049 //---------------------------------------------------------------------- 00050 00051 void 00052 ExceptionHandler(ExceptionType which) 00053 { 00054 int type = kernel->machine->ReadRegister(2); 00055 00056 DEBUG(dbgSys, "Received Exception " << which << " type: " << type << "\n"); 00057 00058 switch (which) { 00059 case SyscallException: 00060 switch(type) { 00061 case SC_Halt: 00062 DEBUG(dbgSys, "Shutdown, initiated by user program.\n"); 00063 00064 SysHalt(); 00065 00066 ASSERTNOTREACHED(); 00067 break; 00068 00069 case SC_Add: 00070 DEBUG(dbgSys, "Add " << kernel->machine->ReadRegister(4) << " + " << kernel->machine->ReadRegister(5) << "\n"); 00071 00072 /* Process SysAdd Systemcall*/ 00073 int result; 00074 result = SysAdd(/* int op1 */(int)kernel->machine->ReadRegister(4), 00075 /* int op2 */(int)kernel->machine->ReadRegister(5)); 00076 00077 DEBUG(dbgSys, "Add returning with " << result << "\n"); 00078 /* Prepare Result */ 00079 kernel->machine->WriteRegister(2, (int)result); 00080 00081 /* Modify return point */ 00082 { 00083 /* set previous programm counter (debugging only)*/ 00084 kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg)); 00085 00086 /* set programm counter to next instruction (all Instructions are 4 byte wide)*/ 00087 kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4); 00088 00089 /* set next programm counter for brach execution */ 00090 kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg)+4); 00091 } 00092 00093 return; 00094 00095 ASSERTNOTREACHED(); 00096 00097 break; 00098 00099 default: 00100 cerr << "Unexpected system call " << type << "\n"; 00101 break; 00102 } 00103 break; 00104 default: 00105 cerr << "Unexpected user mode exception" << (int)which << "\n"; 00106 break; 00107 } 00108 ASSERTNOTREACHED(); 00109 }