automated merge
This commit is contained in:
commit
7a0bf814b6
14 changed files with 366 additions and 148 deletions
|
@ -431,7 +431,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
|
|||
/* 302 */ SyscallDesc("mount", unimplementedFunc),
|
||||
/* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc),
|
||||
/* 304 */ SyscallDesc("swapoff", unimplementedFunc),
|
||||
/* 305 */ SyscallDesc("getdents", getdentsFunc),
|
||||
/* 305 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 306 */ SyscallDesc("create_module", unimplementedFunc),
|
||||
/* 307 */ SyscallDesc("init_module", unimplementedFunc),
|
||||
/* 308 */ SyscallDesc("delete_module", unimplementedFunc),
|
||||
|
@ -503,7 +503,7 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
|
|||
/* 374 */ SyscallDesc("pivot_root", unimplementedFunc),
|
||||
/* 375 */ SyscallDesc("mincore", unimplementedFunc),
|
||||
/* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc),
|
||||
/* 377 */ SyscallDesc("getdents64", getdents64Func),
|
||||
/* 377 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 378 */ SyscallDesc("gettid", unimplementedFunc),
|
||||
/* 379 */ SyscallDesc("readahead", unimplementedFunc),
|
||||
/* 380 */ SyscallDesc("security", unimplementedFunc),
|
||||
|
|
|
@ -260,7 +260,7 @@ static SyscallDesc syscallDescs32[] = {
|
|||
/* 138 */ SyscallDesc("setfsuid", unimplementedFunc),
|
||||
/* 139 */ SyscallDesc("setfsgid", unimplementedFunc),
|
||||
/* 140 */ SyscallDesc("llseek", _llseekFunc),
|
||||
/* 141 */ SyscallDesc("getdents", getdentsFunc),
|
||||
/* 141 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 142 */ SyscallDesc("newselect", unimplementedFunc),
|
||||
/* 143 */ SyscallDesc("flock", unimplementedFunc),
|
||||
/* 144 */ SyscallDesc("msync", unimplementedFunc),
|
||||
|
@ -336,7 +336,7 @@ static SyscallDesc syscallDescs32[] = {
|
|||
/* 214 */ SyscallDesc("setgid", unimplementedFunc),
|
||||
/* 215 */ SyscallDesc("setfsuid", unimplementedFunc),
|
||||
/* 216 */ SyscallDesc("setfsgid", unimplementedFunc),
|
||||
/* 217 */ SyscallDesc("getdents64", getdents64Func),
|
||||
/* 217 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 218 */ SyscallDesc("pivot_root", unimplementedFunc),
|
||||
/* 219 */ SyscallDesc("mincore", unimplementedFunc),
|
||||
/* 220 */ SyscallDesc("madvise", unimplementedFunc),
|
||||
|
|
|
@ -277,7 +277,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
|||
/* 138 */ SyscallDesc("setfsuid", unimplementedFunc),
|
||||
/* 139 */ SyscallDesc("setfsgid", unimplementedFunc),
|
||||
/* 140 */ SyscallDesc("llseek", unimplementedFunc),
|
||||
/* 141 */ SyscallDesc("getdents", getdentsFunc),
|
||||
/* 141 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 142 */ SyscallDesc("newselect", unimplementedFunc),
|
||||
/* 143 */ SyscallDesc("flock", unimplementedFunc),
|
||||
/* 144 */ SyscallDesc("msync", unimplementedFunc),
|
||||
|
@ -355,7 +355,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
|||
/* 216 */ SyscallDesc("pivot_root", unimplementedFunc),
|
||||
/* 217 */ SyscallDesc("mincore", unimplementedFunc),
|
||||
/* 218 */ SyscallDesc("madvise", unimplementedFunc),
|
||||
/* 219 */ SyscallDesc("getdents64", getdents64Func),
|
||||
/* 219 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 220 */ SyscallDesc("fcntl64", fcntl64Func),
|
||||
/* 221 */ SyscallDesc("reserved#221", unimplementedFunc),
|
||||
/* 222 */ SyscallDesc("gettid", unimplementedFunc),
|
||||
|
|
|
@ -205,7 +205,7 @@ SyscallDesc PowerLinuxProcess::syscallDescs[] = {
|
|||
/* 138 */ SyscallDesc("setfsuid", unimplementedFunc),
|
||||
/* 139 */ SyscallDesc("setfsgid", unimplementedFunc),
|
||||
/* 140 */ SyscallDesc("llseek", _llseekFunc),
|
||||
/* 141 */ SyscallDesc("getdents", getdentsFunc),
|
||||
/* 141 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 142 */ SyscallDesc("newselect", unimplementedFunc),
|
||||
/* 143 */ SyscallDesc("flock", unimplementedFunc),
|
||||
/* 144 */ SyscallDesc("msync", unimplementedFunc),
|
||||
|
@ -281,7 +281,7 @@ SyscallDesc PowerLinuxProcess::syscallDescs[] = {
|
|||
/* 214 */ SyscallDesc("setgid", unimplementedFunc),
|
||||
/* 215 */ SyscallDesc("setfsuid", unimplementedFunc),
|
||||
/* 216 */ SyscallDesc("setfsgid", unimplementedFunc),
|
||||
/* 217 */ SyscallDesc("getdents64", getdents64Func),
|
||||
/* 217 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 218 */ SyscallDesc("pivot_root", unimplementedFunc),
|
||||
/* 219 */ SyscallDesc("mincore", unimplementedFunc),
|
||||
/* 220 */ SyscallDesc("madvise", unimplementedFunc),
|
||||
|
|
|
@ -241,7 +241,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
|
|||
/* 151 */ SyscallDesc("inotify_init", unimplementedFunc),
|
||||
/* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc),
|
||||
/* 153 */ SyscallDesc("poll", unimplementedFunc),
|
||||
/* 154 */ SyscallDesc("getdents64", getdents64Func),
|
||||
/* 154 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 155 */ SyscallDesc("fcntl64", unimplementedFunc),
|
||||
/* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc),
|
||||
/* 157 */ SyscallDesc("statfs", unimplementedFunc),
|
||||
|
@ -261,7 +261,7 @@ SyscallDesc SparcLinuxProcess::syscall32Descs[] = {
|
|||
/* 171 */ SyscallDesc("fsetxattr", unimplementedFunc), // 32 bit
|
||||
/* 172 */ SyscallDesc("getxattr", unimplementedFunc),
|
||||
/* 173 */ SyscallDesc("lgetxattr", unimplementedFunc),
|
||||
/* 174 */ SyscallDesc("getdents", getdentsFunc),
|
||||
/* 174 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 175 */ SyscallDesc("setsid", unimplementedFunc),
|
||||
/* 176 */ SyscallDesc("fchdir", unimplementedFunc),
|
||||
/* 177 */ SyscallDesc("fgetxattr", unimplementedFunc), // 32 bit
|
||||
|
@ -547,7 +547,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
|
|||
/* 151 */ SyscallDesc("inotify_init", unimplementedFunc),
|
||||
/* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc),
|
||||
/* 153 */ SyscallDesc("poll", unimplementedFunc),
|
||||
/* 154 */ SyscallDesc("getdents64", getdents64Func),
|
||||
/* 154 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 155 */ SyscallDesc("fcntl64", unimplementedFunc),
|
||||
/* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc),
|
||||
/* 157 */ SyscallDesc("statfs", unimplementedFunc),
|
||||
|
@ -567,7 +567,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
|
|||
/* 171 */ SyscallDesc("fsetxattr", unimplementedFunc),
|
||||
/* 172 */ SyscallDesc("getxattr", unimplementedFunc),
|
||||
/* 173 */ SyscallDesc("lgetxattr", unimplementedFunc),
|
||||
/* 174 */ SyscallDesc("getdents", getdentsFunc),
|
||||
/* 174 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 175 */ SyscallDesc("setsid", unimplementedFunc),
|
||||
/* 176 */ SyscallDesc("fchdir", unimplementedFunc),
|
||||
/* 177 */ SyscallDesc("fgetxattr", unimplementedFunc),
|
||||
|
|
|
@ -296,7 +296,7 @@ static SyscallDesc syscallDescs64[] = {
|
|||
/* 75 */ SyscallDesc("fdatasync", unimplementedFunc),
|
||||
/* 76 */ SyscallDesc("truncate", truncateFunc),
|
||||
/* 77 */ SyscallDesc("ftruncate", ftruncateFunc),
|
||||
/* 78 */ SyscallDesc("getdents", getdentsFunc),
|
||||
/* 78 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 79 */ SyscallDesc("getcwd", getcwdFunc),
|
||||
/* 80 */ SyscallDesc("chdir", unimplementedFunc),
|
||||
/* 81 */ SyscallDesc("fchdir", unimplementedFunc),
|
||||
|
@ -435,7 +435,7 @@ static SyscallDesc syscallDescs64[] = {
|
|||
/* 214 */ SyscallDesc("epoll_ctl_old", unimplementedFunc),
|
||||
/* 215 */ SyscallDesc("epoll_wait_old", unimplementedFunc),
|
||||
/* 216 */ SyscallDesc("remap_file_pages", unimplementedFunc),
|
||||
/* 217 */ SyscallDesc("getdents64", getdents64Func),
|
||||
/* 217 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 218 */ SyscallDesc("set_tid_address", unimplementedFunc),
|
||||
/* 219 */ SyscallDesc("restart_syscall", unimplementedFunc),
|
||||
/* 220 */ SyscallDesc("semtimedop", unimplementedFunc),
|
||||
|
|
|
@ -46,6 +46,12 @@ class Process(SimObject):
|
|||
def export_methods(cls, code):
|
||||
code('bool map(Addr vaddr, Addr paddr, int size);')
|
||||
|
||||
class EmulatedDriver(SimObject):
|
||||
type = 'EmulatedDriver'
|
||||
cxx_header = "sim/emul_driver.hh"
|
||||
abstract = True
|
||||
filename = Param.String("device file name (under /dev)")
|
||||
|
||||
class LiveProcess(Process):
|
||||
type = 'LiveProcess'
|
||||
cxx_header = "sim/process.hh"
|
||||
|
@ -60,3 +66,5 @@ class LiveProcess(Process):
|
|||
pid = Param.Int(100, 'process id')
|
||||
ppid = Param.Int(99, 'parent process id')
|
||||
simpoint = Param.UInt64(0, 'simulation point at which to start simulation')
|
||||
drivers = VectorParam.EmulatedDriver([], 'Available emulated drivers')
|
||||
|
||||
|
|
90
src/sim/emul_driver.hh
Normal file
90
src/sim/emul_driver.hh
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Advanced Micro Devices, Inc.
|
||||
* All rights reserved
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Steve Reinhardt
|
||||
*/
|
||||
|
||||
#ifndef __SIM_EMUL_DRIVER_HH
|
||||
#define __SIM_EMUL_DRIVER_HH
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "params/EmulatedDriver.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
class LiveProcess;
|
||||
class ThreadContext;
|
||||
|
||||
/**
|
||||
* EmulatedDriver is an abstract base class for fake SE-mode device drivers.
|
||||
*
|
||||
* Specific drivers that allow applications to communicate with simulated
|
||||
* hardware inside gem5 can be created by deriving from this class and
|
||||
* overriding the abstract virtual methods.
|
||||
*
|
||||
* Currently only open() and ioctl() calls are supported, but other calls
|
||||
* (e.g., read(), write(), mmap()) could be added as needed.
|
||||
*/
|
||||
class EmulatedDriver : public SimObject
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* filename for opening this driver (under /dev)
|
||||
*/
|
||||
const std::string &filename;
|
||||
|
||||
public:
|
||||
EmulatedDriver(EmulatedDriverParams *p)
|
||||
: SimObject(p), filename(p->filename)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a match with this driver's filename.
|
||||
*/
|
||||
bool match(const std::string &s) const { return (s == filename); }
|
||||
|
||||
/**
|
||||
* Abstract method, invoked when the user program calls open() on
|
||||
* the device driver. The parameters are the same as those passed
|
||||
* to openFunc() (q.v.).
|
||||
* @return A newly allocated target fd, or -1 on error.
|
||||
*/
|
||||
virtual int open(LiveProcess *p, ThreadContext *tc,
|
||||
int mode, int flags) = 0;
|
||||
|
||||
/**
|
||||
* Abstract method, invoked when the user program calls ioctl() on
|
||||
* the file descriptor returned by a previous open(). The parameters
|
||||
* are the same as those passed in to ioctlFunc() (q.v.).
|
||||
* @return The return code for the ioctl, or the negation of the errno
|
||||
* (see the SyscallReturn class).
|
||||
*/
|
||||
virtual int ioctl(LiveProcess *p, ThreadContext *tc, unsigned req) = 0;
|
||||
};
|
||||
|
||||
#endif // __SIM_EMUL_DRIVER_HH
|
|
@ -278,7 +278,7 @@ Process::alloc_fd(int sim_fd, string filename, int flags, int mode, bool pipe)
|
|||
// find first free target fd
|
||||
for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) {
|
||||
Process::FdMap *fdo = &fd_map[free_fd];
|
||||
if (fdo->fd == -1) {
|
||||
if (fdo->fd == -1 && fdo->driver == NULL) {
|
||||
fdo->fd = sim_fd;
|
||||
fdo->filename = filename;
|
||||
fdo->mode = mode;
|
||||
|
@ -309,6 +309,7 @@ Process::free_fd(int tgt_fd)
|
|||
fdo->flags = 0;
|
||||
fdo->isPipe = false;
|
||||
fdo->readPipeSource = 0;
|
||||
fdo->driver = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -565,16 +566,14 @@ Process::map(Addr vaddr, Addr paddr, int size)
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
LiveProcess::LiveProcess(LiveProcessParams * params, ObjectFile *_objFile)
|
||||
LiveProcess::LiveProcess(LiveProcessParams *params, ObjectFile *_objFile)
|
||||
: Process(params), objFile(_objFile),
|
||||
argv(params->cmd), envp(params->env), cwd(params->cwd)
|
||||
argv(params->cmd), envp(params->env), cwd(params->cwd),
|
||||
__uid(params->uid), __euid(params->euid),
|
||||
__gid(params->gid), __egid(params->egid),
|
||||
__pid(params->pid), __ppid(params->ppid),
|
||||
drivers(params->drivers)
|
||||
{
|
||||
__uid = params->uid;
|
||||
__euid = params->euid;
|
||||
__gid = params->gid;
|
||||
__egid = params->egid;
|
||||
__pid = params->pid;
|
||||
__ppid = params->ppid;
|
||||
|
||||
// load up symbols, if any... these may be used for debugging or
|
||||
// profiling.
|
||||
|
@ -608,6 +607,19 @@ LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width)
|
|||
return getSyscallArg(tc, i);
|
||||
}
|
||||
|
||||
|
||||
EmulatedDriver *
|
||||
LiveProcess::findDriver(std::string filename)
|
||||
{
|
||||
for (EmulatedDriver *d : drivers) {
|
||||
if (d->match(filename))
|
||||
return d;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
LiveProcess *
|
||||
LiveProcess::create(LiveProcessParams * params)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,7 @@ struct LiveProcessParams;
|
|||
class SyscallDesc;
|
||||
class System;
|
||||
class ThreadContext;
|
||||
class EmulatedDriver;
|
||||
|
||||
template<class IntType>
|
||||
struct AuxVector
|
||||
|
@ -139,10 +140,11 @@ class Process : public SimObject
|
|||
bool isPipe;
|
||||
int readPipeSource;
|
||||
uint64_t fileOffset;
|
||||
EmulatedDriver *driver;
|
||||
|
||||
FdMap()
|
||||
: fd(-1), filename("NULL"), mode(0), flags(0),
|
||||
isPipe(false), readPipeSource(0), fileOffset(0)
|
||||
isPipe(false), readPipeSource(0), fileOffset(0), driver(NULL)
|
||||
{ }
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
|
@ -256,6 +258,9 @@ class LiveProcess : public Process
|
|||
uint64_t __pid;
|
||||
uint64_t __ppid;
|
||||
|
||||
// Emulated drivers available to this process
|
||||
std::vector<EmulatedDriver *> drivers;
|
||||
|
||||
public:
|
||||
|
||||
enum AuxiliaryVectorType {
|
||||
|
@ -325,6 +330,14 @@ class LiveProcess : public Process
|
|||
|
||||
virtual SyscallDesc *getDesc(int callnum) = 0;
|
||||
|
||||
/**
|
||||
* Find an emulated device driver.
|
||||
*
|
||||
* @param filename Name of the device (under /dev)
|
||||
* @return Pointer to driver object if found, else NULL
|
||||
*/
|
||||
EmulatedDriver *findDriver(std::string filename);
|
||||
|
||||
// this function is used to create the LiveProcess object, since
|
||||
// we can't tell which subclass of LiveProcess to use until we
|
||||
// open and look at the object file.
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
@ -72,10 +71,15 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc)
|
|||
|
||||
SyscallReturn retval = (*funcPtr)(this, callnum, process, tc);
|
||||
|
||||
DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n",
|
||||
curTick(), tc->getCpuPtr()->name(), name, retval.encodedValue());
|
||||
if (retval.needsRetry()) {
|
||||
DPRINTFS(SyscallVerbose, tc->getCpuPtr(), "syscall %s needs retry\n",
|
||||
name);
|
||||
} else {
|
||||
DPRINTFS(SyscallVerbose, tc->getCpuPtr(), "syscall %s returns %d\n",
|
||||
name, retval.encodedValue());
|
||||
}
|
||||
|
||||
if (!(flags & SyscallDesc::SuppressReturnValue))
|
||||
if (!(flags & SyscallDesc::SuppressReturnValue) && !retval.needsRetry())
|
||||
process->setSyscallReturn(tc, retval);
|
||||
}
|
||||
|
||||
|
@ -868,41 +872,6 @@ cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
}
|
||||
}
|
||||
|
||||
SyscallReturn
|
||||
getdentsFunc(SyscallDesc *desc, int num, LiveProcess *p,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
int index = 0;
|
||||
int fd = p->sim_fd(p->getSyscallArg(tc, index));
|
||||
Addr bufPtr = p->getSyscallArg(tc, index);
|
||||
int nbytes = p->getSyscallArg(tc, index);
|
||||
BufferArg bufArg(bufPtr, nbytes);
|
||||
|
||||
int bytes_read = syscall(SYS_getdents, fd, bufArg.bufferPtr(), nbytes);
|
||||
|
||||
if (bytes_read != -1)
|
||||
bufArg.copyOut(tc->getMemProxy());
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
SyscallReturn
|
||||
getdents64Func(SyscallDesc *desc, int num, LiveProcess *p,
|
||||
ThreadContext *tc)
|
||||
{
|
||||
int index = 0;
|
||||
int fd = p->sim_fd(p->getSyscallArg(tc, index));
|
||||
Addr bufPtr = p->getSyscallArg(tc, index);
|
||||
int nbytes = p->getSyscallArg(tc, index);
|
||||
BufferArg bufArg(bufPtr, nbytes);
|
||||
|
||||
int bytes_read = syscall(SYS_getdents64, fd, bufArg.bufferPtr(), nbytes);
|
||||
|
||||
if (bytes_read != -1)
|
||||
bufArg.copyOut(tc->getMemProxy());
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
SyscallReturn
|
||||
accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc,
|
||||
int index)
|
||||
|
|
|
@ -75,9 +75,10 @@
|
|||
#include "cpu/thread_context.hh"
|
||||
#include "debug/SyscallVerbose.hh"
|
||||
#include "mem/page_table.hh"
|
||||
#include "mem/se_translating_port_proxy.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
#include "sim/emul_driver.hh"
|
||||
#include "sim/process.hh"
|
||||
#include "sim/syscall_emul_buf.hh"
|
||||
#include "sim/syscallreturn.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
|
@ -116,73 +117,6 @@ class SyscallDesc {
|
|||
};
|
||||
|
||||
|
||||
class BaseBufferArg {
|
||||
|
||||
public:
|
||||
|
||||
BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
|
||||
{
|
||||
bufPtr = new uint8_t[size];
|
||||
// clear out buffer: in case we only partially populate this,
|
||||
// and then do a copyOut(), we want to make sure we don't
|
||||
// introduce any random junk into the simulated address space
|
||||
memset(bufPtr, 0, size);
|
||||
}
|
||||
|
||||
virtual ~BaseBufferArg() { delete [] bufPtr; }
|
||||
|
||||
//
|
||||
// copy data into simulator space (read from target memory)
|
||||
//
|
||||
virtual bool copyIn(SETranslatingPortProxy &memproxy)
|
||||
{
|
||||
memproxy.readBlob(addr, bufPtr, size);
|
||||
return true; // no EFAULT detection for now
|
||||
}
|
||||
|
||||
//
|
||||
// copy data out of simulator space (write to target memory)
|
||||
//
|
||||
virtual bool copyOut(SETranslatingPortProxy &memproxy)
|
||||
{
|
||||
memproxy.writeBlob(addr, bufPtr, size);
|
||||
return true; // no EFAULT detection for now
|
||||
}
|
||||
|
||||
protected:
|
||||
Addr addr;
|
||||
int size;
|
||||
uint8_t *bufPtr;
|
||||
};
|
||||
|
||||
|
||||
class BufferArg : public BaseBufferArg
|
||||
{
|
||||
public:
|
||||
BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
|
||||
void *bufferPtr() { return bufPtr; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class TypedBufferArg : public BaseBufferArg
|
||||
{
|
||||
public:
|
||||
// user can optionally specify a specific number of bytes to
|
||||
// allocate to deal with those structs that have variable-size
|
||||
// arrays at the end
|
||||
TypedBufferArg(Addr _addr, int _size = sizeof(T))
|
||||
: BaseBufferArg(_addr, _size)
|
||||
{ }
|
||||
|
||||
// type case
|
||||
operator T*() { return (T *)bufPtr; }
|
||||
|
||||
// dereference operators
|
||||
T &operator*() { return *((T *)bufPtr); }
|
||||
T* operator->() { return (T *)bufPtr; }
|
||||
T &operator[](int i) { return ((T *)bufPtr)[i]; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The following emulation functions are generic enough that they
|
||||
|
@ -439,14 +373,6 @@ futexFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
|
||||
}
|
||||
|
||||
/// Target getdents() handler.
|
||||
SyscallReturn getdentsFunc(SyscallDesc *desc, int num,
|
||||
LiveProcess *process, ThreadContext *tc);
|
||||
|
||||
/// Target getdents64() handler.
|
||||
SyscallReturn getdents64Func(SyscallDesc *desc, int num,
|
||||
LiveProcess *process, ThreadContext *tc);
|
||||
|
||||
|
||||
/// Pseudo Funcs - These functions use a different return convension,
|
||||
/// returning a second value in a register other than the normal return register
|
||||
|
@ -612,11 +538,17 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
|
||||
DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
|
||||
|
||||
if (fd < 0 || process->sim_fd(fd) < 0) {
|
||||
Process::FdMap *fdObj = process->sim_fd_obj(fd);
|
||||
|
||||
if (fdObj == NULL) {
|
||||
// doesn't map to any simulator fd: not a valid target fd
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (fdObj->driver != NULL) {
|
||||
return fdObj->driver->ioctl(process, tc, req);
|
||||
}
|
||||
|
||||
if (OS::isTtyReq(req)) {
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
@ -637,13 +569,6 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
process->getSyscallArg(tc, index)))
|
||||
return -EFAULT;
|
||||
|
||||
if (path == "/dev/sysdev0") {
|
||||
// This is a memory-mapped high-resolution timer device on Alpha.
|
||||
// We don't support it, so just punt.
|
||||
warn("Ignoring open(%s, ...)\n", path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int tgtFlags = process->getSyscallArg(tc, index);
|
||||
int mode = process->getSyscallArg(tc, index);
|
||||
int hostFlags = 0;
|
||||
|
@ -669,6 +594,26 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
|
|||
|
||||
DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
|
||||
|
||||
if (startswith(path, "/dev/")) {
|
||||
std::string filename = path.substr(strlen("/dev/"));
|
||||
if (filename == "sysdev0") {
|
||||
// This is a memory-mapped high-resolution timer device on Alpha.
|
||||
// We don't support it, so just punt.
|
||||
warn("Ignoring open(%s, ...)\n", path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
EmulatedDriver *drv = process->findDriver(filename);
|
||||
if (drv != NULL) {
|
||||
// the driver's open method will allocate a fd from the
|
||||
// process if necessary.
|
||||
return drv->open(process, tc, mode, hostFlags);
|
||||
}
|
||||
|
||||
// fall through here for pass through to host devices, such as
|
||||
// /dev/zero
|
||||
}
|
||||
|
||||
int fd;
|
||||
int local_errno;
|
||||
if (startswith(path, "/proc/") || startswith(path, "/system/") ||
|
||||
|
|
168
src/sim/syscall_emul_buf.hh
Normal file
168
src/sim/syscall_emul_buf.hh
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Steve Reinhardt
|
||||
*/
|
||||
|
||||
#ifndef __SIM_SYSCALL_EMUL_BUF_HH__
|
||||
#define __SIM_SYSCALL_EMUL_BUF_HH__
|
||||
|
||||
///
|
||||
/// @file syscall_emul_buf.hh
|
||||
///
|
||||
/// This file defines buffer classes used to handle pointer arguments
|
||||
/// in emulated syscalls.
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "base/types.hh"
|
||||
#include "mem/se_translating_port_proxy.hh"
|
||||
|
||||
/**
|
||||
* Base class for BufferArg and TypedBufferArg, Not intended to be
|
||||
* used directly.
|
||||
*
|
||||
* The BufferArg classes represent buffers in target user space that
|
||||
* are passed by reference to an (emulated) system call. Each
|
||||
* instance provides an internal (simulator-space) buffer of the
|
||||
* appropriate size and tracks the user-space address. The copyIn()
|
||||
* and copyOut() methods copy the user-space buffer to and from the
|
||||
* simulator-space buffer, respectively.
|
||||
*/
|
||||
class BaseBufferArg {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Allocate a buffer of size 'size' representing the memory at
|
||||
* target address 'addr'.
|
||||
*/
|
||||
BaseBufferArg(Addr _addr, int _size)
|
||||
: addr(_addr), size(_size), bufPtr(new uint8_t[size])
|
||||
{
|
||||
// clear out buffer: in case we only partially populate this,
|
||||
// and then do a copyOut(), we want to make sure we don't
|
||||
// introduce any random junk into the simulated address space
|
||||
memset(bufPtr, 0, size);
|
||||
}
|
||||
|
||||
~BaseBufferArg() { delete [] bufPtr; }
|
||||
|
||||
/**
|
||||
* copy data into simulator space (read from target memory)
|
||||
*/
|
||||
bool copyIn(SETranslatingPortProxy &memproxy)
|
||||
{
|
||||
memproxy.readBlob(addr, bufPtr, size);
|
||||
return true; // no EFAULT detection for now
|
||||
}
|
||||
|
||||
/**
|
||||
* copy data out of simulator space (write to target memory)
|
||||
*/
|
||||
bool copyOut(SETranslatingPortProxy &memproxy)
|
||||
{
|
||||
memproxy.writeBlob(addr, bufPtr, size);
|
||||
return true; // no EFAULT detection for now
|
||||
}
|
||||
|
||||
protected:
|
||||
const Addr addr; ///< address of buffer in target address space
|
||||
const int size; ///< buffer size
|
||||
uint8_t * const bufPtr; ///< pointer to buffer in simulator space
|
||||
};
|
||||
|
||||
/**
|
||||
* BufferArg represents an untyped buffer in target user space that is
|
||||
* passed by reference to an (emulated) system call.
|
||||
*/
|
||||
class BufferArg : public BaseBufferArg
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Allocate a buffer of size 'size' representing the memory at
|
||||
* target address 'addr'.
|
||||
*/
|
||||
BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
|
||||
|
||||
/**
|
||||
* Return a pointer to the internal simulator-space buffer.
|
||||
*/
|
||||
void *bufferPtr() { return bufPtr; }
|
||||
};
|
||||
|
||||
/**
|
||||
* TypedBufferArg is a class template; instances of this template
|
||||
* represent typed buffers in target user space that are passed by
|
||||
* reference to an (emulated) system call.
|
||||
*
|
||||
* This template provides operator overloads for convenience, allowing
|
||||
* for example the use of '->' to reference fields within a struct
|
||||
* type.
|
||||
*/
|
||||
template <class T>
|
||||
class TypedBufferArg : public BaseBufferArg
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Allocate a buffer of type T representing the memory at target
|
||||
* address 'addr'. The user can optionally specify a specific
|
||||
* number of bytes to allocate to deal with structs that have
|
||||
* variable-size arrays at the end.
|
||||
*/
|
||||
TypedBufferArg(Addr _addr, int _size = sizeof(T))
|
||||
: BaseBufferArg(_addr, _size)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Convert TypedBufferArg<T> to a pointer to T that points to the
|
||||
* internal buffer.
|
||||
*/
|
||||
operator T*() { return (T *)bufPtr; }
|
||||
|
||||
/**
|
||||
* Convert TypedBufferArg<T> to a reference to T that references the
|
||||
* internal buffer value.
|
||||
*/
|
||||
T &operator*() { return *((T *)bufPtr); }
|
||||
|
||||
|
||||
/**
|
||||
* Enable the use of '->' to reference fields where T is a struct
|
||||
* type.
|
||||
*/
|
||||
T* operator->() { return (T *)bufPtr; }
|
||||
|
||||
/**
|
||||
* Enable the use of '[]' to reference fields where T is an array
|
||||
* type.
|
||||
*/
|
||||
T &operator[](int i) { return ((T *)bufPtr)[i]; }
|
||||
};
|
||||
|
||||
|
||||
#endif // __SIM_SYSCALL_EMUL_BUF_HH__
|
|
@ -64,9 +64,17 @@ class SyscallReturn
|
|||
/// value is expected, e.g., as the return value from a system
|
||||
/// call emulation function ('return 0;' or 'return -EFAULT;').
|
||||
SyscallReturn(int64_t v)
|
||||
: value(v)
|
||||
: value(v), retryFlag(false)
|
||||
{}
|
||||
|
||||
/// Pseudo-constructor to create an instance with the retry flag set.
|
||||
static SyscallReturn retry()
|
||||
{
|
||||
SyscallReturn s(0);
|
||||
s.retryFlag = true;
|
||||
return s;
|
||||
}
|
||||
|
||||
~SyscallReturn() {}
|
||||
|
||||
/// Was the system call successful?
|
||||
|
@ -75,6 +83,9 @@ class SyscallReturn
|
|||
return (value >= 0 || value <= -4096);
|
||||
}
|
||||
|
||||
/// Does the syscall need to be retried?
|
||||
bool needsRetry() const { return retryFlag; }
|
||||
|
||||
/// The return value
|
||||
int64_t returnValue() const
|
||||
{
|
||||
|
@ -98,6 +109,8 @@ class SyscallReturn
|
|||
private:
|
||||
|
||||
int64_t value;
|
||||
|
||||
bool retryFlag;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue