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__ |