06-16-09-Syscalls

From Msim

Jump to: navigation, search

This page describes the changes made to syscall.c to provide/fix/adjust functionality of the syscall support provided.
We indicate the additional code here.

Contents

OSF_SYS_SETSYSINFO

#include <sys/sysinfo.h>
#define OSF_SYS_setsysinfo  257
case OSF_SYS_setsysinfo:
if(regs->regs_R[MD_REG_A0]==SSI_IEEE_FP_CONTROL)
{
 //We are just ignoring this, it "might" be ok
 fprintf(stderr,"faked setsysinfo(SSI_IEEE_FP_CONTROL,...) - returning ok");
 regs->regs_R[MD_REG_V0] = 1;
}
else
{
 warn("unsupported setsysinfo(op,...) option");
 regs->regs_R[MD_REG_V0] = 0;
}
 regs->regs_R[MD_REG_A3] = 0;
 check_error = true;
break;
//This defines the subset of the OSF/1 getsysinfo/setsysinfo calls that we support (read: have to support)
//setsysinfo
#define SSI_NVPAIRS                     1
#define SSI_IEEE_FP_CONTROL             14
#define SSI_IEEE_STATE_AT_SIGNAL        15
#define SSI_IEEE_IGNORE_STATE_AT_SIGNAL 16
#define SSI_IEEE_RAISE_EXCEPTION        1001    /* linux specific */

OSF_SYS_GETSYSINFO

#include <sys/sysinfo.h>
#define OSF_SYS_getsysinfo  256
case OSF_SYS_getsysinfo:
{
 if(regs->regs_R[MD_REG_A0]==GSI_IEEE_FP_CONTROL)
 {
  //This is taken from the FPCR_MASK define in asm/fpu.h
  unsigned long long temp(0xffff800000000000L);
  mem_bcopy(mem_fn, mem, Write, regs->regs_R[MD_REG_A1], &temp, sizeof(unsigned long long));
 }
 else
 {
  warn("unsupported getsysinfo(op,...) option");
  fprintf(stderr,"Args:\n0: %lld\n1: %lld\n2: %lld\n3: %lld\n4: %lld\n5: %lld\n",regs->regs_R[MD_REG_A0],regs->regs_R[MD_REG_A1],regs->regs_R[MD_REG_A2],regs->regs_R[MD_REG_A3],regs->regs_R[MD_REG_A4],regs->regs_R[MD_REG_A5]);
 }
 regs->regs_R[MD_REG_V0] = 0;
 check_error = true;
}
break;
//This defines the subset of the OSF/1 getsysinfo/setsysinfo calls that we support (read: have to support)
//getsysinfo
#define GSI_UACPROC                     8
#define GSI_IEEE_FP_CONTROL             45
#define GSI_IEEE_STATE_AT_SIGNAL        46
#define GSI_PROC_TYPE                   60
#define GSI_GET_HWRPB                   101

OSF_SYS_FSTAT64

The following class is required to store fstat64 data in alpha format (it is slightly different than native linux).

#define OSF_SYS_fstat64     427
class osf_statbuf64
{
 public:
  unsigned long long	osf_st_dev;
  unsigned long long	osf_st_ino;
  unsigned long long	osf_st_rdev;
  long long		osf_st_size;
  unsigned long long	osf_st_blocks;
  unsigned int		osf_st_mode;
  unsigned int		osf_st_uid;
  unsigned int		osf_st_gid;
  unsigned int		osf_st_blksize;
  unsigned int		osf_st_nlink;
  int			__pad0;
  unsigned long long	osf_st_atime;
  unsigned long long	osf_st_atime_nsec;
  unsigned long long	osf_st_mtime;
  unsigned long long	osf_st_mtime_nsec;
  unsigned long long	osf_st_ctime;
  unsigned long long	osf_st_ctime_nsec;
  long long	__unused[3];
};
case OSF_SYS_fstat64:
{
 osf_statbuf64 osf_sbuf;
 struct stat64 sbuf;
 //fstat64() the file
 regs->regs_R[MD_REG_V0] = fstat64(regs->regs_R[MD_REG_A0], &sbuf);
 
 check_error = true;
 
 //translate the stat structure to host format
 osf_sbuf.osf_st_dev = MD_SWAPQ(sbuf.st_dev);
 osf_sbuf.osf_st_ino = MD_SWAPQ(sbuf.st_ino);
 osf_sbuf.osf_st_rdev = MD_SWAPQ(sbuf.st_rdev);
 osf_sbuf.osf_st_size = MD_SWAPQ(sbuf.st_size);
 osf_sbuf.osf_st_mode = MD_SWAPW(sbuf.st_mode);
 osf_sbuf.osf_st_uid = MD_SWAPW(sbuf.st_uid);
 osf_sbuf.osf_st_gid = MD_SWAPW(sbuf.st_gid);
 osf_sbuf.osf_st_nlink = MD_SWAPW(sbuf.st_nlink);
 osf_sbuf.osf_st_atime = MD_SWAPQ(sbuf.st_atime);
 osf_sbuf.osf_st_mtime = MD_SWAPQ(sbuf.st_mtime);
 osf_sbuf.osf_st_ctime = MD_SWAPQ(sbuf.st_ctime);
#ifndef _MSC_VER
 osf_sbuf.osf_st_blksize = MD_SWAPQ(sbuf.st_blksize);
 osf_sbuf.osf_st_blocks = MD_SWAPW(sbuf.st_blocks);
#endif /* !_MSC_VER */
 
 //copy fstat64() results to simulator memory
 mem_bcopy(mem_fn, mem, Write, regs->regs_R[MD_REG_A1], &osf_sbuf, sizeof(osf_statbuf64));
}
break;

