syscall_emul.hh (2665:a124942bacb8) syscall_emul.hh (2680:246e7104f744)
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 40 unchanged lines hidden (view full) ---

49#include <sys/uio.h>
50
51#include "arch/isa_traits.hh" // for Addr
52#include "base/chunk_generator.hh"
53#include "base/intmath.hh" // for RoundUp
54#include "base/misc.hh"
55#include "base/trace.hh"
56#include "cpu/base.hh"
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

--- 40 unchanged lines hidden (view full) ---

49#include <sys/uio.h>
50
51#include "arch/isa_traits.hh" // for Addr
52#include "base/chunk_generator.hh"
53#include "base/intmath.hh" // for RoundUp
54#include "base/misc.hh"
55#include "base/trace.hh"
56#include "cpu/base.hh"
57#include "cpu/exec_context.hh"
57#include "cpu/thread_context.hh"
58#include "mem/translating_port.hh"
59#include "mem/page_table.hh"
60#include "sim/process.hh"
61
62///
63/// System call descriptor.
64///
65class SyscallDesc {
66
67 public:
68
69 /// Typedef for target syscall handler functions.
70 typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
58#include "mem/translating_port.hh"
59#include "mem/page_table.hh"
60#include "sim/process.hh"
61
62///
63/// System call descriptor.
64///
65class SyscallDesc {
66
67 public:
68
69 /// Typedef for target syscall handler functions.
70 typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
71 Process *, ExecContext *);
71 Process *, ThreadContext *);
72
73 const char *name; //!< Syscall name (e.g., "open").
74 FuncPtr funcPtr; //!< Pointer to emulation function.
75 int flags; //!< Flags (see Flags enum).
76
77 /// Flag values for controlling syscall behavior.
78 enum Flags {
79 /// Don't set return regs according to funcPtr return value.
80 /// Used for syscalls with non-standard return conventions
72
73 const char *name; //!< Syscall name (e.g., "open").
74 FuncPtr funcPtr; //!< Pointer to emulation function.
75 int flags; //!< Flags (see Flags enum).
76
77 /// Flag values for controlling syscall behavior.
78 enum Flags {
79 /// Don't set return regs according to funcPtr return value.
80 /// Used for syscalls with non-standard return conventions
81 /// that explicitly set the ExecContext regs (e.g.,
81 /// that explicitly set the ThreadContext regs (e.g.,
82 /// sigreturn).
83 SuppressReturnValue = 1
84 };
85
86 /// Constructor.
87 SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
88 : name(_name), funcPtr(_funcPtr), flags(_flags)
89 {
90 }
91
92 /// Emulate the syscall. Public interface for calling through funcPtr.
82 /// sigreturn).
83 SuppressReturnValue = 1
84 };
85
86 /// Constructor.
87 SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
88 : name(_name), funcPtr(_funcPtr), flags(_flags)
89 {
90 }
91
92 /// Emulate the syscall. Public interface for calling through funcPtr.
93 void doSyscall(int callnum, Process *proc, ExecContext *xc);
93 void doSyscall(int callnum, Process *proc, ThreadContext *tc);
94};
95
96
97class BaseBufferArg {
98
99 public:
100
101 BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)

--- 65 unchanged lines hidden (view full) ---

167// don't need to be recompiled for different emulated OS's. They are
168// defined in sim/syscall_emul.cc.
169//
170//////////////////////////////////////////////////////////////////////
171
172
173/// Handler for unimplemented syscalls that we haven't thought about.
174SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
94};
95
96
97class BaseBufferArg {
98
99 public:
100
101 BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)

--- 65 unchanged lines hidden (view full) ---

