* [Qemu-devel] [PULL 2/5] linux-user: Convert blkpg to use a special subop handler
2014-10-06 14:34 [Qemu-devel] [PULL 0/5] linux-user patches for 2.2 riku.voipio
2014-10-06 14:34 ` [Qemu-devel] [PULL 1/5] linux-user: Enable epoll_pwait syscall for ARM riku.voipio
@ 2014-10-06 14:34 ` riku.voipio
2014-10-06 14:34 ` [Qemu-devel] [PULL 3/5] linux-user: Simplify timerid checks on g_posix_timers range riku.voipio
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: riku.voipio @ 2014-10-06 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
From: Alexander Graf <agraf@suse.de>
The blkpg ioctl can take different payloads depending on the opcode in
its payload structure. Create a new special ioctl handler that can only
deal with partition style ones for now.
This patch fixes running parted for me.
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/ioctls.h | 3 ++-
linux-user/syscall.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
linux-user/syscall_types.h | 2 +-
3 files changed, 56 insertions(+), 2 deletions(-)
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..dcb9df9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3696,6 +3696,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)
{
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 */
--
2.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PULL 3/5] linux-user: Simplify timerid checks on g_posix_timers range
2014-10-06 14:34 [Qemu-devel] [PULL 0/5] linux-user patches for 2.2 riku.voipio
2014-10-06 14:34 ` [Qemu-devel] [PULL 1/5] linux-user: Enable epoll_pwait syscall for ARM riku.voipio
2014-10-06 14:34 ` [Qemu-devel] [PULL 2/5] linux-user: Convert blkpg to use a special subop handler riku.voipio
@ 2014-10-06 14:34 ` riku.voipio
2014-10-06 14:34 ` [Qemu-devel] [PULL 4/5] linux-user: don't include timerfd if not needed riku.voipio
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: riku.voipio @ 2014-10-06 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexander Graf
From: Alexander Graf <agraf@suse.de>
We check whether the passed in timer id is negative on all calls
that involve g_posix_timers.
However, these checks are bogus. First off we limit the timer_id to
16 bits which is not what Linux does. Then we check whether it's negative
which it can't be because we masked it.
We can safely remove the masking. For the negativity check we can just
treat the timerid as unsigned and only check for upper boundaries.
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index dcb9df9..7087a56 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9615,11 +9615,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);
@@ -9635,13 +9636,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));
@@ -9657,11 +9659,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;
@@ -9672,13 +9675,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;
}
--
2.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PULL 5/5] translate-all.c: memory walker initial address miscalculation
2014-10-06 14:34 [Qemu-devel] [PULL 0/5] linux-user patches for 2.2 riku.voipio
` (3 preceding siblings ...)
2014-10-06 14:34 ` [Qemu-devel] [PULL 4/5] linux-user: don't include timerfd if not needed riku.voipio
@ 2014-10-06 14:34 ` riku.voipio
2014-10-06 14:59 ` [Qemu-devel] [PULL 0/5] linux-user patches for 2.2 Peter Maydell
5 siblings, 0 replies; 9+ messages in thread
From: riku.voipio @ 2014-10-06 14:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Mikhail Ilyin
From: Mikhail Ilyin <m.ilin@samsung.com>
The initial base address is miscalculated in walk_memory_regions().
It has to be shifted TARGET_PAGE_BITS more. Holder variables are
extended to target_ulong size otherwise they don't fit for MIPS N32
(a 32-bit ABI with a 64-bit address space) and qemu won't compile.
The issue led to incorrect debug output of memory maps and a
mis-formed coredumped file.
Signed-off-by: Mikhail Ilyin <m.ilin@samsung.com>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
include/exec/cpu-all.h | 4 ++--
linux-user/elfload.c | 18 +++++++++---------
translate-all.c | 33 ++++++++++++++++-----------------
3 files changed, 27 insertions(+), 28 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/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/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) {
--
2.0.1
^ permalink raw reply related [flat|nested] 9+ messages in thread