aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2011-02-20 14:47:48 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-02-20 14:47:48 +0100
commit0899965f6841ff96fcfe1fd766e95216af96b33e (patch)
tree9ad1eb89378f50ff13bae169dfa6b1303d6b8813
parent64d7e9a421fea0ac50b44541f5521de455e7cd5d (diff)
parent80f5ce758ac277e76c016dd7c0b246e40d4fca2d (diff)
Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu
* 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu: linux-user: correct core dump format linux-user: Define target alignment size linux-user: Support the epoll syscalls linux-user: in linux-user/strace.c, tswap() is useless linux-user: add rmdir() strace
-rwxr-xr-xconfigure71
-rw-r--r--cpu-defs.h14
-rw-r--r--linux-user/elfload.c34
-rw-r--r--linux-user/strace.c91
-rw-r--r--linux-user/strace.list3
-rw-r--r--linux-user/syscall.c107
-rw-r--r--linux-user/syscall_defs.h13
7 files changed, 267 insertions, 66 deletions
diff --git a/configure b/configure
index a3f53456f4..fe00036dbd 100755
--- a/configure
+++ b/configure
@@ -2142,6 +2142,51 @@ if compile_prog "" "" ; then
dup3=yes
fi
+# check for epoll support
+epoll=no
+cat > $TMPC << EOF
+#include <sys/epoll.h>
+
+int main(void)
+{
+ epoll_create(0);
+ return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+ epoll=yes
+fi
+
+# epoll_create1 and epoll_pwait are later additions
+# so we must check separately for their presence
+epoll_create1=no
+cat > $TMPC << EOF
+#include <sys/epoll.h>
+
+int main(void)
+{
+ epoll_create1(0);
+ return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+ epoll_create1=yes
+fi
+
+epoll_pwait=no
+cat > $TMPC << EOF
+#include <sys/epoll.h>
+
+int main(void)
+{
+ epoll_pwait(0, 0, 0, 0, 0);
+ return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+ epoll_pwait=yes
+fi
+
# Check if tools are available to build documentation.
if test "$docs" != "no" ; then
if has makeinfo && has pod2man; then
@@ -2674,6 +2719,15 @@ fi
if test "$dup3" = "yes" ; then
echo "CONFIG_DUP3=y" >> $config_host_mak
fi
+if test "$epoll" = "yes" ; then
+ echo "CONFIG_EPOLL=y" >> $config_host_mak
+fi
+if test "$epoll_create1" = "yes" ; then
+ echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak
+fi
+if test "$epoll_pwait" = "yes" ; then
+ echo "CONFIG_EPOLL_PWAIT=y" >> $config_host_mak
+fi
if test "$inotify" = "yes" ; then
echo "CONFIG_INOTIFY=y" >> $config_host_mak
fi
@@ -2908,6 +2962,10 @@ target_nptl="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"`
echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
gdb_xml_files=""
+target_short_alignment=2
+target_int_alignment=4
+target_long_alignment=4
+target_llong_alignment=8
TARGET_ARCH="$target_arch2"
TARGET_BASE_ARCH=""
@@ -2920,9 +2978,11 @@ case "$target_arch2" in
x86_64)
TARGET_BASE_ARCH=i386
target_phys_bits=64
+ target_long_alignment=8
;;
alpha)
target_phys_bits=64
+ target_long_alignment=8
target_nptl="yes"
;;
arm|armeb)
@@ -2931,6 +2991,7 @@ case "$target_arch2" in
target_nptl="yes"
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
target_phys_bits=32
+ target_llong_alignment=4
;;
cris)
target_nptl="yes"
@@ -2940,6 +3001,9 @@ case "$target_arch2" in
bflt="yes"
gdb_xml_files="cf-core.xml cf-fp.xml"
target_phys_bits=32
+ target_int_alignment=2
+ target_long_alignment=2
+ target_llong_alignment=2
;;
microblaze)
bflt="yes"
@@ -2963,6 +3027,7 @@ case "$target_arch2" in
TARGET_BASE_ARCH=mips
echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
target_phys_bits=64
+ target_long_alignment=8
;;
ppc)
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
@@ -2981,6 +3046,7 @@ case "$target_arch2" in
TARGET_ABI_DIR=ppc
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_phys_bits=64
+ target_long_alignment=8
;;
ppc64abi32)
TARGET_ARCH=ppc64
@@ -3002,6 +3068,7 @@ case "$target_arch2" in
sparc64)
TARGET_BASE_ARCH=sparc
target_phys_bits=64
+ target_long_alignment=8
;;
sparc32plus)
TARGET_ARCH=sparc64
@@ -3018,6 +3085,10 @@ case "$target_arch2" in
exit 1
;;
esac
+echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
+echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
+echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
+echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak
echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak
target_arch_name="`echo $TARGET_ARCH | tr '[:lower:]' '[:upper:]'`"
echo "TARGET_$target_arch_name=y" >> $config_target_mak
diff --git a/cpu-defs.h b/cpu-defs.h
index db809ed465..2b59fa6fb0 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -37,16 +37,22 @@
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
+typedef int16_t target_short __attribute__ ((aligned(TARGET_SHORT_ALIGNMENT)));
+typedef uint16_t target_ushort __attribute__((aligned(TARGET_SHORT_ALIGNMENT)));
+typedef int32_t target_int __attribute__((aligned(TARGET_INT_ALIGNMENT)));
+typedef uint32_t target_uint __attribute__((aligned(TARGET_INT_ALIGNMENT)));
+typedef int64_t target_llong __attribute__((aligned(TARGET_LLONG_ALIGNMENT)));
+typedef uint64_t target_ullong __attribute__((aligned(TARGET_LLONG_ALIGNMENT)));
/* target_ulong is the type of a virtual address */
#if TARGET_LONG_SIZE == 4
-typedef int32_t target_long;
-typedef uint32_t target_ulong;
+typedef int32_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
+typedef uint32_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
#define TARGET_FMT_lx "%08x"
#define TARGET_FMT_ld "%d"
#define TARGET_FMT_lu "%u"
#elif TARGET_LONG_SIZE == 8
-typedef int64_t target_long;
-typedef uint64_t target_ulong;
+typedef int64_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
+typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
#define TARGET_FMT_lx "%016" PRIx64
#define TARGET_FMT_ld "%" PRId64
#define TARGET_FMT_lu "%" PRIu64
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2de83e4bfb..fe5410e6f9 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -103,13 +103,13 @@ enum {
typedef target_ulong target_elf_greg_t;
#ifdef USE_UID16
-typedef uint16_t target_uid_t;
-typedef uint16_t target_gid_t;
+typedef target_ushort target_uid_t;
+typedef target_ushort target_gid_t;
#else
-typedef uint32_t target_uid_t;
-typedef uint32_t target_gid_t;
+typedef target_uint target_uid_t;
+typedef target_uint target_gid_t;
#endif
-typedef int32_t target_pid_t;
+typedef target_int target_pid_t;
#ifdef TARGET_I386
@@ -1761,19 +1761,20 @@ struct memelfnote {
size_t namesz_rounded;
int type;
size_t datasz;
+ size_t datasz_rounded;
void *data;
size_t notesz;
};
struct target_elf_siginfo {
- int si_signo; /* signal number */
- int si_code; /* extra code */
- int si_errno; /* errno */
+ target_int si_signo; /* signal number */
+ target_int si_code; /* extra code */
+ target_int si_errno; /* errno */
};
struct target_elf_prstatus {
struct target_elf_siginfo pr_info; /* Info associated with signal */
- short pr_cursig; /* Current signal */
+ target_short pr_cursig; /* Current signal */
target_ulong pr_sigpend; /* XXX */
target_ulong pr_sighold; /* XXX */
target_pid_t pr_pid;
@@ -1785,7 +1786,7 @@ struct target_elf_prstatus {
struct target_timeval pr_cutime; /* XXX Cumulative user time */
struct target_timeval pr_cstime; /* XXX Cumulative system time */
target_elf_gregset_t pr_reg; /* GP registers */
- int pr_fpvalid; /* XXX */
+ target_int pr_fpvalid; /* XXX */
};
#define ELF_PRARGSZ (80) /* Number of chars for args */
@@ -2036,7 +2037,9 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
note->namesz = namesz;
note->namesz_rounded = roundup(namesz, sizeof (int32_t));
note->type = type;
- note->datasz = roundup(sz, sizeof (int32_t));;
+ note->datasz = sz;
+ note->datasz_rounded = roundup(sz, sizeof (int32_t));
+
note->data = data;
/*
@@ -2044,7 +2047,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
* ELF document.
*/
note->notesz = sizeof (struct elf_note) +
- note->namesz_rounded + note->datasz;
+ note->namesz_rounded + note->datasz_rounded;
}
static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
@@ -2264,7 +2267,7 @@ static int write_note(struct memelfnote *men, int fd)
return (-1);
if (dump_write(fd, men->name, men->namesz_rounded) != 0)
return (-1);
- if (dump_write(fd, men->data, men->datasz) != 0)
+ if (dump_write(fd, men->data, men->datasz_rounded) != 0)
return (-1);
return (0);
@@ -2480,7 +2483,7 @@ static int elf_core_dump(int signr, const CPUState *env)
* ELF specification wants data to start at page boundary so
* we align it here.
*/
- offset = roundup(offset, ELF_EXEC_PAGESIZE);
+ data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
/*
* Write program headers for memory regions mapped in
@@ -2503,6 +2506,7 @@ static int elf_core_dump(int signr, const CPUState *env)
phdr.p_flags |= PF_X;
phdr.p_align = ELF_EXEC_PAGESIZE;
+ bswap_phdr(&phdr, 1);
dump_write(fd, &phdr, sizeof (phdr));
}
@@ -2514,8 +2518,6 @@ static int elf_core_dump(int signr, const CPUState *env)
goto out;
/* align data to page boundary */
- data_offset = lseek(fd, 0, SEEK_CUR);
- data_offset = TARGET_PAGE_ALIGN(data_offset);
if (lseek(fd, data_offset, SEEK_SET) != data_offset)
goto out;
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 18366661cd..8dd398b9f2 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -441,14 +441,11 @@ get_comma(int last)
}
static void
-print_flags(const struct flags *f, abi_long tflags, int last)
+print_flags(const struct flags *f, abi_long flags, int last)
{
const char *sep = "";
- int flags;
int n;
- flags = (int)tswap32(tflags);
-
if ((flags == 0) && (f->f_value == 0)) {
gemu_log("%s%s", f->f_string, get_comma(last));
return;
@@ -465,36 +462,33 @@ print_flags(const struct flags *f, abi_long tflags, int last)
if (n > 0) {
/* print rest of the flags as numeric */
if (flags != 0) {
- gemu_log("%s%#x%s", sep, flags, get_comma(last));
+ gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last));
} else {
gemu_log("%s", get_comma(last));
}
} else {
/* no string version of flags found, print them in hex then */
- gemu_log("%#x%s", flags, get_comma(last));
+ gemu_log("%#x%s", (unsigned int)flags, get_comma(last));
}
}
static void
-print_at_dirfd(abi_long tdirfd, int last)
+print_at_dirfd(abi_long dirfd, int last)
{
- int dirfd = tswap32(tdirfd);
-
#ifdef AT_FDCWD
if (dirfd == AT_FDCWD) {
gemu_log("AT_FDCWD%s", get_comma(last));
return;
}
#endif
- gemu_log("%d%s", dirfd, get_comma(last));
+ gemu_log("%d%s", (int)dirfd, get_comma(last));
}
static void
-print_file_mode(abi_long tmode, int last)
+print_file_mode(abi_long mode, int last)
{
const char *sep = "";
const struct flags *m;
- mode_t mode = (mode_t)tswap32(tmode);
for (m = &mode_flags[0]; m->f_string != NULL; m++) {
if ((m->f_value & mode) == m->f_value) {
@@ -508,16 +502,14 @@ print_file_mode(abi_long tmode, int last)
mode &= ~S_IFMT;
/* print rest of the mode as octal */
if (mode != 0)
- gemu_log("%s%#o", sep, mode);
+ gemu_log("%s%#o", sep, (unsigned int)mode);
gemu_log("%s", get_comma(last));
}
static void
-print_open_flags(abi_long tflags, int last)
+print_open_flags(abi_long flags, int last)
{
- int flags = tswap32(tflags);
-
print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1);
flags &= ~TARGET_O_ACCMODE;
if (flags == 0) {
@@ -620,7 +612,7 @@ print_accept(const struct syscallname *name,
abi_long arg3, abi_long arg4, abi_long arg5)
{
print_syscall_prologue(name);
- print_raw_param("%d", tswap32(arg0), 0);
+ print_raw_param("%d", arg0, 0);
print_pointer(arg1, 0);
print_number(arg2, 1);
print_syscall_epilogue(name);
@@ -698,7 +690,7 @@ print_execv(const struct syscallname *name,
{
print_syscall_prologue(name);
print_string(arg0, 0);
- print_raw_param("0x" TARGET_ABI_FMT_lx, tswapl(arg1), 1);
+ print_raw_param("0x" TARGET_ABI_FMT_lx, arg1, 1);
print_syscall_epilogue(name);
}
#endif
@@ -742,13 +734,8 @@ print_fchownat(const struct syscallname *name,
print_syscall_prologue(name);
print_at_dirfd(arg0, 0);
print_string(arg1, 0);
-#ifdef USE_UID16
- print_raw_param("%d", tswap16(arg2), 0);
- print_raw_param("%d", tswap16(arg3), 0);
-#else
- print_raw_param("%d", tswap32(arg2), 0);
- print_raw_param("%d", tswap32(arg3), 0);
-#endif
+ print_raw_param("%d", arg2, 0);
+ print_raw_param("%d", arg3, 0);
print_flags(at_file_flags, arg4, 1);
print_syscall_epilogue(name);
}
@@ -761,7 +748,7 @@ print_fcntl(const struct syscallname *name,
abi_long arg3, abi_long arg4, abi_long arg5)
{
print_syscall_prologue(name);
- print_raw_param("%d", tswap32(arg0), 0);
+ print_raw_param("%d", arg0, 0);
print_flags(fcntl_flags, arg1, 0);
/*
* TODO: check flags and print following argument only
@@ -842,7 +829,7 @@ print_fstat(const struct syscallname *name,
abi_long arg3, abi_long arg4, abi_long arg5)
{
print_syscall_prologue(name);
- print_raw_param("%d", tswap32(arg0), 0);
+ print_raw_param("%d", arg0, 0);
print_pointer(arg1, 1);
print_syscall_epilogue(name);
}
@@ -876,20 +863,32 @@ print_mkdirat(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_rmdir
+static void
+print_rmdir(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+ print_string(arg0, 0);
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_mknod
static void
print_mknod(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
- int hasdev = (tswapl(arg1) & (S_IFCHR|S_IFBLK));
+ int hasdev = (arg1 & (S_IFCHR|S_IFBLK));
print_syscall_prologue(name);
print_string(arg0, 0);
print_file_mode(arg1, (hasdev == 0));
if (hasdev) {
- print_raw_param("makedev(%d", major(tswapl(arg2)), 0);
- print_raw_param("%d)", minor(tswapl(arg2)), 1);
+ print_raw_param("makedev(%d", major(arg2), 0);
+ print_raw_param("%d)", minor(arg2), 1);
}
print_syscall_epilogue(name);
}
@@ -901,15 +900,15 @@ print_mknodat(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
- int hasdev = (tswapl(arg2) & (S_IFCHR|S_IFBLK));
+ int hasdev = (arg2 & (S_IFCHR|S_IFBLK));
print_syscall_prologue(name);
print_at_dirfd(arg0, 0);
print_string(arg1, 0);
print_file_mode(arg2, (hasdev == 0));
if (hasdev) {
- print_raw_param("makedev(%d", major(tswapl(arg3)), 0);
- print_raw_param("%d)", minor(tswapl(arg3)), 1);
+ print_raw_param("makedev(%d", major(arg3), 0);
+ print_raw_param("%d)", minor(arg3), 1);
}
print_syscall_epilogue(name);
}
@@ -921,7 +920,7 @@ print_mq_open(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
- int is_creat = (tswapl(arg1) & TARGET_O_CREAT);
+ int is_creat = (arg1 & TARGET_O_CREAT);
print_syscall_prologue(name);
print_string(arg0, 0);
@@ -940,7 +939,7 @@ print_open(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
- int is_creat = (tswap32(arg1) & TARGET_O_CREAT);
+ int is_creat = (arg1 & TARGET_O_CREAT);
print_syscall_prologue(name);
print_string(arg0, 0);
@@ -957,7 +956,7 @@ print_openat(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
- int is_creat = (tswap32(arg2) & TARGET_O_CREAT);
+ int is_creat = (arg2 & TARGET_O_CREAT);
print_syscall_prologue(name);
print_at_dirfd(arg0, 0);
@@ -1006,7 +1005,7 @@ print_readlink(const struct syscallname *name,
print_syscall_prologue(name);
print_string(arg0, 0);
print_pointer(arg1, 0);
- print_raw_param("%u", tswapl(arg2), 1);
+ print_raw_param("%u", arg2, 1);
print_syscall_epilogue(name);
}
#endif
@@ -1021,7 +1020,7 @@ print_readlinkat(const struct syscallname *name,
print_at_dirfd(arg0, 0);
print_string(arg1, 0);
print_pointer(arg2, 0);
- print_raw_param("%u", tswapl(arg3), 1);
+ print_raw_param("%u", arg3, 1);
print_syscall_epilogue(name);
}
#endif
@@ -1211,11 +1210,11 @@ print_mmap(const struct syscallname *name,
{
print_syscall_prologue(name);
print_pointer(arg0, 0);
- print_raw_param("%d", tswapl(arg1), 0);
+ print_raw_param("%d", arg1, 0);
print_flags(mmap_prot_flags, arg2, 0);
print_flags(mmap_flags, arg3, 0);
- print_raw_param("%d", tswapl(arg4), 0);
- print_raw_param("%#x", tswapl(arg5), 1);
+ print_raw_param("%d", arg4, 0);
+ print_raw_param("%#x", arg5, 1);
print_syscall_epilogue(name);
}
#define print_mmap2 print_mmap
@@ -1229,7 +1228,7 @@ print_mprotect(const struct syscallname *name,
{
print_syscall_prologue(name);
print_pointer(arg0, 0);
- print_raw_param("%d", tswapl(arg1), 0);
+ print_raw_param("%d", arg1, 0);
print_flags(mmap_prot_flags, arg2, 1);
print_syscall_epilogue(name);
}
@@ -1243,7 +1242,7 @@ print_munmap(const struct syscallname *name,
{
print_syscall_prologue(name);
print_pointer(arg0, 0);
- print_raw_param("%d", tswapl(arg1), 1);
+ print_raw_param("%d", arg1, 1);
print_syscall_epilogue(name);
}
#endif
@@ -1257,7 +1256,7 @@ if( cmd == val ) { \
return; \
}
- int cmd = (int)tswap32(tflag);
+ int cmd = (int)tflag;
#ifdef FUTEX_PRIVATE_FLAG
if (cmd & FUTEX_PRIVATE_FLAG) {
gemu_log("FUTEX_PRIVATE_FLAG|");
@@ -1291,10 +1290,10 @@ print_futex(const struct syscallname *name,
print_syscall_prologue(name);
print_pointer(arg0, 0);
print_futex_op(arg1, 0);
- print_raw_param(",%d", tswapl(arg2), 0);
+ print_raw_param(",%d", arg2, 0);
print_pointer(arg3, 0); /* struct timespec */
print_pointer(arg4, 0);
- print_raw_param("%d", tswapl(arg4), 1);
+ print_raw_param("%d", arg4, 1);
print_syscall_epilogue(name);
}
#endif
diff --git a/linux-user/strace.list b/linux-user/strace.list
index d7be0e7a68..563a67f0a2 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -495,6 +495,9 @@
#ifdef TARGET_NR_mkdirat
{ TARGET_NR_mkdirat, "mkdirat" , NULL, print_mkdirat, NULL },
#endif
+#ifdef TARGET_NR_rmdir
+{ TARGET_NR_rmdir, "rmdir" , NULL, print_rmdir, NULL },
+#endif
#ifdef TARGET_NR_mknod
{ TARGET_NR_mknod, "mknod" , NULL, print_mknod, NULL },
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4412a9b143..cf8a4c3876 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -66,6 +66,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
#endif
+#ifdef CONFIG_EPOLL
+#include <sys/epoll.h>
+#endif
#define termios host_termios
#define winsize host_winsize
@@ -7612,6 +7615,110 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
#endif
#endif
+#if defined(CONFIG_EPOLL)
+#if defined(TARGET_NR_epoll_create)
+ case TARGET_NR_epoll_create:
+ ret = get_errno(epoll_create(arg1));
+ break;
+#endif
+#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
+ case TARGET_NR_epoll_create1:
+ ret = get_errno(epoll_create1(arg1));
+ break;
+#endif
+#if defined(TARGET_NR_epoll_ctl)
+ case TARGET_NR_epoll_ctl:
+ {
+ struct epoll_event ep;
+ struct epoll_event *epp = 0;
+ if (arg4) {
+ struct target_epoll_event *target_ep;
+ if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
+ goto efault;
+ }
+ ep.events = tswap32(target_ep->events);
+ /* The epoll_data_t union is just opaque data to the kernel,
+ * so we transfer all 64 bits across and need not worry what
+ * actual data type it is.
+ */
+ ep.data.u64 = tswap64(target_ep->data.u64);
+ unlock_user_struct(target_ep, arg4, 0);
+ epp = &ep;
+ }
+ ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
+ break;
+ }
+#endif
+
+#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT)
+#define IMPLEMENT_EPOLL_PWAIT
+#endif
+#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT)
+#if defined(TARGET_NR_epoll_wait)
+ case TARGET_NR_epoll_wait:
+#endif
+#if defined(IMPLEMENT_EPOLL_PWAIT)
+ case TARGET_NR_epoll_pwait:
+#endif
+ {
+ struct target_epoll_event *target_ep;
+ struct epoll_event *ep;
+ int epfd = arg1;
+ int maxevents = arg3;
+ int timeout = arg4;
+
+ target_ep = lock_user(VERIFY_WRITE, arg2,
+ maxevents * sizeof(struct target_epoll_event), 1);
+ if (!target_ep) {
+ goto efault;
+ }
+
+ ep = alloca(maxevents * sizeof(struct epoll_event));
+
+ switch (num) {
+#if defined(IMPLEMENT_EPOLL_PWAIT)
+ case TARGET_NR_epoll_pwait:
+ {
+ target_sigset_t *target_set;
+ sigset_t _set, *set = &_set;
+
+ if (arg5) {
+ target_set = lock_user(VERIFY_READ, arg5,
+ sizeof(target_sigset_t), 1);
+ if (!target_set) {
+ unlock_user(target_ep, arg2, 0);
+ goto efault;
+ }
+ target_to_host_sigset(set, target_set);
+ unlock_user(target_set, arg5, 0);
+ } else {
+ set = NULL;
+ }
+
+ ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set));
+ break;
+ }
+#endif
+#if defined(TARGET_NR_epoll_wait)
+ case TARGET_NR_epoll_wait:
+ ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout));
+ break;
+#endif
+ default:
+ ret = -TARGET_ENOSYS;
+ }
+ if (!is_error(ret)) {
+ int i;
+ for (i = 0; i < ret; i++) {
+ target_ep[i].events = tswap32(ep[i].events);
+ target_ep[i].data.u64 = tswap64(ep[i].data.u64);
+ }
+ }
+ unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
+ break;
+ }
+#endif
+#endif
default:
unimplemented:
gemu_log("qemu: Unsupported syscall: %d\n", num);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 4742ac0272..702652cb9e 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2206,3 +2206,16 @@ struct target_mq_attr {
#define FUTEX_CLOCK_REALTIME 256
#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
+#ifdef CONFIG_EPOLL
+typedef union target_epoll_data {
+ abi_ulong ptr;
+ abi_ulong fd;
+ uint32_t u32;
+ uint64_t u64;
+} target_epoll_data_t;
+
+struct target_epoll_event {
+ uint32_t events;
+ target_epoll_data_t data;
+};
+#endif