⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syscall.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * *//************************************************************** * Syscall.c * * This file is used to emulate the system calls I want to * provide reliably.  Since Mipsy sometimes uses data handling, * I'll need to do this so that the system calls can see * coherent memory, which I provide by reading the caches * appropriately.  If the calls ran directly, as they do now, * incorrect memory can easily be seen by these calls * * Author: $Author: bosch $ * Date:   $Date: 1998/02/10 00:33:37 $ * * ************************************************************** */#include <stdio.h>#include "simtypes.h"#include "mipsy.h"#include "cpu.h"#include "sim_error.h"#include "cp0.h"#include "fpu.h"#include "eventcallback.h"#include "pcache.h"#include "cpu_stats.h"#include "simstats.h"#include "cpu_interface.h"#include "malloc.h"#include "sim_error.h"#include "solo_interface.h"#include <bstring.h>#include <sys/types.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <math.h>#include <errno.h>extern int errno;/* Includes for syscalls we emulate */#include <unistd.h>#include "solo.h"#include "solo_extras.h"#include "sys.s"#define PAGE_SIZE 4096extern char *AppBrk;extern uint soloLockBase;/* * ReadSyscallStringNolength * * This routine reads, a byte at a time, a null terminated ascii string * used for input to a syscall. This read goes through Mipsy Caches.  As * such, it must issue a read and the go away if it misses. * * This routine should return 1 only when the string is completely intact in * S->syscallBuf[which].  It should return 0 when the processor is stalling * for memory it needs. * */static intReadSyscallStringNolength(int cpuNum, int which, int base){   int i;   byte data;   SoloState *S = &machineState[cpuNum];    if (S->syscallState[which] == -1) {      S->syscallState[which] = 0;   }/*  AllocateSyscallString(P, which, length);  */				/* Allocate buffer area */   SIM_DEBUG(('o', "Reading ascii string starting at index %d for syscall #%d(%s)\n",              S->syscallState[which], S->syscallNum,              syscallName[S->syscallNum]));   /* Fill buffer coherently, bailing of if  I miss */   for (i=S->syscallState[which];; i++) {      if (SoloReadByte(cpuNum, base+i, &data) != SUCCESS) {	 /* syscall_op case will set up P's stall information */         	 SIM_DEBUG(('o', "Ascii string read stalling at addr %8.8x for syscall #%d(%s)\n",                    base+i,S->syscallNum, syscallName[S->syscallNum]));	 return 0;      } else {         if (i >= SYSCALL_BUF_SIZE) {            S->syscallBuf[which][SYSCALL_BUF_SIZE - 1] = 0;            CPUError("Syscall string parameter with length  > SYSCALL_BUF_SIZE\n%s\n",                       S->syscallBuf[which]);         }	 S->syscallBuf[which][i] = data;	 S->syscallState[which]=i+1;         if(data == 0)            break;      }   }      SIM_DEBUG(('o', "Ascii string read done for for syscall #%d(%s)\n",              S->syscallNum, syscallName[S->syscallNum]));   return 1;}   /* * ReadSyscallString * * This routine reads, a byte at a time, a string used for input to a * syscall. This read goes through Mipsy Caches.  As such, it must issue a * read and the go away if it misses.  * * This routine should return 1 only when the string is completely intact in * S->syscallBuf[which].  It should return 0 when the processor is stalling * for memory it needs. * */static intReadSyscallString(int cpuNum, int which, int base, int length){   int i;   byte data;   SoloState *S = &machineState[cpuNum];    if (length == 0) {		/* If length is zero...I do nothing *//* Currently using static allocation *//*      S->syscallBuf[which] = NULL; */      return 1;   }   if (S->syscallState[which] >= length) {      return 1;			/* This buffer is all ready to go */   }      if (S->syscallState[0] == -1) { /* I suspect the [0] here is a bug */      S->syscallState[0] = 0;   }/*  AllocateSyscallString(P, which, length);  */				/* Allocate buffer area */   SIM_DEBUG(('o', "Reading string starting at index %d(/%d) for syscall #%d(%s)\n",              S->syscallState[which], length, S->syscallNum,              syscallName[S->syscallNum]));   /* Fill buffer coherently, bailing of if  I miss */   for (i=S->syscallState[which]; i<length; i++) {      if (SoloReadByte(cpuNum, base+i, &data) != SUCCESS) {	 /* syscall_op case will set up P's stall information */	 SIM_DEBUG(('o', "String read stalling at addr %8.8x for syscall #%d(%s)\n",                    base+i,S->syscallNum, syscallName[S->syscallNum]));	 return 0;      } else {	 S->syscallBuf[which][i] = data;	 S->syscallState[which]=i+1;      }   }      SIM_DEBUG(('o', "String read done for for syscall #%d(%s)\n",              S->syscallNum, syscallName[S->syscallNum]));   return 1;}   /* * WriteSyscallString * * This routine writes, a byte at a time, a string derived from output of a * syscall. This write goes through Mipsy Caches.  As such, it must issue a * write and the go away if it misses.  * * This routine should return 1 only when the string is completely written from * S->syscallBuf[which].  It should return 0 when the processor is stalling * for memory it needs. * */static intWriteSyscallString(int cpuNum, int which, int base, int length){   int i;   SoloState *S = &machineState[cpuNum];    if (length == 0) {		/* If length is zero...I do nothing */      return 1;   }   if (S->syscallState[which] >= length) {      return 1;			/* This buffer is all ready to go */   }   SIM_DEBUG(('o', "Writing string starting at index %d(/%d) for syscall #%d(%s)\n",              S->syscallState[which], length, S->syscallNum,              syscallName[S->syscallNum]));   /* Fill buffer coherently, bailing of if  I miss */   for (i=S->syscallState[which]; i<length; i++) {       if (SoloWriteByte(cpuNum, base+i, S->syscallBuf[which][i]) != SUCCESS) {	 S->syscallState[which] = i;				/* Store partial progress indication */	 /* syscall_op case will set up P's stall information */	 SIM_DEBUG(('o', "String write stalling at addr %8.8x for syscall #%d(%s)\n",                    base+i,S->syscallNum, syscallName[S->syscallNum]));	 return 0;      }   }      SIM_DEBUG(('o', "String write done for for syscall #%d(%s)\n",              S->syscallNum, syscallName[S->syscallNum]));   return 1;}      /* * SoloEmulateSystemCall * * This routine emulates system calls, often over multiple steps.  A call * may come here multiple times before the syscall is ultimately * satisfied. * * This routine must return 0 if the system call is not complete! * * Switch cases should break(!) to the end if they complete successfully for * cleanup code to run. */intSoloEmulateSyscall(int cpuNum, int syscallNum){   long r4, r5, r6;   long err;   SoloState *S = &machineState[cpuNum];    CPUState *P = &(PE[cpuNum]);   if (!(((syscallNum+SYSVoffset) == SYS_pause) && (S->syscallState[0] != -1))) {      SIM_DEBUG(('o',"EmulateSyscall by cpu %d  syscallNum %d (%s)\n", cpuNum,                 syscallNum, syscallName[syscallNum]));   }   if (S->syscallNum != -1 &&       S->syscallNum != syscallNum) {				/*				 * This is the BEGINNING of emulation of a new				 * system call, not the continuation of an old				 * one!!  Initialize the state!  I do this				 * same work at the completion of a syscall,				 * so if I see this it means something is				 * wrong!				 */      CPUWarning("EmulateSyscall saw different syscallNum (new: %d, old %d\n",		   syscallNum, S->syscallNum);      /* Clean up */      S->syscallState[0] = -1;	/* Strings are uninitialized */      S->syscallState[1] = -1;  /* Strings are uninitialized */   }   S->syscallNum = syscallNum;   /* WARNING: Do not return 1 inside this switch. Use "break" instead */   switch (syscallNum+SYSVoffset) {/* Handled syscalls */   case SYS_exit:      CPUError("SoloMipsy should handle exit() (SYS_exit) in CPURun!\n");      break;   case SYS_brk:   {      int fd;      void *ret;      unsigned long incr;            SIM_DEBUG(('o', "Mipsy caught brk()...pP->R[4] = 0x%8.8x\n",P->R[4]));            if ((char *) P->R[4] > AppBrk) {				/* Will need more heap..grab 1MB more,  				   or how much the application requested,				   whichever is more */	 if ( ((unsigned long) P->R[4] - (unsigned long) AppBrk) > 0x100000) {	    incr = ((unsigned long) P->R[4] - (unsigned long) AppBrk);            /* has to be page aligned */            incr = ((incr + PAGE_SIZE - 1)/PAGE_SIZE)*PAGE_SIZE;	 } else {	    incr = 0x100000;	 }#if 0	 if ((uint) AppBrk+incr > soloLockBase) {	    CPUError("Mipsy: application brk() would have encroached on lock space:\nCurrent heap top: %8.8x  soloLockBase: %8.8x\n",		     AppBrk, soloLockBase);	 }#endif	 CPUPrint("Mipsy: Extending application heap region: %8.8x to %8.8x\n",		 AppBrk, AppBrk + incr);	 fd = open("/dev/zero", O_RDWR);	 if (fd == -1) {	    CPUError("brk emulation: /dev/zero open (for heap mmap) failed");	 }	 ret = (char *) mmap((void *) AppBrk, incr,			     PROT_READ|PROT_WRITE,			     MAP_SHARED|MAP_FIXED, fd, 0);	 if (ret != (char *) (AppBrk)) {	    perror("Mapping new heap region for application");	    (void) close(fd);	    return -1;	 }	 AppBrk += incr;	/* incr more memory now available */      }       /* memory already ready from before, just return success */      P->R[7] = 0;		/* Return success */      break;   }   case SYS_fxstat:            SIM_DEBUG(('o', "Emulating fxstat() system call\n"));      r4 = P->R[4];      r5 = P->R[5];      r6 = P->R[6];      if (S->syscallState[0] == -1) {				/* first time through */	 S->syscallState[0] = 0;	          /* the  libc stub code looks at a3 to decide if the call succeeded or failed */         err = _fxstat(r4, r5, (struct stat *)S->syscallBuf[0]);         if(err < 0) {            P->R[7] = 1;            P->R[2] = errno;            break;         } else {            P->syscallStatus = 0;            P->syscallResult = err;         }      }      if (!WriteSyscallString(cpuNum, 0, r6, sizeof(struct stat))) {	 return STALL;      } else {         P->R[7] = P->syscallStatus;         P->R[2] = P->syscallResult;      }      /* errno may not be supported correctly across threads */      /* Success */      break;         case SYS_open:            SIM_DEBUG(('o', "Emulating open() system call\n"));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -