Merge branch 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu
* 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu: Userspace ARM BE8 support elf.h: Update EF_ARM_ constants to newer ABI versions arm-linux-user: fix elfload.c's AT_HWCAP to reflect cpu features. linux-user/arm/syscall_nr.h: Add syscall number for ppoll linux-user: Add support for prctl PR_GET_NAME and PR_SET_NAME linux-user/syscall.c: Fix indentation in prctl handling linux-user: reserve 4GB of vmem for 32-on-64 linux-user: resolve reserved_va vma downwards linux-user: take RESERVED_VA into account for g2h_valid() linux-user: fix fallocate linux-user: Add ioctl for BLKBSZGET linux-user: add BLKSSZGET ioctl wrapper linux-user: fix BLK ioctl arguments linux-user: add struct old_dev_t compat linux-user: implement device mapper ioctls linux-user: target_argv is placed on ts->bprm->argv and can't be freed() linux-user: improve fake /proc/self/stat making `ps` not segfault.
This commit is contained in:
commit
adcd61f7fc
@ -204,7 +204,8 @@ extern unsigned long reserved_va;
|
||||
#else
|
||||
#define h2g_valid(x) ({ \
|
||||
unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
|
||||
__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS); \
|
||||
(__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
|
||||
(!RESERVED_VA || (__guest < RESERVED_VA)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
18
disas.c
18
disas.c
@ -138,7 +138,7 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info)
|
||||
/* Disassemble this for me please... (debugging). 'flags' has the following
|
||||
values:
|
||||
i386 - 1 means 16 bit code, 2 means 64 bit code
|
||||
arm - nonzero means thumb code
|
||||
arm - bit 0 = thumb, bit 1 = reverse endian
|
||||
ppc - nonzero means little endian
|
||||
other targets - unused
|
||||
*/
|
||||
@ -169,10 +169,18 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
|
||||
disasm_info.mach = bfd_mach_i386_i386;
|
||||
print_insn = print_insn_i386;
|
||||
#elif defined(TARGET_ARM)
|
||||
if (flags)
|
||||
print_insn = print_insn_thumb1;
|
||||
else
|
||||
print_insn = print_insn_arm;
|
||||
if (flags & 1) {
|
||||
print_insn = print_insn_thumb1;
|
||||
} else {
|
||||
print_insn = print_insn_arm;
|
||||
}
|
||||
if (flags & 2) {
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
disasm_info.endian = BFD_ENDIAN_LITTLE;
|
||||
#else
|
||||
disasm_info.endian = BFD_ENDIAN_BIG;
|
||||
#endif
|
||||
}
|
||||
#elif defined(TARGET_SPARC)
|
||||
print_insn = print_insn_sparc;
|
||||
#ifdef TARGET_SPARC64
|
||||
|
21
elf.h
21
elf.h
@ -538,6 +538,27 @@ typedef struct {
|
||||
#define EF_ALIGN8 0x40 /* 8-bit structure alignment is in use */
|
||||
#define EF_NEW_ABI 0x80
|
||||
#define EF_OLD_ABI 0x100
|
||||
#define EF_ARM_SOFT_FLOAT 0x200
|
||||
#define EF_ARM_VFP_FLOAT 0x400
|
||||
#define EF_ARM_MAVERICK_FLOAT 0x800
|
||||
|
||||
/* Other constants defined in the ARM ELF spec. version B-01. */
|
||||
#define EF_ARM_SYMSARESORTED 0x04 /* NB conflicts with EF_INTERWORK */
|
||||
#define EF_ARM_DYNSYMSUSESEGIDX 0x08 /* NB conflicts with EF_APCS26 */
|
||||
#define EF_ARM_MAPSYMSFIRST 0x10 /* NB conflicts with EF_APCS_FLOAT */
|
||||
#define EF_ARM_EABIMASK 0xFF000000
|
||||
|
||||
/* Constants defined in AAELF. */
|
||||
#define EF_ARM_BE8 0x00800000
|
||||
#define EF_ARM_LE8 0x00400000
|
||||
|
||||
#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
|
||||
#define EF_ARM_EABI_UNKNOWN 0x00000000
|
||||
#define EF_ARM_EABI_VER1 0x01000000
|
||||
#define EF_ARM_EABI_VER2 0x02000000
|
||||
#define EF_ARM_EABI_VER3 0x03000000
|
||||
#define EF_ARM_EABI_VER4 0x04000000
|
||||
#define EF_ARM_EABI_VER5 0x05000000
|
||||
|
||||
/* Additional symbol types for Thumb */
|
||||
#define STT_ARM_TFUNC 0xd
|
||||
|
@ -339,7 +339,7 @@
|
||||
#define TARGET_NR_fchmodat (333)
|
||||
#define TARGET_NR_faccessat (334)
|
||||
#define TARGET_NR_pselect6 (335)
|
||||
/* 336 for ppoll */
|
||||
#define TARGET_NR_ppoll (336)
|
||||
#define TARGET_NR_unshare (337)
|
||||
#define TARGET_NR_set_robust_list (338)
|
||||
#define TARGET_NR_get_robust_list (339)
|
||||
|
@ -375,10 +375,33 @@ bool guest_validate_base(unsigned long guest_base)
|
||||
return 1; /* All good */
|
||||
}
|
||||
|
||||
#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
|
||||
| ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
|
||||
| ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
|
||||
| ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
|
||||
|
||||
#define ELF_HWCAP get_elf_hwcap()
|
||||
|
||||
static uint32_t get_elf_hwcap(void)
|
||||
{
|
||||
CPUARMState *e = thread_env;
|
||||
uint32_t hwcaps = 0;
|
||||
|
||||
hwcaps |= ARM_HWCAP_ARM_SWP;
|
||||
hwcaps |= ARM_HWCAP_ARM_HALF;
|
||||
hwcaps |= ARM_HWCAP_ARM_THUMB;
|
||||
hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
|
||||
hwcaps |= ARM_HWCAP_ARM_FPA;
|
||||
|
||||
/* probe for the extra features */
|
||||
#define GET_FEATURE(feat, hwcap) \
|
||||
do {if (arm_feature(e, feat)) { hwcaps |= hwcap; } } while (0)
|
||||
GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
|
||||
GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
|
||||
GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
|
||||
GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
|
||||
GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
|
||||
GET_FEATURE(ARM_FEATURE_VFP_FP16, ARM_HWCAP_ARM_VFPv3D16);
|
||||
#undef GET_FEATURE
|
||||
|
||||
return hwcaps;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1553,6 +1576,7 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
info->start_data = -1;
|
||||
info->end_data = 0;
|
||||
info->brk = 0;
|
||||
info->elf_flags = ehdr->e_flags;
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
struct elf_phdr *eppnt = phdr + i;
|
||||
|
@ -74,6 +74,8 @@
|
||||
IOCTL(BLKFLSBUF, 0, TYPE_NULL)
|
||||
IOCTL(BLKRASET, 0, TYPE_INT)
|
||||
IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
|
||||
IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG))
|
||||
IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT))
|
||||
#ifdef FIBMAP
|
||||
IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
|
||||
#endif
|
||||
@ -345,3 +347,35 @@
|
||||
IOCTL(VT_SETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode)))
|
||||
IOCTL(VT_RELDISP, 0, TYPE_INT)
|
||||
IOCTL(VT_DISALLOCATE, 0, TYPE_INT)
|
||||
|
||||
IOCTL(DM_VERSION, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_REMOVE_ALL, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_LIST_DEVICES, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_DEV_CREATE, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_DEV_REMOVE, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_DEV_RENAME, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_DEV_SUSPEND, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_DEV_STATUS, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_DEV_WAIT, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_TABLE_LOAD, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_TABLE_CLEAR, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_TABLE_DEPS, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_TABLE_STATUS, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_LIST_VERSIONS,IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_TARGET_MSG, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
|
||||
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "tcg.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "envlist.h"
|
||||
#include "elf.h"
|
||||
|
||||
#define DEBUG_LOGFILE "/tmp/qemu.log"
|
||||
|
||||
@ -48,8 +49,19 @@ unsigned long mmap_min_addr;
|
||||
#if defined(CONFIG_USE_GUEST_BASE)
|
||||
unsigned long guest_base;
|
||||
int have_guest_base;
|
||||
#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64)
|
||||
/*
|
||||
* When running 32-on-64 we should make sure we can fit all of the possible
|
||||
* guest address space into a contiguous chunk of virtual host memory.
|
||||
*
|
||||
* This way we will never overlap with our own libraries or binaries or stack
|
||||
* or anything else that QEMU maps.
|
||||
*/
|
||||
unsigned long reserved_va = 0xf7000000;
|
||||
#else
|
||||
unsigned long reserved_va;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void usage(void);
|
||||
|
||||
@ -463,6 +475,22 @@ void cpu_loop(CPUX86State *env)
|
||||
|
||||
#ifdef TARGET_ARM
|
||||
|
||||
#define get_user_code_u32(x, gaddr, doswap) \
|
||||
({ abi_long __r = get_user_u32((x), (gaddr)); \
|
||||
if (!__r && (doswap)) { \
|
||||
(x) = bswap32(x); \
|
||||
} \
|
||||
__r; \
|
||||
})
|
||||
|
||||
#define get_user_code_u16(x, gaddr, doswap) \
|
||||
({ abi_long __r = get_user_u16((x), (gaddr)); \
|
||||
if (!__r && (doswap)) { \
|
||||
(x) = bswap16(x); \
|
||||
} \
|
||||
__r; \
|
||||
})
|
||||
|
||||
/*
|
||||
* See the Linux kernel's Documentation/arm/kernel_user_helpers.txt
|
||||
* Input:
|
||||
@ -696,7 +724,7 @@ void cpu_loop(CPUARMState *env)
|
||||
/* we handle the FPU emulation here, as Linux */
|
||||
/* we get the opcode */
|
||||
/* FIXME - what to do if get_user() fails? */
|
||||
get_user_u32(opcode, env->regs[15]);
|
||||
get_user_code_u32(opcode, env->regs[15], env->bswap_code);
|
||||
|
||||
rc = EmulateAll(opcode, &ts->fpa, env);
|
||||
if (rc == 0) { /* illegal instruction */
|
||||
@ -766,23 +794,25 @@ void cpu_loop(CPUARMState *env)
|
||||
if (trapnr == EXCP_BKPT) {
|
||||
if (env->thumb) {
|
||||
/* FIXME - what to do if get_user() fails? */
|
||||
get_user_u16(insn, env->regs[15]);
|
||||
get_user_code_u16(insn, env->regs[15], env->bswap_code);
|
||||
n = insn & 0xff;
|
||||
env->regs[15] += 2;
|
||||
} else {
|
||||
/* FIXME - what to do if get_user() fails? */
|
||||
get_user_u32(insn, env->regs[15]);
|
||||
get_user_code_u32(insn, env->regs[15], env->bswap_code);
|
||||
n = (insn & 0xf) | ((insn >> 4) & 0xff0);
|
||||
env->regs[15] += 4;
|
||||
}
|
||||
} else {
|
||||
if (env->thumb) {
|
||||
/* FIXME - what to do if get_user() fails? */
|
||||
get_user_u16(insn, env->regs[15] - 2);
|
||||
get_user_code_u16(insn, env->regs[15] - 2,
|
||||
env->bswap_code);
|
||||
n = insn & 0xff;
|
||||
} else {
|
||||
/* FIXME - what to do if get_user() fails? */
|
||||
get_user_u32(insn, env->regs[15] - 4);
|
||||
get_user_code_u32(insn, env->regs[15] - 4,
|
||||
env->bswap_code);
|
||||
n = insn & 0xffffff;
|
||||
}
|
||||
}
|
||||
@ -3420,6 +3450,7 @@ int main(int argc, char **argv, char **envp)
|
||||
guest_base = HOST_PAGE_ALIGN((unsigned long)p);
|
||||
}
|
||||
qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va);
|
||||
mmap_next_start = reserved_va;
|
||||
}
|
||||
|
||||
if (reserved_va || have_guest_base) {
|
||||
@ -3486,11 +3517,6 @@ int main(int argc, char **argv, char **envp)
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < target_argc; i++) {
|
||||
free(target_argv[i]);
|
||||
}
|
||||
free(target_argv);
|
||||
|
||||
for (wrk = target_environ; *wrk; wrk++) {
|
||||
free(*wrk);
|
||||
}
|
||||
@ -3650,6 +3676,11 @@ int main(int argc, char **argv, char **envp)
|
||||
for(i = 0; i < 16; i++) {
|
||||
env->regs[i] = regs->uregs[i];
|
||||
}
|
||||
/* Enable BE8. */
|
||||
if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
|
||||
&& (info->elf_flags & EF_ARM_BE8)) {
|
||||
env->bswap_code = 1;
|
||||
}
|
||||
}
|
||||
#elif defined(TARGET_UNICORE32)
|
||||
{
|
||||
|
@ -212,7 +212,7 @@ static int mmap_frag(abi_ulong real_start,
|
||||
#else
|
||||
# define TASK_UNMAPPED_BASE 0x40000000
|
||||
#endif
|
||||
static abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
|
||||
abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
|
||||
|
||||
unsigned long last_brk;
|
||||
|
||||
@ -222,7 +222,7 @@ unsigned long last_brk;
|
||||
static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
|
||||
{
|
||||
abi_ulong addr;
|
||||
abi_ulong last_addr;
|
||||
abi_ulong end_addr;
|
||||
int prot;
|
||||
int looped = 0;
|
||||
|
||||
@ -230,25 +230,38 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
|
||||
return (abi_ulong)-1;
|
||||
}
|
||||
|
||||
last_addr = start;
|
||||
for (addr = start; last_addr + size != addr; addr += qemu_host_page_size) {
|
||||
if (last_addr + size >= RESERVED_VA
|
||||
|| (abi_ulong)(last_addr + size) < last_addr) {
|
||||
size = HOST_PAGE_ALIGN(size);
|
||||
end_addr = start + size;
|
||||
if (end_addr > RESERVED_VA) {
|
||||
end_addr = RESERVED_VA;
|
||||
}
|
||||
addr = end_addr - qemu_host_page_size;
|
||||
|
||||
while (1) {
|
||||
if (addr > end_addr) {
|
||||
if (looped) {
|
||||
return (abi_ulong)-1;
|
||||
}
|
||||
last_addr = qemu_host_page_size;
|
||||
addr = 0;
|
||||
end_addr = RESERVED_VA;
|
||||
addr = end_addr - qemu_host_page_size;
|
||||
looped = 1;
|
||||
continue;
|
||||
}
|
||||
prot = page_get_flags(addr);
|
||||
if (prot) {
|
||||
last_addr = addr + qemu_host_page_size;
|
||||
end_addr = addr;
|
||||
}
|
||||
if (addr + size == end_addr) {
|
||||
break;
|
||||
}
|
||||
addr -= qemu_host_page_size;
|
||||
}
|
||||
mmap_next_start = addr;
|
||||
return last_addr;
|
||||
|
||||
if (start == mmap_next_start) {
|
||||
mmap_next_start = addr;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -51,6 +51,7 @@ struct image_info {
|
||||
abi_ulong auxv_len;
|
||||
abi_ulong arg_start;
|
||||
abi_ulong arg_end;
|
||||
uint32_t elf_flags;
|
||||
int personality;
|
||||
#ifdef CONFIG_USE_FDPIC
|
||||
abi_ulong loadmap_addr;
|
||||
@ -251,6 +252,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||
abi_ulong new_addr);
|
||||
int target_msync(abi_ulong start, abi_ulong len, int flags);
|
||||
extern unsigned long last_brk;
|
||||
extern abi_ulong mmap_next_start;
|
||||
void mmap_lock(void);
|
||||
void mmap_unlock(void);
|
||||
abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
|
||||
|
@ -95,6 +95,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
||||
#endif
|
||||
#include <linux/fb.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
#include "linux_loop.h"
|
||||
#include "cpu-uname.h"
|
||||
|
||||
@ -3354,6 +3355,231 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
|
||||
abi_long cmd, abi_long arg)
|
||||
{
|
||||
void *argptr;
|
||||
struct dm_ioctl *host_dm;
|
||||
abi_long guest_data;
|
||||
uint32_t guest_data_size;
|
||||
int target_size;
|
||||
const argtype *arg_type = ie->arg_type;
|
||||
abi_long ret;
|
||||
void *big_buf = NULL;
|
||||
char *host_data;
|
||||
|
||||
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);
|
||||
|
||||
/* buf_temp is too small, so fetch things into a bigger buffer */
|
||||
big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
|
||||
memcpy(big_buf, buf_temp, target_size);
|
||||
buf_temp = big_buf;
|
||||
host_dm = big_buf;
|
||||
|
||||
guest_data = arg + host_dm->data_start;
|
||||
if ((guest_data - arg) < 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
guest_data_size = host_dm->data_size - host_dm->data_start;
|
||||
host_data = (char*)host_dm + host_dm->data_start;
|
||||
|
||||
argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
|
||||
switch (ie->host_cmd) {
|
||||
case DM_REMOVE_ALL:
|
||||
case DM_LIST_DEVICES:
|
||||
case DM_DEV_CREATE:
|
||||
case DM_DEV_REMOVE:
|
||||
case DM_DEV_SUSPEND:
|
||||
case DM_DEV_STATUS:
|
||||
case DM_DEV_WAIT:
|
||||
case DM_TABLE_STATUS:
|
||||
case DM_TABLE_CLEAR:
|
||||
case DM_TABLE_DEPS:
|
||||
case DM_LIST_VERSIONS:
|
||||
/* no input data */
|
||||
break;
|
||||
case DM_DEV_RENAME:
|
||||
case DM_DEV_SET_GEOMETRY:
|
||||
/* data contains only strings */
|
||||
memcpy(host_data, argptr, guest_data_size);
|
||||
break;
|
||||
case DM_TARGET_MSG:
|
||||
memcpy(host_data, argptr, guest_data_size);
|
||||
*(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
|
||||
break;
|
||||
case DM_TABLE_LOAD:
|
||||
{
|
||||
void *gspec = argptr;
|
||||
void *cur_data = host_data;
|
||||
const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
|
||||
int spec_size = thunk_type_size(arg_type, 0);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < host_dm->target_count; i++) {
|
||||
struct dm_target_spec *spec = cur_data;
|
||||
uint32_t next;
|
||||
int slen;
|
||||
|
||||
thunk_convert(spec, gspec, arg_type, THUNK_HOST);
|
||||
slen = strlen((char*)gspec + spec_size) + 1;
|
||||
next = spec->next;
|
||||
spec->next = sizeof(*spec) + slen;
|
||||
strcpy((char*)&spec[1], gspec + spec_size);
|
||||
gspec += next;
|
||||
cur_data += spec->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = -TARGET_EINVAL;
|
||||
goto out;
|
||||
}
|
||||
unlock_user(argptr, guest_data, 0);
|
||||
|
||||
ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
|
||||
if (!is_error(ret)) {
|
||||
guest_data = arg + host_dm->data_start;
|
||||
guest_data_size = host_dm->data_size - host_dm->data_start;
|
||||
argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
|
||||
switch (ie->host_cmd) {
|
||||
case DM_REMOVE_ALL:
|
||||
case DM_DEV_CREATE:
|
||||
case DM_DEV_REMOVE:
|
||||
case DM_DEV_RENAME:
|
||||
case DM_DEV_SUSPEND:
|
||||
case DM_DEV_STATUS:
|
||||
case DM_TABLE_LOAD:
|
||||
case DM_TABLE_CLEAR:
|
||||
case DM_TARGET_MSG:
|
||||
case DM_DEV_SET_GEOMETRY:
|
||||
/* no return data */
|
||||
break;
|
||||
case DM_LIST_DEVICES:
|
||||
{
|
||||
struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
|
||||
uint32_t remaining_data = guest_data_size;
|
||||
void *cur_data = argptr;
|
||||
const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
|
||||
int nl_size = 12; /* can't use thunk_size due to alignment */
|
||||
|
||||
while (1) {
|
||||
uint32_t next = nl->next;
|
||||
if (next) {
|
||||
nl->next = nl_size + (strlen(nl->name) + 1);
|
||||
}
|
||||
if (remaining_data < nl->next) {
|
||||
host_dm->flags |= DM_BUFFER_FULL_FLAG;
|
||||
break;
|
||||
}
|
||||
thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
|
||||
strcpy(cur_data + nl_size, nl->name);
|
||||
cur_data += nl->next;
|
||||
remaining_data -= nl->next;
|
||||
if (!next) {
|
||||
break;
|
||||
}
|
||||
nl = (void*)nl + next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DM_DEV_WAIT:
|
||||
case DM_TABLE_STATUS:
|
||||
{
|
||||
struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
|
||||
void *cur_data = argptr;
|
||||
const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
|
||||
int spec_size = thunk_type_size(arg_type, 0);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < host_dm->target_count; i++) {
|
||||
uint32_t next = spec->next;
|
||||
int slen = strlen((char*)&spec[1]) + 1;
|
||||
spec->next = (cur_data - argptr) + spec_size + slen;
|
||||
if (guest_data_size < spec->next) {
|
||||
host_dm->flags |= DM_BUFFER_FULL_FLAG;
|
||||
break;
|
||||
}
|
||||
thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
|
||||
strcpy(cur_data + spec_size, (char*)&spec[1]);
|
||||
cur_data = argptr + spec->next;
|
||||
spec = (void*)host_dm + host_dm->data_start + next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DM_TABLE_DEPS:
|
||||
{
|
||||
void *hdata = (void*)host_dm + host_dm->data_start;
|
||||
int count = *(uint32_t*)hdata;
|
||||
uint64_t *hdev = hdata + 8;
|
||||
uint64_t *gdev = argptr + 8;
|
||||
int i;
|
||||
|
||||
*(uint32_t*)argptr = tswap32(count);
|
||||
for (i = 0; i < count; i++) {
|
||||
*gdev = tswap64(*hdev);
|
||||
gdev++;
|
||||
hdev++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DM_LIST_VERSIONS:
|
||||
{
|
||||
struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
|
||||
uint32_t remaining_data = guest_data_size;
|
||||
void *cur_data = argptr;
|
||||
const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
|
||||
int vers_size = thunk_type_size(arg_type, 0);
|
||||
|
||||
while (1) {
|
||||
uint32_t next = vers->next;
|
||||
if (next) {
|
||||
vers->next = vers_size + (strlen(vers->name) + 1);
|
||||
}
|
||||
if (remaining_data < vers->next) {
|
||||
host_dm->flags |= DM_BUFFER_FULL_FLAG;
|
||||
break;
|
||||
}
|
||||
thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
|
||||
strcpy(cur_data + vers_size, vers->name);
|
||||
cur_data += vers->next;
|
||||
remaining_data -= vers->next;
|
||||
if (!next) {
|
||||
break;
|
||||
}
|
||||
vers = (void*)vers + next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = -TARGET_EINVAL;
|
||||
goto out;
|
||||
}
|
||||
unlock_user(argptr, guest_data, guest_data_size);
|
||||
|
||||
argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
|
||||
if (!argptr) {
|
||||
ret = -TARGET_EFAULT;
|
||||
goto out;
|
||||
}
|
||||
thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
|
||||
unlock_user(argptr, arg, target_size);
|
||||
}
|
||||
out:
|
||||
if (big_buf) {
|
||||
free(big_buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static IOCTLEntry ioctl_entries[] = {
|
||||
#define IOCTL(cmd, access, ...) \
|
||||
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
|
||||
@ -4662,11 +4888,22 @@ static int open_self_stat(void *cpu_env, int fd)
|
||||
int len;
|
||||
uint64_t val = 0;
|
||||
|
||||
if (i == 27) {
|
||||
/* stack bottom */
|
||||
val = start_stack;
|
||||
if (i == 0) {
|
||||
/* pid */
|
||||
val = getpid();
|
||||
snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
|
||||
} else if (i == 1) {
|
||||
/* app name */
|
||||
snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
|
||||
} else if (i == 27) {
|
||||
/* stack bottom */
|
||||
val = start_stack;
|
||||
snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
|
||||
} else {
|
||||
/* for the rest, there is MasterCard */
|
||||
snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%"PRId64 "%c", val, i == 43 ? '\n' : ' ');
|
||||
|
||||
len = strlen(buf);
|
||||
if (write(fd, buf, len) != len) {
|
||||
return -1;
|
||||
@ -7005,21 +7242,46 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
goto unimplemented;
|
||||
#endif
|
||||
case TARGET_NR_prctl:
|
||||
switch (arg1)
|
||||
{
|
||||
case PR_GET_PDEATHSIG:
|
||||
{
|
||||
int deathsig;
|
||||
ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
|
||||
if (!is_error(ret) && arg2
|
||||
&& put_user_ual(deathsig, arg2))
|
||||
goto efault;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
|
||||
break;
|
||||
switch (arg1) {
|
||||
case PR_GET_PDEATHSIG:
|
||||
{
|
||||
int deathsig;
|
||||
ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
|
||||
if (!is_error(ret) && arg2
|
||||
&& put_user_ual(deathsig, arg2)) {
|
||||
goto efault;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef PR_GET_NAME
|
||||
case PR_GET_NAME:
|
||||
{
|
||||
void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
|
||||
if (!name) {
|
||||
goto efault;
|
||||
}
|
||||
ret = get_errno(prctl(arg1, (unsigned long)name,
|
||||
arg3, arg4, arg5));
|
||||
unlock_user(name, arg2, 16);
|
||||
break;
|
||||
}
|
||||
case PR_SET_NAME:
|
||||
{
|
||||
void *name = lock_user(VERIFY_READ, arg2, 16, 1);
|
||||
if (!name) {
|
||||
goto efault;
|
||||
}
|
||||
ret = get_errno(prctl(arg1, (unsigned long)name,
|
||||
arg3, arg4, arg5));
|
||||
unlock_user(name, arg2, 0);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
/* Most prctl options have no pointer arguments */
|
||||
ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef TARGET_NR_arch_prctl
|
||||
case TARGET_NR_arch_prctl:
|
||||
@ -8248,7 +8510,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#endif /* CONFIG_EVENTFD */
|
||||
#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
|
||||
case TARGET_NR_fallocate:
|
||||
#if TARGET_ABI_BITS == 32
|
||||
ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
|
||||
target_offset64(arg5, arg6)));
|
||||
#else
|
||||
ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_SYNC_FILE_RANGE)
|
||||
|
@ -832,9 +832,11 @@ struct target_pollfd {
|
||||
#define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
|
||||
#define TARGET_BLKSSZGET TARGET_IO(0x12,104)/* get block device sector size */
|
||||
/* A jump here: 108-111 have been used for various private purposes. */
|
||||
#define TARGET_BLKBSZGET TARGET_IOR(0x12,112,sizeof(int))
|
||||
#define TARGET_BLKBSZSET TARGET_IOW(0x12,113,sizeof(int))
|
||||
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
|
||||
#define TARGET_BLKBSZGET TARGET_IOR(0x12,112,int)
|
||||
#define TARGET_BLKBSZSET TARGET_IOW(0x12,113,int)
|
||||
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong)
|
||||
/* return device size in bytes
|
||||
(u64 *arg) */
|
||||
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
|
||||
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
|
||||
#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
|
||||
@ -989,6 +991,24 @@ struct target_pollfd {
|
||||
#define TARGET_VT_RELDISP 0x5605
|
||||
#define TARGET_VT_DISALLOCATE 0x5608
|
||||
|
||||
/* device mapper */
|
||||
#define TARGET_DM_VERSION TARGET_IOWRU(0xfd, 0x00)
|
||||
#define TARGET_DM_REMOVE_ALL TARGET_IOWRU(0xfd, 0x01)
|
||||
#define TARGET_DM_LIST_DEVICES TARGET_IOWRU(0xfd, 0x02)
|
||||
#define TARGET_DM_DEV_CREATE TARGET_IOWRU(0xfd, 0x03)
|
||||
#define TARGET_DM_DEV_REMOVE TARGET_IOWRU(0xfd, 0x04)
|
||||
#define TARGET_DM_DEV_RENAME TARGET_IOWRU(0xfd, 0x05)
|
||||
#define TARGET_DM_DEV_SUSPEND TARGET_IOWRU(0xfd, 0x06)
|
||||
#define TARGET_DM_DEV_STATUS TARGET_IOWRU(0xfd, 0x07)
|
||||
#define TARGET_DM_DEV_WAIT TARGET_IOWRU(0xfd, 0x08)
|
||||
#define TARGET_DM_TABLE_LOAD TARGET_IOWRU(0xfd, 0x09)
|
||||
#define TARGET_DM_TABLE_CLEAR TARGET_IOWRU(0xfd, 0x0a)
|
||||
#define TARGET_DM_TABLE_DEPS TARGET_IOWRU(0xfd, 0x0b)
|
||||
#define TARGET_DM_TABLE_STATUS TARGET_IOWRU(0xfd, 0x0c)
|
||||
#define TARGET_DM_LIST_VERSIONS TARGET_IOWRU(0xfd, 0x0d)
|
||||
#define TARGET_DM_TARGET_MSG TARGET_IOWRU(0xfd, 0x0e)
|
||||
#define TARGET_DM_DEV_SET_GEOMETRY TARGET_IOWRU(0xfd, 0x0f)
|
||||
|
||||
/* from asm/termbits.h */
|
||||
|
||||
#define TARGET_NCC 8
|
||||
|
@ -83,9 +83,9 @@ STRUCT(mixer_info,
|
||||
/* loop device ioctls */
|
||||
STRUCT(loop_info,
|
||||
TYPE_INT, /* lo_number */
|
||||
TYPE_SHORT, /* lo_device */
|
||||
TYPE_OLDDEVT, /* lo_device */
|
||||
TYPE_ULONG, /* lo_inode */
|
||||
TYPE_SHORT, /* lo_rdevice */
|
||||
TYPE_OLDDEVT, /* lo_rdevice */
|
||||
TYPE_INT, /* lo_offset */
|
||||
TYPE_INT, /* lo_encrypt_type */
|
||||
TYPE_INT, /* lo_encrypt_key_size */
|
||||
@ -186,6 +186,42 @@ STRUCT(vt_mode,
|
||||
TYPE_SHORT, /* acqsig */
|
||||
TYPE_SHORT) /* frsig */
|
||||
|
||||
STRUCT(dm_ioctl,
|
||||
MK_ARRAY(TYPE_INT, 3), /* version */
|
||||
TYPE_INT, /* data_size */
|
||||
TYPE_INT, /* data_start */
|
||||
TYPE_INT, /* target_count*/
|
||||
TYPE_INT, /* open_count */
|
||||
TYPE_INT, /* flags */
|
||||
TYPE_INT, /* event_nr */
|
||||
TYPE_INT, /* padding */
|
||||
TYPE_ULONGLONG, /* dev */
|
||||
MK_ARRAY(TYPE_CHAR, 128), /* name */
|
||||
MK_ARRAY(TYPE_CHAR, 129), /* uuid */
|
||||
MK_ARRAY(TYPE_CHAR, 7)) /* data */
|
||||
|
||||
STRUCT(dm_target_spec,
|
||||
TYPE_ULONGLONG, /* sector_start */
|
||||
TYPE_ULONGLONG, /* length */
|
||||
TYPE_INT, /* status */
|
||||
TYPE_INT, /* next */
|
||||
MK_ARRAY(TYPE_CHAR, 16)) /* target_type */
|
||||
|
||||
STRUCT(dm_target_deps,
|
||||
TYPE_INT, /* count */
|
||||
TYPE_INT) /* padding */
|
||||
|
||||
STRUCT(dm_name_list,
|
||||
TYPE_ULONGLONG, /* dev */
|
||||
TYPE_INT) /* next */
|
||||
|
||||
STRUCT(dm_target_versions,
|
||||
TYPE_INT, /* next */
|
||||
MK_ARRAY(TYPE_INT, 3)) /* version*/
|
||||
|
||||
STRUCT(dm_target_msg,
|
||||
TYPE_ULONGLONG) /* sector */
|
||||
|
||||
STRUCT(fiemap_extent,
|
||||
TYPE_ULONGLONG, /* fe_logical */
|
||||
TYPE_ULONGLONG, /* fe_physical */
|
||||
|
@ -216,6 +216,9 @@ typedef struct CPUARMState {
|
||||
uint32_t cregs[16];
|
||||
} iwmmxt;
|
||||
|
||||
/* For mixed endian mode. */
|
||||
bool bswap_code;
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* For usermode syscall translation. */
|
||||
int eabi;
|
||||
@ -491,7 +494,9 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
|
||||
#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT)
|
||||
#define ARM_TBFLAG_CONDEXEC_SHIFT 8
|
||||
#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||
/* Bits 31..16 are currently unused. */
|
||||
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
|
||||
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
||||
/* Bits 31..17 are currently unused. */
|
||||
|
||||
/* some convenience accessor macros */
|
||||
#define ARM_TBFLAG_THUMB(F) \
|
||||
@ -506,6 +511,8 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
|
||||
(((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
|
||||
#define ARM_TBFLAG_CONDEXEC(F) \
|
||||
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||
#define ARM_TBFLAG_BSWAP_CODE(F) \
|
||||
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
@ -516,7 +523,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
||||
*flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
|
||||
| (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
|
||||
| (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
|
||||
| (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT);
|
||||
| (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||
| (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
|
||||
} else {
|
||||
@ -543,4 +551,24 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb)
|
||||
env->regs[15] = tb->pc;
|
||||
}
|
||||
|
||||
/* Load an instruction and return it in the standard little-endian order */
|
||||
static inline uint32_t arm_ldl_code(uint32_t addr, bool do_swap)
|
||||
{
|
||||
uint32_t insn = ldl_code(addr);
|
||||
if (do_swap) {
|
||||
return bswap32(insn);
|
||||
}
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Ditto, for a halfword (Thumb) instruction */
|
||||
static inline uint16_t arm_lduw_code(uint32_t addr, bool do_swap)
|
||||
{
|
||||
uint16_t insn = lduw_code(addr);
|
||||
if (do_swap) {
|
||||
return bswap16(insn);
|
||||
}
|
||||
return insn;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -842,7 +842,7 @@ static void do_interrupt_v7m(CPUARMState *env)
|
||||
case EXCP_BKPT:
|
||||
if (semihosting_enabled) {
|
||||
int nr;
|
||||
nr = lduw_code(env->regs[15]) & 0xff;
|
||||
nr = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
|
||||
if (nr == 0xab) {
|
||||
env->regs[15] += 2;
|
||||
env->regs[0] = do_arm_semihosting(env);
|
||||
@ -914,9 +914,10 @@ void do_interrupt(CPUARMState *env)
|
||||
if (semihosting_enabled) {
|
||||
/* Check for semihosting interrupt. */
|
||||
if (env->thumb) {
|
||||
mask = lduw_code(env->regs[15] - 2) & 0xff;
|
||||
mask = arm_lduw_code(env->regs[15] - 2, env->bswap_code) & 0xff;
|
||||
} else {
|
||||
mask = ldl_code(env->regs[15] - 4) & 0xffffff;
|
||||
mask = arm_ldl_code(env->regs[15] - 4, env->bswap_code)
|
||||
& 0xffffff;
|
||||
}
|
||||
/* Only intercept calls from privileged modes, to provide some
|
||||
semblance of security. */
|
||||
@ -936,7 +937,7 @@ void do_interrupt(CPUARMState *env)
|
||||
case EXCP_BKPT:
|
||||
/* See if this is a semihosting syscall. */
|
||||
if (env->thumb && semihosting_enabled) {
|
||||
mask = lduw_code(env->regs[15]) & 0xff;
|
||||
mask = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
|
||||
if (mask == 0xab
|
||||
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
|
||||
env->regs[15] += 2;
|
||||
|
@ -59,6 +59,7 @@ typedef struct DisasContext {
|
||||
struct TranslationBlock *tb;
|
||||
int singlestep_enabled;
|
||||
int thumb;
|
||||
int bswap_code;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
int user;
|
||||
#endif
|
||||
@ -6705,7 +6706,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
|
||||
TCGv addr;
|
||||
TCGv_i64 tmp64;
|
||||
|
||||
insn = ldl_code(s->pc);
|
||||
insn = arm_ldl_code(s->pc, s->bswap_code);
|
||||
s->pc += 4;
|
||||
|
||||
/* M variants do not implement ARM mode. */
|
||||
@ -8133,7 +8134,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
||||
/* Fall through to 32-bit decode. */
|
||||
}
|
||||
|
||||
insn = lduw_code(s->pc);
|
||||
insn = arm_lduw_code(s->pc, s->bswap_code);
|
||||
s->pc += 2;
|
||||
insn |= (uint32_t)insn_hw1 << 16;
|
||||
|
||||
@ -9163,7 +9164,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
insn = lduw_code(s->pc);
|
||||
insn = arm_lduw_code(s->pc, s->bswap_code);
|
||||
s->pc += 2;
|
||||
|
||||
switch (insn >> 12) {
|
||||
@ -9872,6 +9873,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
|
||||
dc->singlestep_enabled = env->singlestep_enabled;
|
||||
dc->condjmp = 0;
|
||||
dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
|
||||
dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
|
||||
dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
|
||||
dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
@ -10105,7 +10107,8 @@ done_generating:
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
||||
qemu_log("----------------\n");
|
||||
qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
||||
log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
|
||||
log_target_disas(pc_start, dc->pc - pc_start,
|
||||
dc->thumb | (dc->bswap_code << 1));
|
||||
qemu_log("\n");
|
||||
}
|
||||
#endif
|
||||
|
28
thunk.c
28
thunk.c
@ -46,6 +46,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr)
|
||||
case TYPE_LONG:
|
||||
case TYPE_ULONG:
|
||||
case TYPE_PTRVOID:
|
||||
case TYPE_OLDDEVT:
|
||||
return type_ptr;
|
||||
case TYPE_PTR:
|
||||
return thunk_type_next_ptr(type_ptr);
|
||||
@ -188,6 +189,33 @@ const argtype *thunk_convert(void *dst, const void *src,
|
||||
#else
|
||||
#warning unsupported conversion
|
||||
#endif
|
||||
case TYPE_OLDDEVT:
|
||||
{
|
||||
uint64_t val = 0;
|
||||
switch (thunk_type_size(type_ptr - 1, !to_host)) {
|
||||
case 2:
|
||||
val = *(uint16_t *)src;
|
||||
break;
|
||||
case 4:
|
||||
val = *(uint32_t *)src;
|
||||
break;
|
||||
case 8:
|
||||
val = *(uint64_t *)src;
|
||||
break;
|
||||
}
|
||||
switch (thunk_type_size(type_ptr - 1, to_host)) {
|
||||
case 2:
|
||||
*(uint16_t *)dst = tswap16(val);
|
||||
break;
|
||||
case 4:
|
||||
*(uint32_t *)dst = tswap32(val);
|
||||
break;
|
||||
case 8:
|
||||
*(uint64_t *)dst = tswap64(val);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
int array_length, i, dst_size, src_size;
|
||||
|
28
thunk.h
28
thunk.h
@ -37,6 +37,7 @@ typedef enum argtype {
|
||||
TYPE_PTR,
|
||||
TYPE_ARRAY,
|
||||
TYPE_STRUCT,
|
||||
TYPE_OLDDEVT,
|
||||
} argtype;
|
||||
|
||||
#define MK_PTR(type) TYPE_PTR, type
|
||||
@ -104,6 +105,31 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
|
||||
return TARGET_ABI_BITS / 8;
|
||||
}
|
||||
break;
|
||||
case TYPE_OLDDEVT:
|
||||
if (is_host) {
|
||||
#if defined(HOST_X86_64)
|
||||
return 8;
|
||||
#elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \
|
||||
defined(HOST_PARISC) || defined(HOST_SPARC64)
|
||||
return 4;
|
||||
#elif defined(HOST_PPC)
|
||||
return HOST_LONG_SIZE;
|
||||
#else
|
||||
return 2;
|
||||
#endif
|
||||
} else {
|
||||
#if defined(TARGET_X86_64)
|
||||
return 8;
|
||||
#elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \
|
||||
defined(TARGET_PARISC) || defined(TARGET_SPARC64)
|
||||
return 4;
|
||||
#elif defined(TARGET_PPC)
|
||||
return TARGET_ABI_BITS / 8;
|
||||
#else
|
||||
return 2;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
size = type_ptr[1];
|
||||
return size * thunk_type_size_array(type_ptr + 2, is_host);
|
||||
@ -141,6 +167,8 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
|
||||
return TARGET_ABI_BITS / 8;
|
||||
}
|
||||
break;
|
||||
case TYPE_OLDDEVT:
|
||||
return thunk_type_size(type_ptr, is_host);
|
||||
case TYPE_ARRAY:
|
||||
return thunk_type_align_array(type_ptr + 2, is_host);
|
||||
case TYPE_STRUCT:
|
||||
|
Loading…
Reference in New Issue
Block a user