summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-10-07 10:41:48 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-10-07 10:41:48 +0100
commitb6011bd8a57c1eda81a857d21adeb9b66e58b1b0 (patch)
tree571bd286415d0a7e877327695107985a2f304909
parent2472b6c07bb50179019589af1c22f43935ab7f5c (diff)
parent1a1c4db9b298956e89caf53b09b6a7a960d55d66 (diff)
downloadhqemu-b6011bd8a57c1eda81a857d21adeb9b66e58b1b0.zip
hqemu-b6011bd8a57c1eda81a857d21adeb9b66e58b1b0.tar.gz
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>
-rw-r--r--include/exec/cpu-all.h4
-rw-r--r--linux-user/arm/syscall_nr.h2
-rw-r--r--linux-user/elfload.c18
-rw-r--r--linux-user/ioctls.h3
-rw-r--r--linux-user/syscall.c87
-rw-r--r--linux-user/syscall_types.h2
-rw-r--r--translate-all.c33
7 files changed, 104 insertions, 45 deletions
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index f9d132f..c085804 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -232,8 +232,8 @@ extern uintptr_t qemu_host_page_mask;
#if defined(CONFIG_USER_ONLY)
void page_dump(FILE *f);
-typedef int (*walk_memory_regions_fn)(void *, abi_ulong,
- abi_ulong, unsigned long);
+typedef int (*walk_memory_regions_fn)(void *, target_ulong,
+ target_ulong, unsigned long);
int walk_memory_regions(void *, walk_memory_regions_fn);
int page_get_flags(target_ulong address);
diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h
index bef847c..7d7be7c 100644
--- a/linux-user/arm/syscall_nr.h
+++ b/linux-user/arm/syscall_nr.h
@@ -350,7 +350,7 @@
#define TARGET_NR_vmsplice (343)
#define TARGET_NR_move_pages (344)
#define TARGET_NR_getcpu (345)
- /* 346 for epoll_pwait */
+#define TARGET_NR_epoll_pwait (346)
#define TARGET_NR_kexec_load (347)
#define TARGET_NR_utimensat (348)
#define TARGET_NR_signalfd (349)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index bea803b..1c04fcf 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2355,9 +2355,9 @@ struct elf_note_info {
};
struct vm_area_struct {
- abi_ulong vma_start; /* start vaddr of memory region */
- abi_ulong vma_end; /* end vaddr of memory region */
- abi_ulong vma_flags; /* protection etc. flags for the region */
+ target_ulong vma_start; /* start vaddr of memory region */
+ target_ulong vma_end; /* end vaddr of memory region */
+ abi_ulong vma_flags; /* protection etc. flags for the region */
QTAILQ_ENTRY(vm_area_struct) vma_link;
};
@@ -2368,13 +2368,13 @@ struct mm_struct {
static struct mm_struct *vma_init(void);
static void vma_delete(struct mm_struct *);
-static int vma_add_mapping(struct mm_struct *, abi_ulong,
- abi_ulong, abi_ulong);
+static int vma_add_mapping(struct mm_struct *, target_ulong,
+ target_ulong, abi_ulong);
static int vma_get_mapping_count(const struct mm_struct *);
static struct vm_area_struct *vma_first(const struct mm_struct *);
static struct vm_area_struct *vma_next(struct vm_area_struct *);
static abi_ulong vma_dump_size(const struct vm_area_struct *);
-static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
+static int vma_walker(void *priv, target_ulong start, target_ulong end,
unsigned long flags);
static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
@@ -2466,8 +2466,8 @@ static void vma_delete(struct mm_struct *mm)
g_free(mm);
}
-static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
- abi_ulong end, abi_ulong flags)
+static int vma_add_mapping(struct mm_struct *mm, target_ulong start,
+ target_ulong end, abi_ulong flags)
{
struct vm_area_struct *vma;
@@ -2535,7 +2535,7 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
return (vma->vma_end - vma->vma_start);
}
-static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
+static int vma_walker(void *priv, target_ulong start, target_ulong end,
unsigned long flags)
{
struct mm_struct *mm = (struct mm_struct *)priv;
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 609b27c..e672655 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -78,7 +78,8 @@
IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG))
IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT))
- IOCTL(BLKPG, IOC_W, MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg)))
+ IOCTL_SPECIAL(BLKPG, IOC_W, do_ioctl_blkpg,
+ MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg)))
#ifdef FIBMAP
IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8fe9df7..a175cc1 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;
}
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 9d0c92d..1fd4ee0 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -252,4 +252,4 @@ STRUCT(blkpg_ioctl_arg,
TYPE_INT, /* op */
TYPE_INT, /* flags */
TYPE_INT, /* datalen */
- MK_PTR(MK_STRUCT(STRUCT_blkpg_partition))) /* data */
+ TYPE_PTRVOID) /* data */
diff --git a/translate-all.c b/translate-all.c
index 2e0265a..ba5c840 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1660,30 +1660,30 @@ void cpu_interrupt(CPUState *cpu, int mask)
struct walk_memory_regions_data {
walk_memory_regions_fn fn;
void *priv;
- uintptr_t start;
+ target_ulong start;
int prot;
};
static int walk_memory_regions_end(struct walk_memory_regions_data *data,
- abi_ulong end, int new_prot)
+ target_ulong end, int new_prot)
{
- if (data->start != -1ul) {
+ if (data->start != -1u) {
int rc = data->fn(data->priv, data->start, end, data->prot);
if (rc != 0) {
return rc;
}
}
- data->start = (new_prot ? end : -1ul);
+ data->start = (new_prot ? end : -1u);
data->prot = new_prot;
return 0;
}
static int walk_memory_regions_1(struct walk_memory_regions_data *data,
- abi_ulong base, int level, void **lp)
+ target_ulong base, int level, void **lp)
{
- abi_ulong pa;
+ target_ulong pa;
int i, rc;
if (*lp == NULL) {
@@ -1708,7 +1708,7 @@ static int walk_memory_regions_1(struct walk_memory_regions_data *data,
void **pp = *lp;
for (i = 0; i < V_L2_SIZE; ++i) {
- pa = base | ((abi_ulong)i <<
+ pa = base | ((target_ulong)i <<
(TARGET_PAGE_BITS + V_L2_BITS * level));
rc = walk_memory_regions_1(data, pa, level - 1, pp + i);
if (rc != 0) {
@@ -1727,13 +1727,12 @@ int walk_memory_regions(void *priv, walk_memory_regions_fn fn)
data.fn = fn;
data.priv = priv;
- data.start = -1ul;
+ data.start = -1u;
data.prot = 0;
for (i = 0; i < V_L1_SIZE; i++) {
- int rc = walk_memory_regions_1(&data, (abi_ulong)i << V_L1_SHIFT,
+ int rc = walk_memory_regions_1(&data, (target_ulong)i << (V_L1_SHIFT + TARGET_PAGE_BITS),
V_L1_SHIFT / V_L2_BITS - 1, l1_map + i);
-
if (rc != 0) {
return rc;
}
@@ -1742,13 +1741,13 @@ int walk_memory_regions(void *priv, walk_memory_regions_fn fn)
return walk_memory_regions_end(&data, 0, 0);
}
-static int dump_region(void *priv, abi_ulong start,
- abi_ulong end, unsigned long prot)
+static int dump_region(void *priv, target_ulong start,
+ target_ulong end, unsigned long prot)
{
FILE *f = (FILE *)priv;
- (void) fprintf(f, TARGET_ABI_FMT_lx"-"TARGET_ABI_FMT_lx
- " "TARGET_ABI_FMT_lx" %c%c%c\n",
+ (void) fprintf(f, TARGET_FMT_lx"-"TARGET_FMT_lx
+ " "TARGET_FMT_lx" %c%c%c\n",
start, end, end - start,
((prot & PAGE_READ) ? 'r' : '-'),
((prot & PAGE_WRITE) ? 'w' : '-'),
@@ -1760,7 +1759,7 @@ static int dump_region(void *priv, abi_ulong start,
/* dump memory mappings */
void page_dump(FILE *f)
{
- const int length = sizeof(abi_ulong) * 2;
+ const int length = sizeof(target_ulong) * 2;
(void) fprintf(f, "%-*s %-*s %-*s %s\n",
length, "start", length, "end", length, "size", "prot");
walk_memory_regions(f, dump_region);
@@ -1788,7 +1787,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
guest address space. If this assert fires, it probably indicates
a missing call to h2g_valid. */
#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS
- assert(end < ((abi_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
+ assert(end < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
#endif
assert(start < end);
@@ -1825,7 +1824,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
guest address space. If this assert fires, it probably indicates
a missing call to h2g_valid. */
#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS
- assert(start < ((abi_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
+ assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
#endif
if (len == 0) {
OpenPOWER on IntegriCloud