diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-10-07 10:41:48 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-10-07 10:41:48 +0100 |
commit | b6011bd8a57c1eda81a857d21adeb9b66e58b1b0 (patch) | |
tree | 571bd286415d0a7e877327695107985a2f304909 /linux-user/syscall.c | |
parent | 2472b6c07bb50179019589af1c22f43935ab7f5c (diff) | |
parent | 1a1c4db9b298956e89caf53b09b6a7a960d55d66 (diff) |
Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20141006-2' into staging
linux-user pull for 2.2
Clearest linux-user patches sent to the list since august,
Apart from Mikhails patch, the rest are quite trivial.
v2: check for CONFIG_TIMERFD only after it has been defined
# gpg: Signature made Mon 06 Oct 2014 20:08:10 BST using RSA key ID DE3C9BC0
# gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>"
# gpg: aka "Riku Voipio <riku.voipio@linaro.org>"
* remotes/riku/tags/pull-linux-user-20141006-2:
translate-all.c: memory walker initial address miscalculation
linux-user: don't include timerfd if not needed
linux-user: Simplify timerid checks on g_posix_timers range
linux-user: Convert blkpg to use a special subop handler
linux-user: Enable epoll_pwait syscall for ARM
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 87 |
1 files changed, 73 insertions, 14 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8fe9df7b87..a175cc15f8 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -58,7 +58,6 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <sys/shm.h> #include <sys/sem.h> #include <sys/statfs.h> -#include <sys/timerfd.h> #include <utime.h> #include <sys/sysinfo.h> //#include <sys/user.h> @@ -67,6 +66,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <linux/wireless.h> #include <linux/icmp.h> #include "qemu-common.h" +#ifdef CONFIG_TIMERFD +#include <sys/timerfd.h> +#endif #ifdef TARGET_GPROF #include <sys/gmon.h> #endif @@ -3696,6 +3698,59 @@ out: return ret; } +static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, + abi_long cmd, abi_long arg) +{ + void *argptr; + int target_size; + const argtype *arg_type = ie->arg_type; + const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) }; + abi_long ret; + + struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp; + struct blkpg_partition host_part; + + /* Read and convert blkpg */ + arg_type++; + target_size = thunk_type_size(arg_type, 0); + argptr = lock_user(VERIFY_READ, arg, target_size, 1); + if (!argptr) { + ret = -TARGET_EFAULT; + goto out; + } + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); + unlock_user(argptr, arg, 0); + + switch (host_blkpg->op) { + case BLKPG_ADD_PARTITION: + case BLKPG_DEL_PARTITION: + /* payload is struct blkpg_partition */ + break; + default: + /* Unknown opcode */ + ret = -TARGET_EINVAL; + goto out; + } + + /* Read and convert blkpg->data */ + arg = (abi_long)(uintptr_t)host_blkpg->data; + target_size = thunk_type_size(part_arg_type, 0); + argptr = lock_user(VERIFY_READ, arg, target_size, 1); + if (!argptr) { + ret = -TARGET_EFAULT; + goto out; + } + thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST); + unlock_user(argptr, arg, 0); + + /* Swizzle the data pointer to our local copy and call! */ + host_blkpg->data = &host_part; + ret = get_errno(ioctl(fd, ie->host_cmd, host_blkpg)); + +out: + return ret; +} + static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, abi_long cmd, abi_long arg) { @@ -9562,11 +9617,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { /* args: timer_t timerid, int flags, const struct itimerspec *new_value, * struct itimerspec * old_value */ - arg1 &= 0xffff; - if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + target_ulong timerid = arg1; + + if (arg3 == 0 || timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; struct itimerspec hspec_new = {{0},}, hspec_old = {{0},}; target_to_host_itimerspec(&hspec_new, arg3); @@ -9582,13 +9638,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_timer_gettime: { /* args: timer_t timerid, struct itimerspec *curr_value */ - arg1 &= 0xffff; + target_ulong timerid = arg1; + if (!arg2) { return -TARGET_EFAULT; - } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + } else if (timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; struct itimerspec hspec; ret = get_errno(timer_gettime(htimer, &hspec)); @@ -9604,11 +9661,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_timer_getoverrun: { /* args: timer_t timerid */ - arg1 &= 0xffff; - if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + target_ulong timerid = arg1; + + if (timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; ret = get_errno(timer_getoverrun(htimer)); } break; @@ -9619,13 +9677,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_timer_delete: { /* args: timer_t timerid */ - arg1 &= 0xffff; - if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) { + target_ulong timerid = arg1; + + if (timerid >= ARRAY_SIZE(g_posix_timers)) { ret = -TARGET_EINVAL; } else { - timer_t htimer = g_posix_timers[arg1]; + timer_t htimer = g_posix_timers[timerid]; ret = get_errno(timer_delete(htimer)); - g_posix_timers[arg1] = 0; + g_posix_timers[timerid] = 0; } break; } |