OSF_SYS_EXIT_GROUP

#define OSF_SYS_exit_group  405

Syscall code:

case OSF_SYS_exit_group:
 //FIXME: This terminates the entire simulator, should we just kill the thread instead?
 //exit jumps to the target set in main()
 fprintf(stderr,"Received syscode OSF_SYS_exit_group with status: %lld, exiting\n",regs->regs_R[MD_REG_A0]);
 warn("Threading is not supported, therefore, can't kill threads");
 longjmp(sim_exit_buf,/* exitcode + fudge */(regs->regs_R[MD_REG_A0] & 0xff) + 1);
 break;


OSF_SYS_OBREAK

The original implementation was incorrect.

case OSF_SYS_obreak:
{
 //http://kerneltrap.org/man/linux/man2/brk.2
 if(regs->regs_R[MD_REG_A0]==0)
 {
  regs->regs_R[MD_REG_V0] = mem->ld_brk_point;
  regs->regs_R[MD_REG_A3] = 0;
 }
 else
 {
  mem->ld_brk_point = regs->regs_R[MD_REG_A0];
  regs->regs_R[MD_REG_V0] = 0;
  regs->regs_R[MD_REG_A3] = 0;
 }
}
break;


OSF_SYS_UNAME

#include <sys/utsname.h>

OSF_SYS_uname was previously defined as 207. That is now utsname.

#define OSF_SYS_uname       339

OSF_SYS_UTSNAME

#include <sys/utsname.h>
#define OSF_SYS_utsname       207

The original implementation was incomplete.

case OSF_SYS_utsname:
case OSF_SYS_uname:
//Entry size is defined by the use of sys/utsname.h. We will hope/assume the pointer can handle it without overflow.
//Gets name and information about the current kernel
{
 utsname temp;
 regs->regs_R[MD_REG_V0] = uname(&temp);
 mem_bcopy(mem_fn, mem, Write, regs->regs_R[MD_REG_A0], &temp, sizeof(utsname));
 check_error = true;
}
break;


OSF_SYS_MMAP

Memory mapping was implemented incorrectly since the simulator can't use the pointers provided. Now, we just assign a pointer (the memory logic can handle it) incrementally into the memory space (this is totally incorrect in reality but works in simulation).
The first memory map gets address 0x160000000, each successive request is at address+0x1000000. The request is always granted.

