sim-se: adding pipe2 syscall
pipe2 builds on top of the pipe syscall implementation by adding some extra flags for the files (to avoid have to make separate calls to fcntl). Change-Id: I88cf6f1387b9d14e60b33a32db412da9ed93a3e6 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/12310 Reviewed-by: Brandon Potter <Brandon.Potter@amd.com> Maintainer: Brandon Potter <Brandon.Potter@amd.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Brandon Potter
parent
361bc8b472
commit
20428d69da
@@ -483,7 +483,7 @@ static SyscallDesc syscallDescs64[] = {
|
||||
/* 218 */ SyscallDesc("set_tid_address", setTidAddressFunc),
|
||||
/* 219 */ SyscallDesc("restart_syscall", unimplementedFunc),
|
||||
/* 220 */ SyscallDesc("semtimedop", unimplementedFunc),
|
||||
/* 221 */ SyscallDesc("fadvise64", unimplementedFunc),
|
||||
/* 221 */ SyscallDesc("fadvise64", ignoreFunc),
|
||||
/* 222 */ SyscallDesc("timer_create", unimplementedFunc),
|
||||
/* 223 */ SyscallDesc("timer_settime", unimplementedFunc),
|
||||
/* 224 */ SyscallDesc("timer_gettime", unimplementedFunc),
|
||||
@@ -555,7 +555,7 @@ static SyscallDesc syscallDescs64[] = {
|
||||
/* 290 */ SyscallDesc("eventfd2", eventfdFunc<X86Linux64>),
|
||||
/* 291 */ SyscallDesc("epoll_create1", unimplementedFunc),
|
||||
/* 292 */ SyscallDesc("dup3", unimplementedFunc),
|
||||
/* 293 */ SyscallDesc("pipe2", unimplementedFunc),
|
||||
/* 293 */ SyscallDesc("pipe2", pipe2Func),
|
||||
/* 294 */ SyscallDesc("inotify_init1", unimplementedFunc),
|
||||
/* 295 */ SyscallDesc("preadv", unimplementedFunc),
|
||||
/* 296 */ SyscallDesc("pwritev", unimplementedFunc),
|
||||
|
||||
@@ -866,13 +866,18 @@ fcntl64Func(SyscallDesc *desc, int num, ThreadContext *tc)
|
||||
}
|
||||
|
||||
SyscallReturn
|
||||
pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
|
||||
pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudo_pipe,
|
||||
bool is_pipe2)
|
||||
{
|
||||
Addr tgt_addr = 0;
|
||||
int flags = 0;
|
||||
auto p = tc->getProcessPtr();
|
||||
if (!pseudoPipe) {
|
||||
if (!pseudo_pipe) {
|
||||
int index = 0;
|
||||
tgt_addr = p->getSyscallArg(tc, index);
|
||||
if (is_pipe2) {
|
||||
flags = p->getSyscallArg(tc, index);
|
||||
}
|
||||
}
|
||||
|
||||
int sim_fds[2], tgt_fds[2];
|
||||
@@ -884,10 +889,12 @@ pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
|
||||
auto rend = PipeFDEntry::EndType::read;
|
||||
auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
|
||||
tgt_fds[0] = p->fds->allocFD(rpfd);
|
||||
int sim_fd_rpfd = rpfd->getSimFD();
|
||||
|
||||
auto wend = PipeFDEntry::EndType::write;
|
||||
auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
|
||||
tgt_fds[1] = p->fds->allocFD(wpfd);
|
||||
int sim_fd_wpfd = wpfd->getSimFD();
|
||||
|
||||
/**
|
||||
* Now patch the read object to record the target file descriptor chosen
|
||||
@@ -899,7 +906,7 @@ pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
|
||||
* Alpha Linux convention for pipe() is that fd[0] is returned as
|
||||
* the return value of the function, and fd[1] is returned in r20.
|
||||
*/
|
||||
if (pseudoPipe) {
|
||||
if (pseudo_pipe) {
|
||||
tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
|
||||
return tgt_fds[0];
|
||||
}
|
||||
@@ -913,6 +920,45 @@ pipeImpl(SyscallDesc *desc, int callnum, ThreadContext *tc, bool pseudoPipe)
|
||||
buf_ptr[0] = tgt_fds[0];
|
||||
buf_ptr[1] = tgt_fds[1];
|
||||
tgt_handle.copyOut(tc->getVirtProxy());
|
||||
|
||||
// pipe2 has additional behavior if flags != 0
|
||||
if (is_pipe2 && flags) {
|
||||
// pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
|
||||
// if flags set to anything else, return EINVAL
|
||||
if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
|
||||
(flags != (O_CLOEXEC | O_NONBLOCK))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
If O_NONBLOCK is passed in as a flag to pipe2, set O_NONBLOCK file
|
||||
status flag for two new open file descriptors.
|
||||
*/
|
||||
if (flags & O_NONBLOCK) {
|
||||
/*
|
||||
O_NONBLOCK is set when the programmer wants to avoid a separate
|
||||
call(s) to fcntl in their code, so mirror the fcntl
|
||||
implementation for handling file descriptors -- rely on host to
|
||||
maintain file status flags.
|
||||
*/
|
||||
if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
|
||||
return -errno;
|
||||
}
|
||||
if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If O_CLOEXEC is passed in as a flag to pipe2, set close-on-exec
|
||||
(FD_CLOEXEC) file status flag for two new open file descriptors.
|
||||
*/
|
||||
if (flags & O_CLOEXEC) {
|
||||
rpfd->setCOE(true);
|
||||
wpfd->setCOE(true);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -928,6 +974,14 @@ pipeFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
|
||||
return pipeImpl(desc, callnum, tc, false);
|
||||
}
|
||||
|
||||
SyscallReturn
|
||||
pipe2Func(SyscallDesc *desc, int callnum, ThreadContext *tc)
|
||||
{
|
||||
// call pipeImpl since the only difference between pipe and pipe2 is
|
||||
// the flags values and what they do (at the end of pipeImpl)
|
||||
return pipeImpl(desc, callnum, tc, false, true);
|
||||
}
|
||||
|
||||
SyscallReturn
|
||||
setpgidFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
|
||||
{
|
||||
|
||||
@@ -252,7 +252,10 @@ SyscallReturn pipeFunc(SyscallDesc *desc, int num, ThreadContext *tc);
|
||||
|
||||
/// Internal pipe() handler.
|
||||
SyscallReturn pipeImpl(SyscallDesc *desc, int num, ThreadContext *tc,
|
||||
bool pseudoPipe);
|
||||
bool pseudo_pipe, bool is_pipe2=false);
|
||||
|
||||
/// Target pipe() handler.
|
||||
SyscallReturn pipe2Func(SyscallDesc *desc, int num, ThreadContext *tc);
|
||||
|
||||
/// Target getpid() handler.
|
||||
SyscallReturn getpidFunc(SyscallDesc *desc, int num, ThreadContext *tc);
|
||||
|
||||
Reference in New Issue
Block a user