167// don't need to be recompiled for different emulated OS's. They are
168// defined in sim/syscall_emul.cc.
169//
170//////////////////////////////////////////////////////////////////////
171
172
173/// Handler for unimplemented syscalls that we haven't thought about.
174SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
175 Process *p, ExecContext *xc);
175 Process *p, ThreadContext *tc);
176
177/// Handler for unimplemented syscalls that we never intend to
178/// implement (signal handling, etc.) and should not affect the correct
179/// behavior of the program. Print a warning only if the appropriate
180/// trace flag is enabled. Return success to the target program.
181SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
176
177/// Handler for unimplemented syscalls that we never intend to
178/// implement (signal handling, etc.) and should not affect the correct
179/// behavior of the program. Print a warning only if the appropriate
180/// trace flag is enabled. Return success to the target program.
181SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
182 Process *p, ExecContext *xc);
182 Process *p, ThreadContext *tc);
183
184/// Target exit() handler: terminate simulation.
185SyscallReturn exitFunc(SyscallDesc *desc, int num,
183
184/// Target exit() handler: terminate simulation.
185SyscallReturn exitFunc(SyscallDesc *desc, int num,
186 Process *p, ExecContext *xc);
186 Process *p, ThreadContext *tc);
187
188/// Target getpagesize() handler.
189SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
187
188/// Target getpagesize() handler.
189SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
190 Process *p, ExecContext *xc);
190 Process *p, ThreadContext *tc);
191
192/// Target obreak() handler: set brk address.
193SyscallReturn obreakFunc(SyscallDesc *desc, int num,
191
192/// Target obreak() handler: set brk address.
193SyscallReturn obreakFunc(SyscallDesc *desc, int num,
194 Process *p, ExecContext *xc);
194 Process *p, ThreadContext *tc);
195
196/// Target close() handler.
197SyscallReturn closeFunc(SyscallDesc *desc, int num,
195
196/// Target close() handler.
197SyscallReturn closeFunc(SyscallDesc *desc, int num,
198 Process *p, ExecContext *xc);
198 Process *p, ThreadContext *tc);
199
200/// Target read() handler.
201SyscallReturn readFunc(SyscallDesc *desc, int num,
199
200/// Target read() handler.
201SyscallReturn readFunc(SyscallDesc *desc, int num,
202 Process *p, ExecContext *xc);
202 Process *p, ThreadContext *tc);
203
204/// Target write() handler.
205SyscallReturn writeFunc(SyscallDesc *desc, int num,
203
204/// Target write() handler.
205SyscallReturn writeFunc(SyscallDesc *desc, int num,
206 Process *p, ExecContext *xc);
206 Process *p, ThreadContext *tc);
207
208/// Target lseek() handler.
209SyscallReturn lseekFunc(SyscallDesc *desc, int num,
207
208/// Target lseek() handler.
209SyscallReturn lseekFunc(SyscallDesc *desc, int num,
210 Process *p, ExecContext *xc);
210 Process *p, ThreadContext *tc);
211
212/// Target munmap() handler.
213SyscallReturn munmapFunc(SyscallDesc *desc, int num,
211
212/// Target munmap() handler.
213SyscallReturn munmapFunc(SyscallDesc *desc, int num,
214 Process *p, ExecContext *xc);
214 Process *p, ThreadContext *tc);
215
216/// Target gethostname() handler.
217SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
215
216/// Target gethostname() handler.
217SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
218 Process *p, ExecContext *xc);
218 Process *p, ThreadContext *tc);
219
220/// Target unlink() handler.
221SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
219
220/// Target unlink() handler.
221SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
222 Process *p, ExecContext *xc);
222 Process *p, ThreadContext *tc);
223
224/// Target rename() handler.
225SyscallReturn renameFunc(SyscallDesc *desc, int num,
223
224/// Target rename() handler.
225SyscallReturn renameFunc(SyscallDesc *desc, int num,
226 Process *p, ExecContext *xc);
226 Process *p, ThreadContext *tc);
227
228
229/// Target truncate() handler.
230SyscallReturn truncateFunc(SyscallDesc *desc, int num,
227
228
229/// Target truncate() handler.
230SyscallReturn truncateFunc(SyscallDesc *desc, int num,
231 Process *p, ExecContext *xc);
231 Process *p, ThreadContext *tc);
232
233
234/// Target ftruncate() handler.
235SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
232
233
234/// Target ftruncate() handler.
235SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
236 Process *p, ExecContext *xc);
236 Process *p, ThreadContext *tc);
237
238
239/// Target chown() handler.
240SyscallReturn chownFunc(SyscallDesc *desc, int num,
237
238
239/// Target chown() handler.
240SyscallReturn chownFunc(SyscallDesc *desc, int num,
241 Process *p, ExecContext *xc);
241 Process *p, ThreadContext *tc);
242
243
244/// Target fchown() handler.
245SyscallReturn fchownFunc(SyscallDesc *desc, int num,
242
243
244/// Target fchown() handler.
245SyscallReturn fchownFunc(SyscallDesc *desc, int num,
246 Process *p, ExecContext *xc);
246 Process *p, ThreadContext *tc);
247
248/// Target fnctl() handler.
249SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
247
248/// Target fnctl() handler.
249SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
250 Process *process, ExecContext *xc);
250 Process *process, ThreadContext *tc);
251
252/// Target setuid() handler.
253SyscallReturn setuidFunc(SyscallDesc *desc, int num,
251
252/// Target setuid() handler.
253SyscallReturn setuidFunc(SyscallDesc *desc, int num,
254 Process *p, ExecContext *xc);
254 Process *p, ThreadContext *tc);
255
256/// Target getpid() handler.
257SyscallReturn getpidFunc(SyscallDesc *desc, int num,
255
256/// Target getpid() handler.
257SyscallReturn getpidFunc(SyscallDesc *desc, int num,
258 Process *p, ExecContext *xc);
258 Process *p, ThreadContext *tc);
259
260/// Target getuid() handler.
261SyscallReturn getuidFunc(SyscallDesc *desc, int num,
259
260/// Target getuid() handler.
261SyscallReturn getuidFunc(SyscallDesc *desc, int num,
262 Process *p, ExecContext *xc);
262 Process *p, ThreadContext *tc);
263
264/// Target getgid() handler.
265SyscallReturn getgidFunc(SyscallDesc *desc, int num,
263
264/// Target getgid() handler.
265SyscallReturn getgidFunc(SyscallDesc *desc, int num,
266 Process *p, ExecContext *xc);
266 Process *p, ThreadContext *tc);
267
268/// Target getppid() handler.
269SyscallReturn getppidFunc(SyscallDesc *desc, int num,
267
268/// Target getppid() handler.
269SyscallReturn getppidFunc(SyscallDesc *desc, int num,
270 Process *p, ExecContext *xc);
270 Process *p, ThreadContext *tc);
271
272/// Target geteuid() handler.
273SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
271
272/// Target geteuid() handler.
273SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
274 Process *p, ExecContext *xc);
274 Process *p, ThreadContext *tc);
275
276/// Target getegid() handler.
277SyscallReturn getegidFunc(SyscallDesc *desc, int num,
275
276/// Target getegid() handler.
277SyscallReturn getegidFunc(SyscallDesc *desc, int num,
278 Process *p, ExecContext *xc);
278 Process *p, ThreadContext *tc);
279
280
281
282/// Pseudo Funcs - These functions use a different return convension,
283/// returning a second value in a register other than the normal return register
284SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
279
280
281
282/// Pseudo Funcs - These functions use a different return convension,
283/// returning a second value in a register other than the normal return register
284SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
285 Process *process, ExecContext *xc);
285 Process *process, ThreadContext *tc);
286
287/// Target getpidPseudo() handler.
288SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
286
287/// Target getpidPseudo() handler.
288SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
289 Process *p, ExecContext *xc);
289 Process *p, ThreadContext *tc);
290
291/// Target getuidPseudo() handler.
292SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
290
291/// Target getuidPseudo() handler.
292SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
293 Process *p, ExecContext *xc);
293 Process *p, ThreadContext *tc);
294
295/// Target getgidPseudo() handler.
296SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
294
295/// Target getgidPseudo() handler.
296SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
297 Process *p, ExecContext *xc);
297 Process *p, ThreadContext *tc);
298
299
300/// This struct is used to build an target-OS-dependent table that
301/// maps the target's open() flags to the host open() flags.
302struct OpenFlagTransTable {
303 int tgtFlag; //!< Target system flag value.
304 int hostFlag; //!< Corresponding host system flag value.
305};

--- 27 unchanged lines hidden (view full) ---

333//////////////////////////////////////////////////////////////////////
334
335/// Target ioctl() handler. For the most part, programs call ioctl()
336/// only to find out if their stdout is a tty, to determine whether to
337/// do line or block buffering.
338template <class OS>
339SyscallReturn
340ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
298
299
300/// This struct is used to build an target-OS-dependent table that
301/// maps the target's open() flags to the host open() flags.
302struct OpenFlagTransTable {
303 int tgtFlag; //!< Target system flag value.
304 int hostFlag; //!< Corresponding host system flag value.
305};

--- 27 unchanged lines hidden (view full) ---

333//////////////////////////////////////////////////////////////////////
334
335/// Target ioctl() handler. For the most part, programs call ioctl()
336/// only to find out if their stdout is a tty, to determine whether to
337/// do line or block buffering.
338template <class OS>
339SyscallReturn
340ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
341 ExecContext *xc)
341 ThreadContext *tc)
342{
342{
343 int fd = xc->getSyscallArg(0);
344 unsigned req = xc->getSyscallArg(1);
343 int fd = tc->getSyscallArg(0);
344 unsigned req = tc->getSyscallArg(1);
345
346 DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
347
348 if (fd < 0 || process->sim_fd(fd) < 0) {
349 // doesn't map to any simulator fd: not a valid target fd
350 return -EBADF;
351 }
352

--- 5 unchanged lines hidden (view full) ---

358 case OS::TIOCSETC:
359 case OS::TIOCGETC:
360 case OS::TIOCGETS:
361 case OS::TIOCGETA:
362 return -ENOTTY;
363
364 default:
365 fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
345
346 DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
347
348 if (fd < 0 || process->sim_fd(fd) < 0) {
349 // doesn't map to any simulator fd: not a valid target fd
350 return -EBADF;
351 }
352

--- 5 unchanged lines hidden (view full) ---

358 case OS::TIOCSETC:
359 case OS::TIOCGETC:
360 case OS::TIOCGETS:
361 case OS::TIOCGETA:
362 return -ENOTTY;
363
364 default:
365 fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
366 fd, req, xc->readPC());
366 fd, req, tc->readPC());
367 }
368}
369
370/// Target open() handler.
371template <class OS>
372SyscallReturn
373openFunc(SyscallDesc *desc, int callnum, Process *process,
367 }
368}
369
370/// Target open() handler.
371template <class OS>
372SyscallReturn
373openFunc(SyscallDesc *desc, int callnum, Process *process,
374 ExecContext *xc)
374 ThreadContext *tc)
375{
376 std::string path;
377
375{
376 std::string path;
377
378 if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
378 if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
379 return -EFAULT;
380
381 if (path == "/dev/sysdev0") {
382 // This is a memory-mapped high-resolution timer device on Alpha.
383 // We don't support it, so just punt.
384 warn("Ignoring open(%s, ...)\n", path);
385 return -ENOENT;
386 }
387
379 return -EFAULT;
380
381 if (path == "/dev/sysdev0") {
382 // This is a memory-mapped high-resolution timer device on Alpha.
383 // We don't support it, so just punt.
384 warn("Ignoring open(%s, ...)\n", path);
385 return -ENOENT;
386 }
387
388 int tgtFlags = xc->getSyscallArg(1);
389 int mode = xc->getSyscallArg(2);
388 int tgtFlags = tc->getSyscallArg(1);
389 int mode = tc->getSyscallArg(2);
390 int hostFlags = 0;
391
392 // translate open flags
393 for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
394 if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
395 tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
396 hostFlags |= OS::openFlagTable[i].hostFlag;
397 }

--- 15 unchanged lines hidden (view full) ---

413 return (fd == -1) ? -errno : process->alloc_fd(fd);
414}
415
416
417/// Target chmod() handler.
418template <class OS>
419SyscallReturn
420chmodFunc(SyscallDesc *desc, int callnum, Process *process,
390 int hostFlags = 0;
391
392 // translate open flags
393 for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
394 if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
395 tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
396 hostFlags |= OS::openFlagTable[i].hostFlag;
397 }

