diff options
| author | Laurent Vivier | 2017-03-01 10:37:48 +0100 |
|---|---|---|
| committer | Riku Voipio | 2017-05-29 13:56:07 +0200 |
| commit | 562a20b4ef63bdde6e2e5bac0da02302aeb5299f (patch) | |
| tree | 1b7a146d5a815554ce689ab626133c41f4f62ec5 | |
| parent | linux-user: call fd_trans_target_to_host_data() for write() (diff) | |
| download | qemu-562a20b4ef63bdde6e2e5bac0da02302aeb5299f.tar.gz qemu-562a20b4ef63bdde6e2e5bac0da02302aeb5299f.tar.xz qemu-562a20b4ef63bdde6e2e5bac0da02302aeb5299f.zip | |
linux-user: fix eventfd
When a fd is opened using eventfd(), a read provides
a 64bit counter in the host byte order, and a
write increase the internal counter by the provided
64bit value.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
| -rw-r--r-- | linux-user/syscall.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b2b563e388..2da8426aaa 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7671,6 +7671,28 @@ static target_timer_t get_timer_id(abi_long arg) return timerid; } +static abi_long swap_data_eventfd(void *buf, size_t len) +{ + uint64_t *counter = buf; + int i; + + if (len < sizeof(uint64_t)) { + return -EINVAL; + } + + for (i = 0; i < len; i += sizeof(uint64_t)) { + *counter = tswap64(*counter); + counter++; + } + + return len; +} + +static TargetFdTrans target_eventfd_trans = { + .host_to_target_data = swap_data_eventfd, + .target_to_host_data = swap_data_eventfd, +}; + /* do_syscall() should always have a single exit point at the end so that actions, such as logging of syscall results, can be performed. All errnos that do_syscall() returns must be -TARGET_<errcode>. */ @@ -11876,7 +11898,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_eventfd) case TARGET_NR_eventfd: ret = get_errno(eventfd(arg1, 0)); - fd_trans_unregister(ret); + fd_trans_register(ret, &target_eventfd_trans); break; #endif #if defined(TARGET_NR_eventfd2) @@ -11890,7 +11912,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, host_flags |= O_CLOEXEC; } ret = get_errno(eventfd(arg1, host_flags)); - fd_trans_unregister(ret); + fd_trans_register(ret, &target_eventfd_trans); break; } #endif |