//Defines provided for mmap
#define PROT_READ             0x1             //Page can be read.
#define PROT_WRITE            0x2             //Page can be written.
#define PROT_EXEC             0x4             //Page can be executed.
#define PROT_NONE             0x0             //Page can not be accessed
#define OSF_MAP_ANON          0x10            //Don't use a file
#define MAP_ANON              0x20
#define MAP_FILE              0x0
#define OSF_MAP_FIXED         0x100           //Interpret addr exactly
#define MAP_FIXED             0x10
#define MAP_SHARED            0x01            //Share changes
#define MAP_PRIVATE           0x02            //Changes are private
unsigned long long next_map = 0x160000000;    //Used for mmap to tell the program where the mapping occurs (this is a hack implementation)
case OSF_SYS_mmap:
{
 unsigned long long addr(regs->regs_R[MD_REG_A0]);
 long long len(regs->regs_R[MD_REG_A1]);
 int prot(regs->regs_R[MD_REG_A2]), flags(regs->regs_R[MD_REG_A3]);
 long long fd(regs->regs_R[MD_REG_A4]), offset(regs->regs_R[MD_REG_A5]);
 fprintf(stderr,"Warning: partially supported OSF_SYS_mmap: Addr: %llx Len: %lld Prot: 0x%x Flags: 0x%x FD: %lld\t",addr,len,prot,flags,fd,offset);
 
 //We don't support fixed memory mapping
 if(flags&OSF_MAP_FIXED)
 {
  warn("Fixed memory mapping not supported");
  regs->regs_R[MD_REG_A3] = -1;
  regs->regs_R[MD_REG_V0] = errno;
 }
 
 if(regs->regs_R[MD_REG_A0]!=0)
 {
  warn("Memory map location hints (param 1, addr) not supported (%lld), ignoring\n",addr);
 }
 
 char * buf = new char[regs->regs_R[MD_REG_A1]];
 unsigned long long address(next_map);
 next_map += 0x10000000;
 if(flags&OSF_MAP_ANON)
 {
  if(fd!=-1)
  {
   warn("Mach VM flags are not supported");
  }
  //Just return the address, successive writes and reads will be taken care of (zeroed)
 }
 else
 {
  //memory map is backed by a file - we need to read it (or map it ourselves)
  warn("Memory mapping to a file, file will not be altered");
  lseek(fd,offset,SEEK_SET);
  read(fd,buf,len);
  mem_bcopy(mem_fn, mem, Write, address, buf, len);
 }
 
 //Based on other syscalls, this seems reversed...
 //regs->regs_R[MD_REG_V0] = (qword_t)buf; //isn't this errno....
 regs->regs_R[MD_REG_V0] = address; //isn't this errno....
 regs->regs_R[MD_REG_A3] = 0; //shouldn't this be the address....
 }
break;


Redirection

Syscalls that try to use STDOUT, STDERR, STDIN may be redirected. They must be given the appropriate file handle if they are used.

//Preprocess, we want to fix input/output redirection here
bool redirected = false;
long long oldA0 = 0;
switch(syscode)
{
case OSF_SYS_read:
case OSF_SYS_write:
case OSF_SYS_lseek:
case OSF_SYS_ioctl:
case OSF_SYS_fstat64:
case OSF_SYS_fstat:
case OSF_SYS_stat64:
case OSF_SYS_stat:
case OSF_SYS_lstat:

Other SetSysInfo/GetSysInfo Defines

//other
#define SSIN_UACPROC                    6
#define UAC_BITMASK                     7
#define UAC_NOPRINT                     1
#define UAC_NOFIX                       2
#define UAC_SIGBUS                      4

Additional Minor Changes

These changes are not complete but may be adequate for the time being.

OSF_SYS_GETRUSAGE2

This syscall is using OSF_SYS_GETRUSAGE's code.

#define OSF_SYS_getrusage2   364

OSF_SYS_STAT64

This syscall is provided using the original stat support. This may not be correct but has worked in our test cases (we'll take a look at this at some point - or if we can find a case that breaks this).

#define OSF_SYS_stat64      425

The OSF_SYS_STAT code was copied as OSF_SYS_STAT64 and noted with a FIXME.

OSF_SYS_GETTIMEOFDAY2

This syscall is attached to OSF_SYS_GETTIMEOFDAY. We are unable to tell if this works or not at this time due to the locale problem.

#define OSF_SYS_gettimeofday2 359

OSF_SYS_RT_SIGACTION

This syscall is attached to OSF_SYS_SIGACTION. Sigaction is partially supported and this syscall will likely be partially supported as well. Be aware that rt_sigaction takes an additional parameter compared to sigaction.

#define OSF_SYS_rt_sigaction 352

OSF_SYS_MUNMAP

The original implementation assumed the use of pointers and that is not how the memory logic is implemented. Munmap does not do any deallocation. It just returns true - therefore, we can't detect double free, or incorrect frees.

case OSF_SYS_munmap:
{
 //warn("partially supported OSF_SYS_munmap");
 //fprintf(stderr,"Args:\nAddr:\t %llx\nLen:\t %lld\n",regs->regs_R[MD_REG_A0],regs->regs_R[MD_REG_A1]);
 
 //If we simply do nothing, the memory will be deallocated at simulator destruction
 //However, then we aren't checking for already deallocated memory, etc.
 regs->regs_R[MD_REG_A3] = 0;
 regs->regs_R[MD_REG_V0] = 0;
}
break;
Personal tools