--- 15 unchanged lines hidden (view full) ---

413 return (fd == -1) ? -errno : process->alloc_fd(fd);
414}
415
416
417/// Target chmod() handler.
418template <class OS>
419SyscallReturn
420chmodFunc(SyscallDesc *desc, int callnum, Process *process,
421 ExecContext *xc)
421 ThreadContext *tc)
422{
423 std::string path;
424
422{
423 std::string path;
424
425 if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
425 if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
426 return -EFAULT;
427
426 return -EFAULT;
427
428 uint32_t mode = xc->getSyscallArg(1);
428 uint32_t mode = tc->getSyscallArg(1);
429 mode_t hostMode = 0;
430
431 // XXX translate mode flags via OS::something???
432 hostMode = mode;
433
434 // do the chmod
435 int result = chmod(path.c_str(), hostMode);
436 if (result < 0)
437 return -errno;
438
439 return 0;
440}
441
442
443/// Target fchmod() handler.
444template <class OS>
445SyscallReturn
446fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
429 mode_t hostMode = 0;
430
431 // XXX translate mode flags via OS::something???
432 hostMode = mode;
433
434 // do the chmod
435 int result = chmod(path.c_str(), hostMode);
436 if (result < 0)
437 return -errno;
438
439 return 0;
440}
441
442
443/// Target fchmod() handler.
444template <class OS>
445SyscallReturn
446fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
447 ExecContext *xc)
447 ThreadContext *tc)
448{
448{
449 int fd = xc->getSyscallArg(0);
449 int fd = tc->getSyscallArg(0);
450 if (fd < 0 || process->sim_fd(fd) < 0) {
451 // doesn't map to any simulator fd: not a valid target fd
452 return -EBADF;
453 }
454
450 if (fd < 0 || process->sim_fd(fd) < 0) {
451 // doesn't map to any simulator fd: not a valid target fd
452 return -EBADF;
453 }
454
455 uint32_t mode = xc->getSyscallArg(1);
455 uint32_t mode = tc->getSyscallArg(1);
456 mode_t hostMode = 0;
457
458 // XXX translate mode flags via OS::someting???
459 hostMode = mode;
460
461 // do the fchmod
462 int result = fchmod(process->sim_fd(fd), hostMode);
463 if (result < 0)
464 return -errno;
465
466 return 0;
467}
468
469
470/// Target stat() handler.
471template <class OS>
472SyscallReturn
473statFunc(SyscallDesc *desc, int callnum, Process *process,
456 mode_t hostMode = 0;
457
458 // XXX translate mode flags via OS::someting???
459 hostMode = mode;
460
461 // do the fchmod
462 int result = fchmod(process->sim_fd(fd), hostMode);
463 if (result < 0)
464 return -errno;
465
466 return 0;
467}
468
469
470/// Target stat() handler.
471template <class OS>
472SyscallReturn
473statFunc(SyscallDesc *desc, int callnum, Process *process,
474 ExecContext *xc)
474 ThreadContext *tc)
475{
476 std::string path;
477
475{
476 std::string path;
477
478 if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
478 if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
479 return -EFAULT;
480
481 struct stat hostBuf;
482 int result = stat(path.c_str(), &hostBuf);
483
484 if (result < 0)
485 return -errno;
486
479 return -EFAULT;
480
481 struct stat hostBuf;
482 int result = stat(path.c_str(), &hostBuf);
483
484 if (result < 0)
485 return -errno;
486
487 OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
487 OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
488
489 return 0;
490}
491
492
493/// Target fstat64() handler.
494template <class OS>
495SyscallReturn
496fstat64Func(SyscallDesc *desc, int callnum, Process *process,
488
489 return 0;
490}
491
492
493/// Target fstat64() handler.
494template <class OS>
495SyscallReturn
496fstat64Func(SyscallDesc *desc, int callnum, Process *process,
497 ExecContext *xc)
497 ThreadContext *tc)
498{
498{
499 int fd = xc->getSyscallArg(0);
499 int fd = tc->getSyscallArg(0);
500 if (fd < 0 || process->sim_fd(fd) < 0) {
501 // doesn't map to any simulator fd: not a valid target fd
502 return -EBADF;
503 }
504
505#if BSD_HOST
506 struct stat hostBuf;
507 int result = fstat(process->sim_fd(fd), &hostBuf);
508#else
509 struct stat64 hostBuf;
510 int result = fstat64(process->sim_fd(fd), &hostBuf);
511#endif
512
513 if (result < 0)
514 return -errno;
515
500 if (fd < 0 || process->sim_fd(fd) < 0) {
501 // doesn't map to any simulator fd: not a valid target fd
502 return -EBADF;
503 }
504
505#if BSD_HOST
506 struct stat hostBuf;
507 int result = fstat(process->sim_fd(fd), &hostBuf);
508#else
509 struct stat64 hostBuf;
510 int result = fstat64(process->sim_fd(fd), &hostBuf);
511#endif
512
513 if (result < 0)
514 return -errno;
515
516 OS::copyOutStat64Buf(xc->getMemPort(), fd, xc->getSyscallArg(1), &hostBuf);
516 OS::copyOutStat64Buf(tc->getMemPort(), fd, tc->getSyscallArg(1), &hostBuf);
517
518 return 0;
519}
520
521
522/// Target lstat() handler.
523template <class OS>
524SyscallReturn
525lstatFunc(SyscallDesc *desc, int callnum, Process *process,
517
518 return 0;
519}
520
521
522/// Target lstat() handler.
523template <class OS>
524SyscallReturn
525lstatFunc(SyscallDesc *desc, int callnum, Process *process,
526 ExecContext *xc)
526 ThreadContext *tc)
527{
528 std::string path;
529
527{
528 std::string path;
529
530 if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
530 if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
531 return -EFAULT;
532
533 struct stat hostBuf;
534 int result = lstat(path.c_str(), &hostBuf);
535
536 if (result < 0)
537 return -errno;
538
531 return -EFAULT;
532
533 struct stat hostBuf;
534 int result = lstat(path.c_str(), &hostBuf);
535
536 if (result < 0)
537 return -errno;
538
539 OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
539 OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
540
541 return 0;
542}
543
544/// Target lstat64() handler.
545template <class OS>
546SyscallReturn
547lstat64Func(SyscallDesc *desc, int callnum, Process *process,
540
541 return 0;
542}
543
544/// Target lstat64() handler.
545template <class OS>
546SyscallReturn
547lstat64Func(SyscallDesc *desc, int callnum, Process *process,
548 ExecContext *xc)
548 ThreadContext *tc)
549{
550 std::string path;
551
549{
550 std::string path;
551
552 if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
552 if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
553 return -EFAULT;
554
555#if BSD_HOST
556 struct stat hostBuf;
557 int result = lstat(path.c_str(), &hostBuf);
558#else
559 struct stat64 hostBuf;
560 int result = lstat64(path.c_str(), &hostBuf);
561#endif
562
563 if (result < 0)
564 return -errno;
565
553 return -EFAULT;
554
555#if BSD_HOST
556 struct stat hostBuf;
557 int result = lstat(path.c_str(), &hostBuf);
558#else
559 struct stat64 hostBuf;
560 int result = lstat64(path.c_str(), &hostBuf);
561#endif
562
563 if (result < 0)
564 return -errno;
565
566 OS::copyOutStat64Buf(xc->getMemPort(), -1, xc->getSyscallArg(1), &hostBuf);
566 OS::copyOutStat64Buf(tc->getMemPort(), -1, tc->getSyscallArg(1), &hostBuf);
567
568 return 0;
569}
570
571/// Target fstat() handler.
572template <class OS>
573SyscallReturn
574fstatFunc(SyscallDesc *desc, int callnum, Process *process,
567
568 return 0;
569}
570
571/// Target fstat() handler.
572template <class OS>
573SyscallReturn
574fstatFunc(SyscallDesc *desc, int callnum, Process *process,
575 ExecContext *xc)
575 ThreadContext *tc)
576{
576{
577 int fd = process->sim_fd(xc->getSyscallArg(0));
577 int fd = process->sim_fd(tc->getSyscallArg(0));
578
579 DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
580
581 if (fd < 0)
582 return -EBADF;
583
584 struct stat hostBuf;
585 int result = fstat(fd, &hostBuf);
586
587 if (result < 0)
588 return -errno;
589
578
579 DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
580
581 if (fd < 0)
582 return -EBADF;
583
584 struct stat hostBuf;
585 int result = fstat(fd, &hostBuf);
586
587 if (result < 0)
588 return -errno;
589
590 OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
590 OS::copyOutStatBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
591
592 return 0;
593}
594
595
596/// Target statfs() handler.
597template <class OS>
598SyscallReturn
599statfsFunc(SyscallDesc *desc, int callnum, Process *process,
591
592 return 0;
593}
594
595
596/// Target statfs() handler.
597template <class OS>
598SyscallReturn
599statfsFunc(SyscallDesc *desc, int callnum, Process *process,
600 ExecContext *xc)
600 ThreadContext *tc)
601{
602 std::string path;
603
601{
602 std::string path;
603
604 if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
604 if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
605 return -EFAULT;
606
607 struct statfs hostBuf;
608 int result = statfs(path.c_str(), &hostBuf);
609
610 if (result < 0)
611 return -errno;
612
605 return -EFAULT;
606
607 struct statfs hostBuf;
608 int result = statfs(path.c_str(), &hostBuf);
609
610 if (result < 0)
611 return -errno;
612
613 OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
613 OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
614
615 return 0;
616}
617
618
619/// Target fstatfs() handler.
620template <class OS>
621SyscallReturn
622fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
614
615 return 0;
616}
617
618
619/// Target fstatfs() handler.
620template <class OS>
621SyscallReturn
622fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
623 ExecContext *xc)
623 ThreadContext *tc)
624{
624{
625 int fd = process->sim_fd(xc->getSyscallArg(0));
625 int fd = process->sim_fd(tc->getSyscallArg(0));
626
627 if (fd < 0)
628 return -EBADF;
629
630 struct statfs hostBuf;
631 int result = fstatfs(fd, &hostBuf);
632
633 if (result < 0)
634 return -errno;
635
626
627 if (fd < 0)
628 return -EBADF;
629
630 struct statfs hostBuf;
631 int result = fstatfs(fd, &hostBuf);
632
633 if (result < 0)
634 return -errno;
635
636 OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
636 OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
637
638 return 0;
639}
640
641
642/// Target writev() handler.
643template <class OS>
644SyscallReturn
645writevFunc(SyscallDesc *desc, int callnum, Process *process,
637
638 return 0;
639}
640
641
642/// Target writev() handler.
643template <class OS>
644SyscallReturn
645writevFunc(SyscallDesc *desc, int callnum, Process *process,
646 ExecContext *xc)
646 ThreadContext *tc)
647{
647{
648 int fd = xc->getSyscallArg(0);
648 int fd = tc->getSyscallArg(0);
649 if (fd < 0 || process->sim_fd(fd) < 0) {
650 // doesn't map to any simulator fd: not a valid target fd
651 return -EBADF;
652 }
653
649 if (fd < 0 || process->sim_fd(fd) < 0) {
650 // doesn't map to any simulator fd: not a valid target fd
651 return -EBADF;
652 }
653
654 TranslatingPort *p = xc->getMemPort();
655 uint64_t tiov_base = xc->getSyscallArg(1);
656 size_t count = xc->getSyscallArg(2);
654 TranslatingPort *p = tc->getMemPort();
655 uint64_t tiov_base = tc->getSyscallArg(1);
656 size_t count = tc->getSyscallArg(2);
657 struct iovec hiov[count];
658 for (int i = 0; i < count; ++i)
659 {
660 typename OS::tgt_iovec tiov;
661
662 p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
663 (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
664 hiov[i].iov_len = gtoh(tiov.iov_len);

--- 25 unchanged lines hidden (view full) ---

690/// since this could be seriously broken if we're not mapping
691/// /dev/zero.
692//
693/// Someday we should explicitly check for /dev/zero in open, flag the
694/// file descriptor, and fail (or implement!) a non-anonymous mmap to
695/// anything else.
696template <class OS>
697SyscallReturn
657 struct iovec hiov[count];
658 for (int i = 0; i < count; ++i)
659 {
660 typename OS::tgt_iovec tiov;
661
662 p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
663 (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
664 hiov[i].iov_len = gtoh(tiov.iov_len);

--- 25 unchanged lines hidden (view full) ---

690/// since this could be seriously broken if we're not mapping
691/// /dev/zero.
692//
693/// Someday we should explicitly check for /dev/zero in open, flag the
694/// file descriptor, and fail (or implement!) a non-anonymous mmap to
695/// anything else.
696template <class OS>
697SyscallReturn
698mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
698mmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
699{
699{
700 Addr start = xc->getSyscallArg(0);
701 uint64_t length = xc->getSyscallArg(1);
702 // int prot = xc->getSyscallArg(2);
703 int flags = xc->getSyscallArg(3);
704 // int fd = p->sim_fd(xc->getSyscallArg(4));
705 // int offset = xc->getSyscallArg(5);
700 Addr start = tc->getSyscallArg(0);
701 uint64_t length = tc->getSyscallArg(1);
702 // int prot = tc->getSyscallArg(2);
703 int flags = tc->getSyscallArg(3);
704 // int fd = p->sim_fd(tc->getSyscallArg(4));
705 // int offset = tc->getSyscallArg(5);
706
707 if ((start % TheISA::VMPageSize) != 0 ||
708 (length % TheISA::VMPageSize) != 0) {
709 warn("mmap failing: arguments not page-aligned: "
710 "start 0x%x length 0x%x",
711 start, length);
712 return -EINVAL;
713 }

--- 5 unchanged lines hidden (view full) ---

719
720 // pick next address from our "mmap region"
721 start = p->mmap_end;
722 p->pTable->allocate(start, length);
723 p->mmap_end += length;
724
725 if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
726 warn("allowing mmap of file @ fd %d. "
706
707 if ((start % TheISA::VMPageSize) != 0 ||
708 (length % TheISA::VMPageSize) != 0) {
709 warn("mmap failing: arguments not page-aligned: "
710 "start 0x%x length 0x%x",
711 start, length);
712 return -EINVAL;
713 }

--- 5 unchanged lines hidden (view full) ---

719
720 // pick next address from our "mmap region"
721 start = p->mmap_end;
722 p->pTable->allocate(start, length);
723 p->mmap_end += length;
724
725 if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
726 warn("allowing mmap of file @ fd %d. "
727 "This will break if not /dev/zero.", xc->getSyscallArg(4));
727 "This will break if not /dev/zero.", tc->getSyscallArg(4));
728 }
729
730 return start;
731}
732
733/// Target getrlimit() handler.
734template <class OS>
735SyscallReturn
736getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
728 }
729
730 return start;
731}
732
733/// Target getrlimit() handler.
734template <class OS>
735SyscallReturn
736getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
737 ExecContext *xc)
737 ThreadContext *tc)
738{
738{
739 unsigned resource = xc->getSyscallArg(0);
740 TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
739 unsigned resource = tc->getSyscallArg(0);
740 TypedBufferArg<typename OS::rlimit> rlp(tc->getSyscallArg(1));
741
742 switch (resource) {
743 case OS::TGT_RLIMIT_STACK:
744 // max stack size in bytes: make up a number (2MB for now)
745 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
746 rlp->rlim_cur = htog(rlp->rlim_cur);
747 rlp->rlim_max = htog(rlp->rlim_max);
748 break;
749
750 default:
751 std::cerr << "getrlimitFunc: unimplemented resource " << resource
752 << std::endl;
753 abort();
754 break;
755 }
756
741
742 switch (resource) {
743 case OS::TGT_RLIMIT_STACK:
744 // max stack size in bytes: make up a number (2MB for now)
745 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
746 rlp->rlim_cur = htog(rlp->rlim_cur);
747 rlp->rlim_max = htog(rlp->rlim_max);
748 break;
749
750 default:
751 std::cerr << "getrlimitFunc: unimplemented resource " << resource
752 << std::endl;
753 abort();
754 break;
755 }
756
757 rlp.copyOut(xc->getMemPort());
757 rlp.copyOut(tc->getMemPort());
758 return 0;
759}
760
761/// Target gettimeofday() handler.
762template <class OS>
763SyscallReturn
764gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
758 return 0;
759}
760
761/// Target gettimeofday() handler.
762template <class OS>
763SyscallReturn
764gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
765 ExecContext *xc)
765 ThreadContext *tc)
766{
766{
767 TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
767 TypedBufferArg<typename OS::timeval> tp(tc->getSyscallArg(0));
768
769 getElapsedTime(tp->tv_sec, tp->tv_usec);
770 tp->tv_sec += seconds_since_epoch;
771 tp->tv_sec = htog(tp->tv_sec);
772 tp->tv_usec = htog(tp->tv_usec);
773
768
769 getElapsedTime(tp->tv_sec, tp->tv_usec);
770 tp->tv_sec += seconds_since_epoch;
771 tp->tv_sec = htog(tp->tv_sec);
772 tp->tv_usec = htog(tp->tv_usec);
773
774 tp.copyOut(xc->getMemPort());
774 tp.copyOut(tc->getMemPort());
775
776 return 0;
777}
778
779
780/// Target utimes() handler.
781template <class OS>
782SyscallReturn
783utimesFunc(SyscallDesc *desc, int callnum, Process *process,
775
776 return 0;
777}
778
779
780/// Target utimes() handler.
781template <class OS>
782SyscallReturn
783utimesFunc(SyscallDesc *desc, int callnum, Process *process,
784 ExecContext *xc)
784 ThreadContext *tc)
785{
786 std::string path;
787
785{
786 std::string path;
787
788 if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
788 if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
789 return -EFAULT;
790
789 return -EFAULT;
790
791 TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
792 tp.copyIn(xc->getMemPort());
791 TypedBufferArg<typename OS::timeval [2]> tp(tc->getSyscallArg(1));
792 tp.copyIn(tc->getMemPort());
793
794 struct timeval hostTimeval[2];
795 for (int i = 0; i < 2; ++i)
796 {
797 hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
798 hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
799 }
800 int result = utimes(path.c_str(), hostTimeval);
801
802 if (result < 0)
803 return -errno;
804
805 return 0;
806}
807/// Target getrusage() function.
808template <class OS>
809SyscallReturn
810getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
793
794 struct timeval hostTimeval[2];
795 for (int i = 0; i < 2; ++i)
796 {
797 hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
798 hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
799 }
800 int result = utimes(path.c_str(), hostTimeval);
801
802 if (result < 0)
803 return -errno;
804
805 return 0;
806}
807/// Target getrusage() function.
808template <class OS>
809SyscallReturn
810getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
811 ExecContext *xc)
811 ThreadContext *tc)
812{
812{
813 int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN
814 TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
813 int who = tc->getSyscallArg(0); // THREAD, SELF, or CHILDREN
814 TypedBufferArg<typename OS::rusage> rup(tc->getSyscallArg(1));
815
816 if (who != OS::TGT_RUSAGE_SELF) {
817 // don't really handle THREAD or CHILDREN, but just warn and
818 // plow ahead
819 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
820 who);
821 }
822

--- 13 unchanged lines hidden (view full) ---

836 rup->ru_inblock = 0;
837 rup->ru_oublock = 0;
838 rup->ru_msgsnd = 0;
839 rup->ru_msgrcv = 0;
840 rup->ru_nsignals = 0;
841 rup->ru_nvcsw = 0;
842 rup->ru_nivcsw = 0;
843
815
816 if (who != OS::TGT_RUSAGE_SELF) {
817 // don't really handle THREAD or CHILDREN, but just warn and
818 // plow ahead
819 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
820 who);
821 }
822

--- 13 unchanged lines hidden (view full) ---

836 rup->ru_inblock = 0;
837 rup->ru_oublock = 0;
838 rup->ru_msgsnd = 0;
839 rup->ru_msgrcv = 0;
840 rup->ru_nsignals = 0;
841 rup->ru_nvcsw = 0;
842 rup->ru_nivcsw = 0;
843
844 rup.copyOut(xc->getMemPort());
844 rup.copyOut(tc->getMemPort());
845
846 return 0;
847}
848
849
850
851
852#endif // __SIM_SYSCALL_EMUL_HH__
845
846 return 0;
847}
848
849
850
851
852#endif // __SIM_SYSCALL_EMUL_HH__