Skip to content

Commit

Permalink
Add getrusage and wait4 syscall shims.
Browse files Browse the repository at this point in the history
  • Loading branch information
staceyson committed Oct 9, 2012
1 parent 7ddc530 commit 3f304df
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 5 deletions.
1 change: 1 addition & 0 deletions work/qemu-1.2.0/bsd-user/qemu.h
Expand Up @@ -192,6 +192,7 @@ void signal_init(void);
int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
int host_to_target_signal(int sig);
long do_sigreturn(CPUArchState *env);
long do_rt_sigreturn(CPUArchState *env);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
Expand Down
3 changes: 1 addition & 2 deletions work/qemu-1.2.0/bsd-user/signal.c
Expand Up @@ -94,10 +94,9 @@ static uint8_t target_to_host_signal_table[_NSIG];
static struct target_sigaction sigact_table[TARGET_NSIG];

static void host_signal_handler(int host_signum, siginfo_t *info, void *puc);
static int host_to_target_signal(int sig);
static int target_to_host_signal(int sig);

static int
int
host_to_target_signal(int sig)
{

Expand Down
83 changes: 80 additions & 3 deletions work/qemu-1.2.0/bsd-user/syscall.c
Expand Up @@ -35,6 +35,7 @@
#include <sys/sysctl.h>
#include <sys/event.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <utime.h>

#include "qemu.h"
Expand Down Expand Up @@ -469,6 +470,54 @@ target_to_host_fcntl_cmd(int cmd)
}
}

static inline abi_long
host_to_target_rusage(abi_ulong target_addr, const struct rusage *rusage)
{
struct target_rusage *target_rusage;

if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
return (-TARGET_EFAULT);
target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
unlock_user_struct(target_rusage, target_addr, 1);

return (0);
}

/*
* Map host to target signal numbers for the wait family of syscalls.
* Assume all other status bits are the same.
*/
static int
host_to_target_waitstatus(int status)
{
if (WIFSIGNALED(status)) {
return (host_to_target_signal(WTERMSIG(status)) |
(status & ~0x7f));
}
if (WIFSTOPPED(status)) {
return (host_to_target_signal(WSTOPSIG(status)) << 8) |
(status & 0xff);
}
return (status);
}

static inline abi_long
fbsd_copy_from_user_timeval(struct timeval *tv, abi_ulong target_tv_addr)
{
Expand Down Expand Up @@ -1741,14 +1790,44 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
break;

case TARGET_FREEBSD_NR_getrusage:
{
struct rusage rusage;
ret = get_errno(getrusage(arg1, &rusage));
if (!is_error(ret))
host_to_target_rusage(arg2, &rusage);
}
break;

case TARGET_FREEBSD_NR_wait4:
{
int status;
abi_long status_ptr = arg2;
struct rusage rusage, *rusage_ptr;
abi_ulong target_rusage = arg4;

if (target_rusage)
rusage_ptr = &rusage;
else
rusage_ptr = NULL;
ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
if (!is_error(ret)) {
status = host_to_target_waitstatus(status);
if (put_user_s32(status, status_ptr))
goto efault;
if (target_rusage)
host_to_target_rusage(target_rusage, &rusage);
}
}
break;

case TARGET_FREEBSD_NR_kill:
case TARGET_FREEBSD_NR_sigaction:
case TARGET_FREEBSD_NR_sigprocmask:
case TARGET_FREEBSD_NR_sigpending:
case TARGET_FREEBSD_NR_sigsuspend:
case TARGET_FREEBSD_NR_sigreturn:

case TARGET_FREEBSD_NR_getrusage:

case TARGET_FREEBSD_NR_pselect:

Expand All @@ -1772,8 +1851,6 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
/* case TARGET_FREEBSD_NR_socket: */
case TARGET_FREEBSD_NR_socketpair:

case TARGET_FREEBSD_NR_wait4:

case TARGET_FREEBSD_NR_swapon:
case TARGET_FREEBSD_NR_swapoff:

Expand Down
19 changes: 19 additions & 0 deletions work/qemu-1.2.0/bsd-user/syscall_defs.h
Expand Up @@ -213,6 +213,25 @@ typedef struct {
abi_ulong sig[TARGET_NSIG_WORDS];
} target_sigset_t;

struct target_rusage {
struct target_timeval ru_utime; /* user time used */
struct target_timeval ru_stime; /* system time used */
abi_long ru_maxrss; /* maximum resident set size */
abi_long ru_ixrss; /* integral shared memory size */
abi_long ru_idrss; /* integral unshared data size */
abi_long ru_isrss; /* integral unshared stack size */
abi_long ru_minflt; /* page reclaims */
abi_long ru_majflt; /* page faults */
abi_long ru_nswap; /* swaps */
abi_long ru_inblock; /* block input operations */
abi_long ru_oublock; /* block output operations */
abi_long ru_msgsnd; /* messages sent */
abi_long ru_msgrcv; /* messages received */
abi_long ru_nsignals; /* signals received */
abi_long ru_nvcsw; /* voluntary context switches */
abi_long ru_nivcsw; /* involuntary context switches */
};

#ifdef BSWAP_NEEDED
static inline void
tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
Expand Down

0 comments on commit 3f304df

Please sign in to comment.