//--------------------------------------------------------------------- // Mbox send handler // // handle mbox send trap // mbox_send(mbox_t handle, int num_bytes, void *data) //---------------------------------------------------------------------- static int TrapMboxSendHandler (uint32 *trapArgs, int sysMode) { mbox_t handle; // Holds handle to mailbox char msg[MBOX_MAX_MESSAGE_LENGTH]; // Holds message in kernel space char *usermessage = NULL; // Pointer to user-space message int length=-1; // Holds length of message (in bytes) // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: handle to mailbox MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &handle, sizeof(mbox_t)); // Argument 1: length of message (in bytes) MemoryCopyUserToSystem (currentPCB, (trapArgs+1), &length, sizeof(int)); // Argument 2: pointer to message data MemoryCopyUserToSystem (currentPCB, (trapArgs+2), &usermessage, sizeof(char *)); // Now copy message data from user space to kernel space MemoryCopyUserToSystem (currentPCB, usermessage, msg, length); } else { // Already in kernel space, no address translation necessary handle = (mbox_t)trapArgs[0]; length = (int)trapArgs[1]; bcopy ((void *)(trapArgs[2]), (void *)msg, length); // Copy message into local variable for simplicity } return MboxSend(handle, length, msg); }
// file_delete(char *filename) int TrapFileDeleteHandler(uint32 *trapArgs, int sysMode) { char filename[FILE_MAX_FILENAME_LENGTH]; char *user_filename = NULL; int i; // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: userland pointer to filename string MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &user_filename, sizeof(uint32)); // Now copy userland filename string into our filename buffer for(i=0; i<FILE_MAX_FILENAME_LENGTH; i++) { MemoryCopyUserToSystem(currentPCB, (user_filename+i), &(filename[i]), sizeof(char)); // Check for end of user-space string if (filename[i] == '\0') break; } if (i == FILE_MAX_FILENAME_LENGTH) { printf("TrapFileDeleteHandler: length of filename longer than allowed!\n"); GracefulExit(); } dbprintf('F', "TrapDeleteCloseHandler: just parsed filename (%s) from trapArgs\n", filename); } else { // Already in kernel space, no address translation necessary dstrncpy(filename, (char *)(trapArgs[0]), FILE_MAX_FILENAME_LENGTH); } return FileDelete(filename); }
static void TrapProcessCreateHandler(uint32 *trapArgs, int sysmode) { char allargs[SIZE_ARG_BUFF]; char name[100]; int i=0, j=0, k=0; uint32 args[MAX_ARGS]; char *destination; // The first argument is the name of the executable file i=0; for(i=0;i<100; i++) allargs[i] = 0; i=0; if(!sysmode) { //Get the arguments into the sytem space MemoryCopyUserToSystem (currentPCB, trapArgs, args, sizeof (args)); do { MemoryCopyUserToSystem (currentPCB,((char*)args[0])+i,name+i,1); i++; } while ((i < sizeof (name)) && (name[i-1] != '\0')); } else { bcopy (trapArgs, args, sizeof (args)); dstrncpy ((char *)args[0], name, sizeof (name)); } name[sizeof(name)-1] = '\0'; // null terminate the name i=0; if(!sysmode) { //Copy the rest of the arguments to the system space for(j=0; (j<11)&&(args[j]!=0); j++) { k=0; do { MemoryCopyUserToSystem (currentPCB,((char*)args[j])+k,allargs+i,1); i++; k++; } while ((i<sizeof(allargs)) && (allargs[i-1]!='\0')); } } else { destination = &allargs[0]; for(j=0; (j<11)&&(args[j]!=0); j++) { k = dstrlen((char *)args[j]); //length of the argument if(&destination[k]-allargs>100) { printf("Fatal: Cumulative length of all arguments > 100\n"); exitsim(); } dstrcpy(destination, (char *)args[j]); destination[k] = '\0'; } } allargs[sizeof(allargs)-1] = '\0'; // null terminate the name ProcessFork(0, (uint32)allargs, name, 1); }
// file_read(uint32 handle, void *mem, int num_bytes) int TrapFileReadHandler(uint32 *trapArgs, int sysMode) { uint32 handle; char *user_mem; char mem[FILE_MAX_READWRITE_BYTES]; int num_bytes; int ret; // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: handle to file descriptor MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &handle, sizeof(uint32)); // Argument 1: userland address of where to copy newly read data MemoryCopyUserToSystem (currentPCB, (trapArgs+1), &user_mem, sizeof(uint32)); // Argument 2: integer number of bytes to read MemoryCopyUserToSystem (currentPCB, (trapArgs+2), &num_bytes, sizeof(uint32)); } else { // Already in kernel space, no address translation necessary handle = trapArgs[0]; user_mem = (char *)(trapArgs[1]); num_bytes = trapArgs[2]; } if (num_bytes > FILE_MAX_READWRITE_BYTES) { printf("TrapFileReadHandler: ERROR: you cannot read more than %d bytes at a time!\n", num_bytes); return FILE_FAIL; } if ((ret = FileRead(handle, mem, num_bytes)) == FILE_FAIL) { return FILE_FAIL; } // Copy bytes that we just read into user mem if (!sysMode) { MemoryCopySystemToUser(currentPCB, mem, user_mem, num_bytes); } else { bcopy(mem, user_mem, num_bytes); } return ret; }
// file_write(uint32 handle, void *mem, int num_bytes) int TrapFileWriteHandler(uint32 *trapArgs, int sysMode) { uint32 handle; char *user_mem; char mem[FILE_MAX_READWRITE_BYTES]; int num_bytes; int ret; // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: handle to file descriptor MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &handle, sizeof(uint32)); // Argument 1: userland address of where data to write is sitting MemoryCopyUserToSystem (currentPCB, (trapArgs+1), &user_mem, sizeof(uint32)); // Argument 2: integer number of bytes to write MemoryCopyUserToSystem (currentPCB, (trapArgs+2), &num_bytes, sizeof(uint32)); // Now copy bytes from userland to kernel buffer for writing if (num_bytes > FILE_MAX_READWRITE_BYTES) { printf("TrapFileWriteHandler: ERROR: you cannot write more than %d bytes at a time!\n", num_bytes); return FILE_FAIL; } MemoryCopyUserToSystem(currentPCB, user_mem, mem, num_bytes); } else { // Already in kernel space, no address translation necessary handle = trapArgs[0]; user_mem = (char *)(trapArgs[1]); num_bytes = trapArgs[2]; if (num_bytes > FILE_MAX_READWRITE_BYTES) { printf("TrapFileWriteHandler: ERROR: you cannot write more than %d bytes at a time!\n", num_bytes); return FILE_FAIL; } bcopy(user_mem, mem, num_bytes); } return FileWrite(handle, mem, num_bytes); return ret; }
//--------------------------------------------------------------------- // Disk write block handler // // handle trap that calls DiskWriteBlock() // disk_write_block(uint32 blocknum, disk_block *b) //---------------------------------------------------------------------- static int TrapDiskWriteBlockHandler(uint32 *trapArgs, int sysMode) { uint32 blocknum; // Holds block number disk_block *user_block = NULL; // Holds user-space address of disk_block disk_block b; // Holds block data in kernel space // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: block number MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &blocknum, sizeof(uint32)); // Argument 1: address of user-space disk_block structure MemoryCopyUserToSystem (currentPCB, (trapArgs+1), &user_block, sizeof(uint32)); // Now copy block from user space to kernel space MemoryCopyUserToSystem (currentPCB, user_block, &b, sizeof(disk_block)); } else { // Already in kernel space, no address translation necessary blocknum = trapArgs[0]; bcopy ((void *)(trapArgs[1]), (void *)&b, sizeof(disk_block)); // Copy message into local variable for simplicity } return DiskWriteBlock(blocknum, &b); }
//-------------------------------------------------------------------- // GetIntFromTrapArg(uint32 *trapArgs, int sysmode) //-------------------------------------------------------------------- static int GetIntFromTrapArg(uint32 *trapArgs, int sysmode) { int arg; if(!sysmode) { MemoryCopyUserToSystem (currentPCB, (char *)trapArgs, (char *)&arg, sizeof (arg)); } else { bcopy ((void *)trapArgs, (void *)&arg, sizeof (arg)); } return arg; }
//-------------------------------------------------------------------- // GetUintFromTrapArg(uint32 *trapArgs, int sysmode) //-------------------------------------------------------------------- static uint32 GetUintFromTrapArg(uint32 *trapArgs, int sysmode) { uint32 arg; if(!sysmode) { MemoryCopyUserToSystem (currentPCB, trapArgs, &arg, sizeof (arg)); } else { bcopy ((void *)trapArgs, (void *)&arg, sizeof (arg)); } return arg; }
// file_seek(uint32 handle, int num_bytes, int from_where) int TrapFileSeekHandler(uint32 *trapArgs, int sysMode) { uint32 handle; int num_bytes; int from_where; // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: handle to file descriptor MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &handle, sizeof(uint32)); // Argument 1: integer number of bytes to seek MemoryCopyUserToSystem (currentPCB, (trapArgs+1), &num_bytes, sizeof(uint32)); // Argument 2: integer representing where to seek from MemoryCopyUserToSystem (currentPCB, (trapArgs+2), &from_where, sizeof(uint32)); } else { handle = trapArgs[0]; num_bytes = trapArgs[1]; from_where = trapArgs[2]; } return FileSeek(handle, num_bytes, from_where); }
//--------------------------------------------------------------------- // Mbox receive handler // // handle mbox receive trap // int mbox_recv(mbox_t handle, int maxlength, void* message); //---------------------------------------------------------------------- static int TrapMboxRecvHandler (uint32 *trapArgs, int sysMode) { mbox_t handle; // Holds handle to mailbox char msg[MBOX_MAX_MESSAGE_LENGTH]; // Holds message in kernel space char *usermessage = NULL; // Pointer to user-space message int maxlength=-1; // Holds max length of message (in bytes) int retval; // Return value of MBoxReceive call // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: handle to mailbox MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &handle, sizeof(mbox_t)); // Argument 1: max length of message (in bytes) MemoryCopyUserToSystem (currentPCB, (trapArgs+1), &maxlength, sizeof(int)); // Argument 2: pointer to message data (user space) MemoryCopyUserToSystem (currentPCB, (trapArgs+2), &usermessage, sizeof(char *)); } else { // Already in kernel space, no address translation necessary handle = (mbox_t)trapArgs[0]; maxlength = (int)trapArgs[1]; usermessage = (char *)trapArgs[2]; } retval = MboxRecv(handle, maxlength, msg); if (retval == MBOX_FAIL) { // No copying necessary, user should assume msg is not filled in return retval; } else { // Copy message from msg to user space. Number of bytes is returned by MboxRecv if (!sysMode) { MemoryCopySystemToUser(currentPCB, msg, usermessage, retval); } else { bcopy(msg, usermessage, retval); } } return retval; }
// file_close(uint32 handle) int TrapFileCloseHandler(uint32 *trapArgs, int sysMode) { uint32 handle; // If we're not in system mode, we need to copy everything from the // user-space virtual address to the kernel space address if (!sysMode) { // Get the arguments themselves into system space // Argument 0: handle to file descriptor MemoryCopyUserToSystem (currentPCB, (trapArgs+0), &handle, sizeof(uint32)); } else { // Already in kernel space, no address translation necessary handle = trapArgs[0]; } return FileClose(handle); }
//-------------------------------------------------------------------- // // int process_create(char *exec_name, ...); // // Here we support reading command-line arguments. Maximum MAX_ARGS // command-line arguments are allowed. Also the total length of the // arguments including the terminating '\0' should be less than or // equal to SIZE_ARG_BUFF. // //-------------------------------------------------------------------- static void TrapProcessCreateHandler(uint32 *trapArgs, int sysmode) { char allargs[SIZE_ARG_BUFF]; // Stores full string of arguments (unparsed) char name[PROCESS_MAX_NAME_LENGTH]; // Local copy of name of executable (100 chars or less) char *username=NULL; // Pointer to user-space address of exec_name string int i=0, j=0; // Loop index variables char *args[MAX_ARGS]; // All parsed arguments (char *'s) int allargs_position = 0; // Index into current "position" in allargs char *userarg = NULL; // Current pointer to user argument string int numargs = 0; // Number of arguments passed on command line dbprintf('p', "TrapProcessCreateHandler: function started\n"); // Initialize allargs string to all NULL's for safety for(i=0;i<SIZE_ARG_BUFF; i++) { allargs[i] = '\0'; } // First deal with user-space addresses if(!sysmode) { dbprintf('p', "TrapProcessCreateHandler: creating user process\n"); // Get the known arguments into the kernel space. // Argument 0: user-space pointer to name of executable MemoryCopyUserToSystem (currentPCB, (char *)(trapArgs+0), (char *)&username, sizeof(char *)); // Copy the user-space string at user-address "username" into kernel space for(i=0; i<PROCESS_MAX_NAME_LENGTH; i++) { MemoryCopyUserToSystem(currentPCB, (char *)(username+i), (char *)&(name[i]), sizeof(char)); // Check for end of user-space string if (name[i] == '\0') break; } dbprintf('p', "TrapProcessCreateHandler: just parsed executable name (%s) from trapArgs\n", name); if (i == PROCESS_MAX_NAME_LENGTH) { printf("TrapProcessCreateHandler: length of executable filename longer than allowed!\n"); exitsim(); } // Copy the program name into "allargs", since it has to be the first argument (i.e. argv[0]) allargs_position = 0; dstrcpy(&(allargs[allargs_position]), name); allargs_position += dstrlen(name) + 1; // The "+1" is so we're pointing just beyond the NULL // Rest of arguments: a series of char *'s until we hit NULL or MAX_ARGS for(i=0; i<MAX_ARGS; i++) { // First, must copy the char * itself into kernel space in order to read its value MemoryCopyUserToSystem(currentPCB, (char *)(trapArgs+1+i), (char *)&userarg, sizeof(char *)); // If this is a NULL in the set of char *'s, this is the end of the list if (userarg == NULL) break; // Store a pointer to the kernel-space location where we're copying the string args[i] = &(allargs[allargs_position]); // Copy the string into the allargs, starting where we left off last time through this loop for (j=0; j<SIZE_ARG_BUFF; j++) { MemoryCopyUserToSystem(currentPCB, (char *)(userarg+j), (char *)&(allargs[allargs_position]), sizeof(char)); // Move current character in allargs to next spot allargs_position++; // Check that total length of arguments is still ok if (allargs_position == SIZE_ARG_BUFF) { printf("TrapProcessCreateHandler: strlen(all arguments) > maximum length allowed!\n"); exitsim(); } // Check for end of user-space string if (allargs[allargs_position-1] == '\0') break; } } if (i == MAX_ARGS) { printf("TrapProcessCreateHandler: too many arguments on command line (did you forget to pass a NULL?)\n"); exitsim(); } numargs = i+1; // Arguments are now setup } else { // Addresses are already in kernel space, so just copy into our local variables // for simplicity // Argument 0: (char *) name of program dstrncpy(name, (char *)(trapArgs[0]), PROCESS_MAX_NAME_LENGTH); // Copy the program name into "allargs", since it has to be the first argument (i.e. argv[0]) allargs_position = 0; dstrcpy(&(allargs[allargs_position]), name); allargs_position += dstrlen(name) + 1; // The "+1" is so that we are now pointing just beyond the "null" in the name allargs_position = 0; for (i=0; i<MAX_ARGS; i++) { userarg = (char *)(trapArgs[i+1]); if (userarg == NULL) break; // found last argument // Store the address of where we're copying the string args[i] = &(allargs[allargs_position]); // Copy string into allargs for(j=0; j<SIZE_ARG_BUFF; j++) { allargs[allargs_position] = userarg[j]; allargs_position++; if (allargs_position == SIZE_ARG_BUFF) { printf("TrapProcessCreateHandler: strlen(all arguments) > maximum length allowed!\n"); exitsim(); } // Check for end of user-space string if (allargs[allargs_position-1] == '\0') break; } } if (i == MAX_ARGS) { printf("TrapProcessCreateHandler: too many arguments on command line (did you forget to pass a NULL?)\n"); exitsim(); } numargs = i+1; } ProcessFork(0, (uint32)allargs, name, 1); }
//---------------------------------------------------------------------- // // doInterrupt // // Handle an interrupt or trap. // //---------------------------------------------------------------------- void dointerrupt (unsigned int cause, unsigned int iar, unsigned int isr, uint32 *trapArgs) { int result; int i; uint32 args[4]; int intrs; uint32 handle; int ihandle; dbprintf ('t',"Interrupt cause=0x%x iar=0x%x isr=0x%x args=0x%08x.\n", cause, iar, isr, (int)trapArgs); // If the TRAP_INSTR bit is set, this was from a trap instruction. // If the bit isn't set, this was a system interrupt. if (cause & TRAP_TRAP_INSTR) { cause &= ~TRAP_TRAP_INSTR; switch (cause) { case TRAP_CONTEXT_SWITCH: dbprintf ('t', "Got a context switch trap!\n"); ProcessSchedule (); ClkResetProcess(); break; case TRAP_EXIT: case TRAP_USER_EXIT: dbprintf ('t', "Got an exit trap!\n"); ProcessDestroy (currentPCB); ProcessSchedule (); ClkResetProcess(); break; case TRAP_PROCESS_FORK: dbprintf ('t', "Got a fork trap!\n"); break; case TRAP_PROCESS_SLEEP: dbprintf ('t', "Got a process sleep trap!\n"); ProcessSuspend (currentPCB); ProcessSchedule (); ClkResetProcess(); break; case TRAP_PRINTF: // Call the trap printf handler and pass the arguments and a flag // indicating whether the trap was called from system mode. dbprintf ('t', "Got a printf trap!\n"); TrapPrintfHandler (trapArgs, isr & DLX_STATUS_SYSMODE); break; case TRAP_OPEN: // Get the arguments to the trap handler. If this is a user mode trap, // copy them from user space. if (isr & DLX_STATUS_SYSMODE) { args[0] = trapArgs[0]; args[1] = trapArgs[1]; } else { char filename[32]; // trapArgs points to the trap arguments in user space. There are // two of them, so copy them to to system space. The first argument // is a string, so it has to be copied to system space and the // argument replaced with a pointer to the string in system space. MemoryCopyUserToSystem (currentPCB, (char *)trapArgs, (char *)args, sizeof(args[0])*2); MemoryCopyUserToSystem (currentPCB, (char *)(args[0]), (char *)filename, 31); // Null-terminate the string in case it's longer than 31 characters. filename[31] = '\0'; // Set the argument to be the filename args[0] = (uint32)filename; } // Allow Open() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, args[1] + 0x10000); printf ("Got an open with parameters ('%s',0x%x)\n", (char *)(args[0]), args[1]); RestoreIntrs (intrs); break; case TRAP_CLOSE: // Allow Close() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_READ: // Allow Read() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_WRITE: // Allow Write() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_DELETE: intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_SEEK: intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_PROCESS_GETPID: ProcessSetResult(currentPCB, GetCurrentPid()); break; case TRAP_PROCESS_CREATE: TrapProcessCreateHandler(trapArgs, isr & DLX_STATUS_SYSMODE); break; case TRAP_SEM_CREATE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = SemCreate(ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_SEM_WAIT: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = SemHandleWait(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_SEM_SIGNAL: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = SemHandleSignal(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_MALLOC: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = (int)malloc(currentPCB, ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_MFREE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = mfree(currentPCB, (void*)ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_LOCK_CREATE: ihandle = LockCreate(); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_LOCK_ACQUIRE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = LockHandleAcquire(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_LOCK_RELEASE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); handle = LockHandleRelease(ihandle); ProcessSetResult(currentPCB, handle); //Return 1 or 0 break; case TRAP_COND_CREATE: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondCreate(ihandle); ProcessSetResult(currentPCB, ihandle); //Return handle break; case TRAP_COND_WAIT: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondHandleWait(ihandle); ProcessSetResult(currentPCB, ihandle); //Return 1 or 0 break; case TRAP_COND_SIGNAL: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondHandleSignal(ihandle); ProcessSetResult(currentPCB, ihandle); //Return 1 or 0 break; case TRAP_COND_BROADCAST: ihandle = GetIntFromTrapArg(trapArgs, isr & DLX_STATUS_SYSMODE); ihandle = CondHandleBroadcast(ihandle); ProcessSetResult(currentPCB, ihandle); //Return 1 or 0 break; default: printf ("Got an unrecognized trap (0x%x) - exiting!\n", cause); exitsim (); break; } } else { switch (cause) { case TRAP_TIMER: dbprintf ('t', "Got a timer interrupt!\n"); // ClkInterrupt returns 1 when 1 "process quantum" has passed, meaning // that it's time to call ProcessSchedule again. if (ClkInterrupt()) { ProcessSchedule (); } break; case TRAP_KBD: do { i = *((uint32 *)DLX_KBD_NCHARSIN); result = *((uint32 *)DLX_KBD_GETCHAR); printf ("Got a keyboard interrupt (char=0x%x(%c), nleft=%d)!\n", result, result, i); } while (i > 1); break; case TRAP_ACCESS: printf ("Exiting after illegal access at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_ADDRESS: printf ("Exiting after illegal address at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_ILLEGALINST: printf ("Exiting after illegal instruction at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_PAGEFAULT: MemoryPageFaultHandler(currentPCB); break; default: printf ("Got an unrecognized system interrupt (0x%x) - exiting!\n", cause); exitsim (); break; } } dbprintf ('t',"About to return from dointerrupt.\n"); // Note that this return may schedule a new process! intrreturn (); }
//---------------------------------------------------------------------- // // TrapPrintfHandler // // Handle a printf trap.here. // Note that the maximum format string length is PRINTF_MAX_FORMAT_LENGTH // characters. Exceeding this length could have unexpected results. // //---------------------------------------------------------------------- static void TrapPrintfHandler(uint32 *trapArgs, int sysMode) { char formatstr[PRINTF_MAX_FORMAT_LENGTH]; // Copy user format string here char *userformatstr=NULL; // Holds user-space address of format string int i,j; // Loop index variables int numargs=0; // Keeps track of number of %'s (i.e. number of arguments) uint32 args[PRINTF_MAX_ARGS]; // Keeps track of all our args char *userstr; // Holds user-space address of the string that goes with any "%s"'s char strings_storage[PRINTF_MAX_STRING_ARGS][PRINTF_MAX_STRING_ARG_LENGTH]; // Places to copy strings for "%s" into int string_argnum=0; // Keeps track of how many "%s"'s we have received (index into strings_storage) if (!sysMode) { // Copy user-space format string into kernel space // Argument 0: format string MemoryCopyUserToSystem(currentPCB, (char *)(trapArgs+0), (char *)&userformatstr, sizeof(char *)); // Copy format string itself from user space to kernel space for(i=0; i<PRINTF_MAX_FORMAT_LENGTH; i++) { MemoryCopyUserToSystem(currentPCB, (char *)(userformatstr + i), (char *)&(formatstr[i]), sizeof(char)); // Check for end of string if (formatstr[i] == '\0') break; } if (i == PRINTF_MAX_FORMAT_LENGTH) { // format string too long printf("TrapPrintfHandler: format string too long!\n"); return; } } else { // Not in system mode, can just copy string directly dstrncpy(formatstr, (char *)(trapArgs+0), PRINTF_MAX_FORMAT_LENGTH); } // Now read format string to find all the %'s numargs = 0; string_argnum = 0; for(i=0; i<dstrlen(formatstr); i++) { if (formatstr[i] == '%') { // Check for "%%" i++; // Skip over % symbol to look at the next character switch(formatstr[i]) { case '%': continue; // Skip over "%%" break; case 'c': // chars // This argument is a single char value, but I think it's stored as a full int value. // If it isn't, then I'm not sure how to call the *real* printf below with some non-4-byte arguments. // The "+1" is because trapArgs[0] is the format string if (!sysMode) { MemoryCopyUserToSystem(currentPCB, (char *)(trapArgs+numargs+1), (char *)&(args[numargs]), sizeof(int)); } else { args[numargs] = trapArgs[numargs+1]; } numargs++; break; case 'l': if (formatstr[i+1] != 'f') { printf("TrapPrintfHandler: unrecognized format character (l%c)\n", formatstr[i+1]); return; } i++; // There is intentionally no "break" here so that the %lf and %f cases do the same thing. // This is what the previous Printf did, but I'm not sure yet that it is right. case 'f': // double floating points (64 bits) case 'g': case 'e': if (!sysMode) { MemoryCopyUserToSystem(currentPCB, (char *)(trapArgs+numargs+1), (char *)&(args[numargs]), sizeof(double)); } else { args[numargs] = trapArgs[numargs+1]; args[numargs+1] = trapArgs[numargs+2]; } numargs += 2; // numargs is incremented by 2 since a double is the size of 2 ints break; case 'd': // integers if (!sysMode) { MemoryCopyUserToSystem(currentPCB, (char *)(trapArgs+numargs+1), (char *)&(args[numargs]), sizeof(int)); } else { args[numargs] = trapArgs[numargs+1]; } numargs++; break; case 's': // string if (!sysMode) { // First make sure we still have local string storage space available if (string_argnum == PRINTF_MAX_STRING_ARGS) { printf("TrapPrintfHandler: too many %%s arguments passed!\n"); return; } // Now copy the user-space address of the string into kernel space MemoryCopyUserToSystem(currentPCB, (char *)(trapArgs+numargs+1), (char *)&userstr, sizeof(char *)); // Now copy each individual character from that string into kernel space for(j=0; j<PRINTF_MAX_STRING_ARG_LENGTH; j++) { MemoryCopyUserToSystem(currentPCB, (char *)(userstr+j), (char *)&(strings_storage[string_argnum][j]), sizeof(char)); // Check for end of user-space string if (strings_storage[string_argnum][j] == '\0') break; } if (j == PRINTF_MAX_STRING_ARG_LENGTH) { // String was too long! printf("TrapPrintfHandler: argument #%d (a string) was too long to print!\n", numargs); return; } // Put the address of this kernel-space string as the argument for printf args[numargs] = (int)(strings_storage[string_argnum]); string_argnum++; } else { // kernel space already, just copy address out of trapArgs args[numargs] = trapArgs[numargs+1]; } numargs++; break; default: printf("TrapPrintfHandler: unrecognized format character (%c)!\n", formatstr[i+1]); return; } } } // Now we can print them all out switch(numargs) { case 0: printf(formatstr); break; case 1: printf(formatstr, args[0]); break; case 2: printf(formatstr, args[0], args[1]); break; case 3: printf(formatstr, args[0], args[1], args[2]); break; case 4: printf(formatstr, args[0], args[1], args[2], args[3]); break; case 5: printf(formatstr, args[0], args[1], args[2], args[3], args[4]); break; case 6: printf(formatstr, args[0], args[1], args[2], args[3], args[4], args[5]); break; case 7: printf(formatstr, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break; case 8: printf(formatstr, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break; case 9: printf(formatstr, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); break; case 10: printf(formatstr, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); break; case 11: printf(formatstr, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); break; case 12: printf(formatstr, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); break; default: printf("TrapPrintfHandler: too many arguments (%d) passed!\n", numargs); } // Done! }
//---------------------------------------------------------------------- // // TrapPrintfHandler // // Handle a printf trap.here. This printf code will correctly // handle integers but will not correctly handle strings (yet). // Also, note that the maximum format string length is 79 characters. // Exceeding this length will cause the format to be truncated. // //---------------------------------------------------------------------- static void TrapPrintfHandler (uint32 *trapArgs, int sysMode) { char formatstr[80]; int i = 0; uint32 printfArgs[10]; uint32 args[10]; int nargs = 0; char *c; // The first argument is the print format string. Copy it to system // space, truncating if necessary. i = 0; if (!sysMode) { // Get the arguments themselves into system space MemoryCopyUserToSystem (currentPCB, trapArgs, args, sizeof (args)); do { MemoryCopyUserToSystem (currentPCB,((char*)args[0])+i,formatstr+i,1); i++; } while ((i < sizeof (formatstr)) && (formatstr[i-1] != '\0')); } else { bcopy (trapArgs, args, sizeof (args)); dstrncpy ((char *)args[0], formatstr, sizeof (formatstr)); } formatstr[sizeof(formatstr)-1] = '\0'; // null terminate the fmt str for (c = formatstr; *c != '\0'; c++) { if (*c == '%') { // if this is a %%, skip past second % if (*(c+1) == '%') { c++; continue; } // Get the current argument off the stack printfArgs[nargs] = args[nargs+1]; // dbprintf ('t', "Argument %d at 0x%x is %d (0x%x).\n", nargs, // args[nargs], args[nargs]); while (1) { c++; if (*c == 's') { // Handle strings here. They don't work for user programs (yet...) break; } else if (*c == 'l') { continue; } else if ((*c == 'f') || (*c == 'g') || (*c == 'e')) { // If it's a floating point number, it'll be passed as // a double, so grab the second word also. nargs += 1; printfArgs[nargs] = args[nargs+1]; break; } else if ((*c >= 'a') && (*c <= 'z')) { // If it's another formatting character, it's not // a string, but we can leave the loop anyway. break; } } nargs += 1; } } printf (formatstr,printfArgs[0],printfArgs[1],printfArgs[2], printfArgs[3], printfArgs[4], printfArgs[5], printfArgs[6], printfArgs[7]); }
//---------------------------------------------------------------------- // // doInterrupt // // Handle an interrupt or trap. // //---------------------------------------------------------------------- void dointerrupt (unsigned int cause, unsigned int iar, unsigned int isr, uint32 *trapArgs) { int result; int i; uint32 args[4]; int intrs; dbprintf ('t',"Interrupt cause=0x%x iar=0x%x isr=0x%x args=0x%08x.\n", cause, iar, isr, (int)trapArgs); // If the TRAP_INSTR bit is set, this was from a trap instruction. // If the bit isn't set, this was a system interrupt. if (cause & TRAP_TRAP_INSTR) { cause &= ~TRAP_TRAP_INSTR; switch (cause) { case TRAP_CONTEXT_SWITCH: dbprintf ('t', "Got a context switch trap!\n"); ProcessSchedule (); break; case TRAP_EXIT: dbprintf ('t', "Got an exit trap!\n"); ProcessDestroy (currentPCB); ProcessSchedule (); break; case TRAP_PROCESS_FORK: dbprintf ('t', "Got a fork trap!\n"); break; case TRAP_PROCESS_SLEEP: dbprintf ('t', "Got a process sleep trap!\n"); ProcessSuspend (currentPCB); ProcessSchedule (); break; case TRAP_PRINTF: // Call the trap printf handler and pass the arguments and a flag // indicating whether the trap was called from system mode. dbprintf ('t', "Got a printf trap!\n"); TrapPrintfHandler (trapArgs, isr & DLX_STATUS_SYSMODE); break; case TRAP_OPEN: // Get the arguments to the trap handler. If this is a user mode trap, // copy them from user space. if (isr & DLX_STATUS_SYSMODE) { args[0] = trapArgs[0]; args[1] = trapArgs[1]; } else { char filename[32]; // trapArgs points to the trap arguments in user space. There are // two of them, so copy them to to system space. The first argument // is a string, so it has to be copied to system space and the // argument replaced with a pointer to the string in system space. MemoryCopyUserToSystem (currentPCB, trapArgs, args, sizeof(args[0])*2); MemoryCopyUserToSystem (currentPCB, args[0], filename, 31); // Null-terminate the string in case it's longer than 31 characters. filename[31] = '\0'; // Set the argument to be the filename args[0] = (uint32)filename; } // Allow Open() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, args[1] + 0x10000); printf ("Got an open with parameters ('%s',0x%x)\n", (char *)args[0], args[1]); RestoreIntrs (intrs); break; case TRAP_CLOSE: // Allow Close() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_READ: // Allow Read() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_WRITE: // Allow Write() calls to be interruptible! intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_DELETE: intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_SEEK: intrs = EnableIntrs (); ProcessSetResult (currentPCB, -1); RestoreIntrs (intrs); break; case TRAP_PROCESS_GETPID: intrs = EnableIntrs (); ProcessSetResult (currentPCB, GetCurrentPid()); RestoreIntrs (intrs); break; default: printf ("Got an unrecognized trap (0x%x) - exiting!\n", cause); exitsim (); break; } } else { switch (cause) { case TRAP_TIMER: dbprintf ('t', "Got a timer interrupt!\n"); ProcessSchedule (); break; case TRAP_KBD: do { i = *((uint32 *)DLX_KBD_NCHARSIN); result = *((uint32 *)DLX_KBD_GETCHAR); printf ("Got a keyboard interrupt (char=0x%x(%c), nleft=%d)!\n", result, result, i); } while (i > 1); break; case TRAP_ACCESS: printf ("Exiting after illegal access at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_ADDRESS: printf ("Exiting after illegal address at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_ILLEGALINST: printf ("Exiting after illegal instruction at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; case TRAP_PAGEFAULT: printf ("Exiting after page fault at iar=0x%x, isr=0x%x\n", iar, isr); exitsim (); break; default: printf ("Got an unrecognized system interrupt (0x%x) - exiting!\n", cause); exitsim (); break; } } dbprintf ('t',"About to return from dointerrupt.\n"); // Note that this return may schedule a new process! intrreturn (); }