diff options
64 files changed, 974 insertions, 250 deletions
diff --git a/CODING_STYLE b/CODING_STYLE index 7c82d4d0af..dcbce28a27 100644 --- a/CODING_STYLE +++ b/CODING_STYLE @@ -1,4 +1,4 @@ -Qemu Coding Style +QEMU Coding Style ================= Please use the script checkpatch.pl in the scripts directory to check @@ -217,6 +217,7 @@ clean: rm -f *.o *.d *.a *.lo $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~ rm -Rf .libs rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d + rm -f qom/*.o qom/*.d rm -f qemu-img-cmds.h rm -f trace/*.o trace/*.d rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp diff --git a/Makefile.target b/Makefile.target index 999a968abe..14c8fa18fc 100644 --- a/Makefile.target +++ b/Makefile.target @@ -96,7 +96,7 @@ libobj-$(TARGET_ARM) += cpu.o libobj-$(TARGET_S390X) += cpu.o ifeq ($(TARGET_BASE_ARCH), sparc) libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o -libobj-y += cpu_init.o +libobj-y += cpu.o endif libobj-$(TARGET_SPARC) += int32_helper.o libobj-$(TARGET_SPARC64) += int64_helper.o diff --git a/block/curl.c b/block/curl.c index e9102e3e20..a909eca337 100644 --- a/block/curl.c +++ b/block/curl.c @@ -282,7 +282,7 @@ static CURLState *curl_init_state(BDRVCURLState *s) break; } if (!state) { - usleep(100); + g_usleep(100); curl_multi_do(s); } } while(!state); @@ -519,14 +519,14 @@ EOF if compile_prog "" "-liberty" ; then LIBS="-liberty $LIBS" fi - prefix="c:/Program Files/Qemu" + prefix="c:/Program Files/QEMU" mandir="\${prefix}" datadir="\${prefix}" docdir="\${prefix}" bindir="\${prefix}" sysconfdir="\${prefix}" confsuffix="" - libs_qga="-lws2_32 -lwinmm -lpowrprof $lib_qga" + libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga" fi werror="" @@ -1993,13 +1993,21 @@ fi ########################################## # glib support probe -if $pkg_config --modversion gthread-2.0 > /dev/null 2>&1 ; then + +if test "$mingw32" = yes; then + # g_poll is required in order to integrate with the glib main loop. + glib_req_ver=2.20 +else + glib_req_ver=2.12 +fi +if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 > /dev/null 2>&1 +then glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null` glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null` LIBS="$glib_libs $LIBS" libs_qga="$glib_libs $libs_qga" else - echo "glib-2.0 required to compile QEMU" + echo "glib-$glib_req_ver required to compile QEMU" exit 1 fi @@ -2672,7 +2680,8 @@ if test "$trace_backend" = "ust"; then int main(void) { return 0; } EOF if compile_prog "" "" ; then - LIBS="-lust $LIBS" + LIBS="-lust -lurcu-bp $LIBS" + libs_qga="-lust -lurcu-bp $libs_qga" else echo echo "Error: Trace backend 'ust' missing libust header files" @@ -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 @@ -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 @@ -11,7 +11,6 @@ #define DMA_H #include <stdio.h> -//#include "cpu.h" #include "hw/hw.h" #include "block.h" diff --git a/docs/ccid.txt b/docs/ccid.txt index b8e504a3cc..450a66ad99 100644 --- a/docs/ccid.txt +++ b/docs/ccid.txt @@ -1,4 +1,4 @@ -Qemu CCID Device Documentation. +QEMU CCID Device Documentation. Contents 1. USB CCID device diff --git a/docs/specs/ivshmem_device_spec.txt b/docs/specs/ivshmem_device_spec.txt index 23dd2ba89f..667a8628f0 100644 --- a/docs/specs/ivshmem_device_spec.txt +++ b/docs/specs/ivshmem_device_spec.txt @@ -24,7 +24,7 @@ The device currently supports 4 registers of 32-bits each. Registers are used for synchronization between guests sharing the same memory object when interrupts are supported (this requires using the shared memory server). -The server assigns each VM an ID number and sends this ID number to the Qemu +The server assigns each VM an ID number and sends this ID number to the QEMU process when the guest starts. enum ivshmem_registers { @@ -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 diff --git a/exec-all.h b/exec-all.h index 93a5b22c1c..fa7bdfecd8 100644 --- a/exec-all.h +++ b/exec-all.h @@ -85,15 +85,15 @@ void cpu_gen_init(void); int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb, int *gen_code_size_ptr); int cpu_restore_state(struct TranslationBlock *tb, - CPUArchState *env, unsigned long searched_pc); -void cpu_resume_from_signal(CPUArchState *env1, void *puc); -void cpu_io_recompile(CPUArchState *env, void *retaddr); + CPUArchState *env, uintptr_t searched_pc); +void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc); +void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, void *retaddr); TranslationBlock *tb_gen_code(CPUArchState *env, target_ulong pc, target_ulong cs_base, int flags, int cflags); void cpu_exec_init(CPUArchState *env); void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1); -int page_unprotect(target_ulong address, unsigned long pc, void *puc); +int page_unprotect(target_ulong address, uintptr_t pc, void *puc); void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, int is_cpu_write_access); void tlb_flush_page(CPUArchState *env, target_ulong addr); @@ -150,7 +150,7 @@ struct TranslationBlock { #ifdef USE_DIRECT_JUMP uint16_t tb_jmp_offset[2]; /* offset of jump instruction */ #else - unsigned long tb_next[2]; /* address of jump generated code */ + uintptr_t tb_next[2]; /* address of jump generated code */ #endif /* list of TBs jumping to this one. This is a circular list using the two least significant bits of the pointers to tell what is @@ -202,14 +202,14 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr); #define tb_set_jmp_target1 ppc_tb_set_jmp_target #elif defined(__i386__) || defined(__x86_64__) -static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) +static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) { /* patch the branch destination */ *(uint32_t *)jmp_addr = addr - (jmp_addr + 4); /* no need to flush icache explicitly */ } #elif defined(__arm__) -static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) +static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) { #if !QEMU_GNUC_PREREQ(4, 1) register unsigned long _beg __asm ("a1"); @@ -237,19 +237,17 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr #endif static inline void tb_set_jmp_target(TranslationBlock *tb, - int n, unsigned long addr) + int n, uintptr_t addr) { - unsigned long offset; - - offset = tb->tb_jmp_offset[n]; - tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr); + uint16_t offset = tb->tb_jmp_offset[n]; + tb_set_jmp_target1((uintptr_t)(tb->tc_ptr + offset), addr); } #else /* set the jump target */ static inline void tb_set_jmp_target(TranslationBlock *tb, - int n, unsigned long addr) + int n, uintptr_t addr) { tb->tb_next[n] = addr; } @@ -262,15 +260,15 @@ static inline void tb_add_jump(TranslationBlock *tb, int n, /* NOTE: this test is only needed for thread safety */ if (!tb->jmp_next[n]) { /* patch the native jump address */ - tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr); + tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc_ptr); /* add in TB jmp circular list */ tb->jmp_next[n] = tb_next->jmp_first; - tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n)); + tb_next->jmp_first = (TranslationBlock *)((uintptr_t)(tb) | (n)); } } -TranslationBlock *tb_find_pc(unsigned long pc_ptr); +TranslationBlock *tb_find_pc(uintptr_t pc_ptr); #include "qemu-lock.h" @@ -288,13 +286,14 @@ extern void *tci_tb_ptr; # define GETPC() tci_tb_ptr # endif #elif defined(__s390__) && !defined(__s390x__) -# define GETPC() ((void*)(((unsigned long)__builtin_return_address(0) & 0x7fffffffUL) - 1)) +# define GETPC() \ + ((void *)(((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1)) #elif defined(__arm__) /* Thumb return addresses have the low bit set, so we need to subtract two. This is still safe in ARM mode because instructions are 4 bytes. */ -# define GETPC() ((void *)((unsigned long)__builtin_return_address(0) - 2)) +# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 2)) #else -# define GETPC() ((void *)((unsigned long)__builtin_return_address(0) - 1)) +# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 1)) #endif #if !defined(CONFIG_USER_ONLY) @@ -1380,7 +1380,7 @@ void tb_link_page(TranslationBlock *tb, /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr < tb[1].tc_ptr. Return NULL if not found */ -TranslationBlock *tb_find_pc(unsigned long tc_ptr) +TranslationBlock *tb_find_pc(uintptr_t tc_ptr) { int m_min, m_max, m; unsigned long v; @@ -2502,7 +2502,7 @@ int page_check_range(target_ulong start, target_ulong len, int flags) /* called from signal handler: invalidate the code and unprotect the page. Return TRUE if the fault was successfully handled. */ -int page_unprotect(target_ulong address, unsigned long pc, void *puc) +int page_unprotect(target_ulong address, uintptr_t pc, void *puc) { unsigned int prot; PageDesc *p; @@ -4484,7 +4484,7 @@ void cpu_io_recompile(CPUArchState *env, void *retaddr) target_ulong pc, cs_base; uint64_t flags; - tb = tb_find_pc((unsigned long)retaddr); + tb = tb_find_pc((uintptr_t)retaddr); if (!tb) { cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", retaddr); diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 81a7d1ae09..d37090ac53 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -117,7 +117,7 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM) int8 roundingMode; flag roundNearestEven; int8 roundIncrement, roundBits; - int32 z; + int32_t z; roundingMode = STATUS(float_rounding_mode); roundNearestEven = ( roundingMode == float_round_nearest_even ); @@ -166,7 +166,7 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU { int8 roundingMode; flag roundNearestEven, increment; - int64 z; + int64_t z; roundingMode = STATUS(float_rounding_mode); roundNearestEven = ( roundingMode == float_round_nearest_even ); @@ -1378,7 +1378,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM ) flag aSign; int16 aExp, shiftCount; uint32_t aSig; - int32 z; + int32_t z; a = float32_squash_input_denormal(a STATUS_VAR); aSig = extractFloat32Frac( a ); @@ -2762,7 +2762,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM ) flag aSign; int16 aExp, shiftCount; uint64_t aSig, savedASig; - int32 z; + int32_t z; a = float64_squash_input_denormal(a STATUS_VAR); aSig = extractFloat64Frac( a ); @@ -4248,7 +4248,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM ) flag aSign; int32 aExp, shiftCount; uint64_t aSig, savedASig; - int32 z; + int32_t z; aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); @@ -5277,7 +5277,7 @@ int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM ) flag aSign; int32 aExp, shiftCount; uint64_t aSig0, aSig1, savedASig; - int32 z; + int32_t z; aSig1 = extractFloat128Frac1( a ); aSig0 = extractFloat128Frac0( a ); diff --git a/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi index faa0434480..e60e3b9465 100644 --- a/fsdev/virtfs-proxy-helper.texi +++ b/fsdev/virtfs-proxy-helper.texi @@ -24,7 +24,7 @@ in non-root mode, but doing privileged operations using socket IO. Proxy helper(a stand alone binary part of qemu) is invoked with root privileges. Proxy helper chroots into 9p export path and creates a socket pair or a named socket based on the command line parameter. -Qemu and proxy helper communicate using this socket. QEMU proxy fs +QEMU and proxy helper communicate using this socket. QEMU proxy fs driver sends filesystem request to proxy helper and receives the response from it. diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 64e1cd968e..b80aa8f1de 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -565,7 +565,7 @@ static void ivshmem_setup_msi(IVShmemState * s) { msix_vector_use(&s->dev, i); } - /* allocate Qemu char devices for receiving interrupts */ + /* allocate QEMU char devices for receiving interrupts */ s->eventfd_table = g_malloc0(s->vectors * sizeof(EventfdEntry)); } @@ -776,7 +776,7 @@ static void load_linux(void *fw_cfg, } /* loader type */ - /* High nybble = B reserved for Qemu; low nybble is revision number. + /* High nybble = B reserved for QEMU; low nybble is revision number. If this code is substantially changed, you may want to consider incrementing the revision. */ if (protocol >= 0x200) diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index ff154c7aa9..8b37336001 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -51,7 +51,6 @@ static void machine_cpu_reset(CPUMBState *env) { - /* FIXME: move to machine specfic cpu reset */ env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family. */ } diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c index 220c81d06e..f0a3ae49e6 100644 --- a/hw/ppc440_bamboo.c +++ b/hw/ppc440_bamboo.c @@ -1,5 +1,5 @@ /* - * Qemu PowerPC 440 Bamboo board emulation + * QEMU PowerPC 440 Bamboo board emulation * * Copyright 2007 IBM Corporation. * Authors: diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 5ee8cb34c1..f1dfbe181c 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -1,5 +1,5 @@ /* - * Qemu PowerPC MPC8544DS board emualtion + * QEMU PowerPC MPC8544DS board emulation * * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved. * @@ -88,7 +88,7 @@ typedef struct { typedef struct { PS2State common; int scan_enabled; - /* Qemu uses translated PC scancodes internally. To avoid multiple + /* QEMU uses translated PC scancodes internally. To avoid multiple conversions we do the translation (if any) in the PS/2 emulation not the keyboard controller. */ int translate; diff --git a/hw/sun4m.c b/hw/sun4m.c index 7bcbf37e98..34088ad185 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -932,8 +932,8 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14], display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1); - // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device - // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device + /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device + Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15], serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); @@ -1581,8 +1581,8 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[12], display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1); - // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device - // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device + /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device + Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ escc_init(hwdef->serial_base, sbi_irq[12], sbi_irq[12], serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); @@ -1762,8 +1762,8 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[1], display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1); - // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device - // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device + /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device + Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ escc_init(hwdef->serial_base, slavio_irq[1], slavio_irq[1], serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); @@ -385,7 +385,7 @@ static void portio_list_add_1(PortioList *piolist, * rather than an offset relative to to start + off_low. */ memory_region_init_io(region, ops, piolist->opaque, piolist->name, - UINT64_MAX); + INT64_MAX); memory_region_init_alias(alias, piolist->name, region, start + off_low, off_high - off_low); memory_region_add_subregion(piolist->address_space, diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h index 7f05879ea3..5356395659 100644 --- a/linux-user/arm/syscall_nr.h +++ b/linux-user/arm/syscall_nr.h @@ -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) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index e502b39007..f3b1552e9e 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -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; diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 6514502dc4..eb96a084c2 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -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))) diff --git a/linux-user/main.c b/linux-user/main.c index 962677e01d..191b75060d 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -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) { diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 994c02bb77..7125d1cd4b 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -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; + } + + if (start == mmap_next_start) { + mmap_next_start = addr; } - mmap_next_start = addr; - return last_addr; + + return addr; } #endif diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 68895671ed..7b299b7bc3 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -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); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9f5e53a7fe..8a92162155 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -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) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 41f0ff8c7d..a79b67df49 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -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 diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index c370125170..601618df98 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -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 */ diff --git a/main-loop.c b/main-loop.c index db23de0497..1ebdc4baf1 100644 --- a/main-loop.c +++ b/main-loop.c @@ -164,7 +164,7 @@ static int qemu_signal_init(void) #else /* _WIN32 */ -HANDLE qemu_event_handle = NULL; +static HANDLE qemu_event_handle = NULL; static void dummy_event_handler(void *opaque) { @@ -218,17 +218,19 @@ int main_loop_init(void) return 0; } - +static fd_set rfds, wfds, xfds; +static int nfds; static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ static int n_poll_fds; static int max_priority; +#ifndef _WIN32 static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds, - fd_set *xfds, struct timeval *tv) + fd_set *xfds, int *cur_timeout) { GMainContext *context = g_main_context_default(); int i; - int timeout = 0, cur_timeout; + int timeout = 0; g_main_context_prepare(context, &max_priority); @@ -253,10 +255,8 @@ static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds, } } - cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000); - if (timeout >= 0 && timeout < cur_timeout) { - tv->tv_sec = timeout / 1000; - tv->tv_usec = (timeout % 1000) * 1000; + if (timeout >= 0 && timeout < *cur_timeout) { + *cur_timeout = timeout; } } @@ -288,7 +288,29 @@ static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds, } } -#ifdef _WIN32 +static int os_host_main_loop_wait(int timeout) +{ + struct timeval tv; + int ret; + + glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout); + + if (timeout > 0) { + qemu_mutex_unlock_iothread(); + } + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); + + if (timeout > 0) { + qemu_mutex_lock_iothread(); + } + + glib_select_poll(&rfds, &wfds, &xfds, (ret < 0)); + return ret; +} +#else /***********************************************************/ /* Polling handling */ @@ -328,6 +350,7 @@ void qemu_del_polling_cb(PollingFunc *func, void *opaque) /* Wait objects support */ typedef struct WaitObjects { int num; + int revents[MAXIMUM_WAIT_OBJECTS + 1]; HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1]; void *opaque[MAXIMUM_WAIT_OBJECTS + 1]; @@ -344,6 +367,7 @@ int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) w->events[w->num] = handle; w->func[w->num] = func; w->opaque[w->num] = opaque; + w->revents[w->num] = 0; w->num++; return 0; } @@ -362,6 +386,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) w->events[i] = w->events[i + 1]; w->func[i] = w->func[i + 1]; w->opaque[i] = w->opaque[i + 1]; + w->revents[i] = w->revents[i + 1]; } } if (found) { @@ -369,61 +394,76 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) } } -static void os_host_main_loop_wait(int *timeout) +void qemu_fd_register(int fd) { - int ret, ret2, i; + WSAEventSelect(fd, qemu_event_handle, FD_READ | FD_ACCEPT | FD_CLOSE | + FD_CONNECT | FD_WRITE | FD_OOB); +} + +static int os_host_main_loop_wait(int timeout) +{ + GMainContext *context = g_main_context_default(); + int ret, i; PollingEntry *pe; + WaitObjects *w = &wait_objects; + static struct timeval tv0; /* XXX: need to suppress polling by better using win32 events */ ret = 0; for (pe = first_polling_entry; pe != NULL; pe = pe->next) { ret |= pe->func(pe->opaque); } - if (ret == 0) { - int err; - WaitObjects *w = &wait_objects; + if (ret != 0) { + return ret; + } - qemu_mutex_unlock_iothread(); - ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout); - qemu_mutex_lock_iothread(); - if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) { - if (w->func[ret - WAIT_OBJECT_0]) { - w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]); - } + if (nfds >= 0) { + ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); + if (ret != 0) { + timeout = 0; + } + } + + g_main_context_prepare(context, &max_priority); + n_poll_fds = g_main_context_query(context, max_priority, &timeout, + poll_fds, ARRAY_SIZE(poll_fds)); + g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds)); - /* Check for additional signaled events */ - for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) { - /* Check if event is signaled */ - ret2 = WaitForSingleObject(w->events[i], 0); - if (ret2 == WAIT_OBJECT_0) { - if (w->func[i]) { - w->func[i](w->opaque[i]); - } - } else if (ret2 != WAIT_TIMEOUT) { - err = GetLastError(); - fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err); - } + for (i = 0; i < w->num; i++) { + poll_fds[n_poll_fds + i].fd = (DWORD) w->events[i]; + poll_fds[n_poll_fds + i].events = G_IO_IN; + } + + qemu_mutex_unlock_iothread(); + ret = g_poll(poll_fds, n_poll_fds + w->num, timeout); + qemu_mutex_lock_iothread(); + if (ret > 0) { + for (i = 0; i < w->num; i++) { + w->revents[i] = poll_fds[n_poll_fds + i].revents; + } + for (i = 0; i < w->num; i++) { + if (w->revents[i] && w->func[i]) { + w->func[i](w->opaque[i]); } - } else if (ret != WAIT_TIMEOUT) { - err = GetLastError(); - fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err); } } - *timeout = 0; -} -#else -static inline void os_host_main_loop_wait(int *timeout) -{ + if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) { + g_main_context_dispatch(context); + } + + /* If an edge-triggered socket event occurred, select will return a + * positive result on the next iteration. We do not need to do anything + * here. + */ + + return ret; } #endif int main_loop_wait(int nonblocking) { - fd_set rfds, wfds, xfds; - int ret, nfds; - struct timeval tv; - int timeout; + int ret, timeout; if (nonblocking) { timeout = 0; @@ -432,11 +472,6 @@ int main_loop_wait(int nonblocking) qemu_bh_update_timeout(&timeout); } - os_host_main_loop_wait(&timeout); - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - /* poll any events */ /* XXX: separate device handlers from system ones */ nfds = -1; @@ -448,19 +483,7 @@ int main_loop_wait(int nonblocking) slirp_select_fill(&nfds, &rfds, &wfds, &xfds); #endif qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds); - glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv); - - if (timeout > 0) { - qemu_mutex_unlock_iothread(); - } - - ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); - - if (timeout > 0) { - qemu_mutex_lock_iothread(); - } - - glib_select_poll(&rfds, &wfds, &xfds, (ret < 0)); + ret = os_host_main_loop_wait(timeout); qemu_iohandler_poll(&rfds, &wfds, &xfds, ret); #ifdef CONFIG_SLIRP slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0)); diff --git a/main-loop.h b/main-loop.h index 4987041ce7..e743aa0cf6 100644 --- a/main-loop.h +++ b/main-loop.h @@ -359,6 +359,7 @@ void qemu_mutex_unlock_iothread(void); /* internal interfaces */ +void qemu_fd_register(int fd); void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc); @@ -1444,6 +1444,11 @@ static void listener_add_address_space(MemoryListener *listener, { FlatRange *fr; + if (listener->address_space_filter + && listener->address_space_filter != as->root) { + return; + } + if (global_dirty_log) { listener->log_global_start(listener); } @@ -1621,6 +1626,13 @@ void mtree_info(fprintf_function mon_printf, void *f) mon_printf(f, "memory\n"); mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head); + if (address_space_io.root && + !QTAILQ_EMPTY(&address_space_io.root->subregions)) { + mon_printf(f, "I/O\n"); + mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head); + } + + mon_printf(f, "aliases\n"); /* print aliased regions */ QTAILQ_FOREACH(ml, &ml_head, queue) { if (!ml->printed) { @@ -1632,11 +1644,4 @@ void mtree_info(fprintf_function mon_printf, void *f) QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) { g_free(ml); } - - if (address_space_io.root && - !QTAILQ_EMPTY(&address_space_io.root->subregions)) { - QTAILQ_INIT(&ml_head); - mon_printf(f, "I/O\n"); - mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head); - } } diff --git a/oslib-win32.c b/oslib-win32.c index ce3021e6c7..ffbc6d0c9f 100644 --- a/oslib-win32.c +++ b/oslib-win32.c @@ -28,6 +28,7 @@ #include <windows.h> #include "config-host.h" #include "sysemu.h" +#include "main-loop.h" #include "trace.h" #include "qemu_socket.h" @@ -76,6 +77,7 @@ void qemu_vfree(void *ptr) void socket_set_block(int fd) { unsigned long opt = 0; + WSAEventSelect(fd, NULL, 0); ioctlsocket(fd, FIONBIO, &opt); } @@ -83,6 +85,7 @@ void socket_set_nonblock(int fd) { unsigned long opt = 1; ioctlsocket(fd, FIONBIO, &opt); + qemu_fd_register(fd); } int inet_aton(const char *cp, struct in_addr *ia) @@ -5152,7 +5152,7 @@ powerpc_dialect (struct disassemble_info *info) return dialect; } -/* Qemu default */ +/* QEMU default */ int print_insn_ppc (bfd_vma memaddr, struct disassemble_info *info) { diff --git a/qemu-doc.texi b/qemu-doc.texi index 83b2ad5237..9e07ba6c1b 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -968,7 +968,7 @@ monitor (@pxref{pcsys_keys}). QEMU emulates a PCI UHCI USB controller. You can virtually plug virtual USB devices or real host USB devices (experimental, works only -on Linux hosts). Qemu will automatically create and connect virtual USB hubs +on Linux hosts). QEMU will automatically create and connect virtual USB hubs as necessary to connect multiple USB devices. @menu @@ -2709,9 +2709,9 @@ MinGW's default header and linker search paths. @file{make}. If you have problems using SDL, verify that @file{sdl-config} can be launched from the MSYS command line. -@item You can install QEMU in @file{Program Files/Qemu} by typing +@item You can install QEMU in @file{Program Files/QEMU} by typing @file{make install}. Don't forget to copy @file{SDL.dll} in -@file{Program Files/Qemu}. +@file{Program Files/QEMU}. @end itemize @@ -2745,7 +2745,7 @@ The example assumes @file{sdl-config} is installed under @file{/usr/i686-pc-ming MinGW cross compilation tools have names like @file{i686-pc-mingw32-gcc} and @file{i686-pc-mingw32-strip}. We set the @code{PATH} environment variable to ensure the MinGW version of @file{sdl-config} is used and use --cross-prefix to specify the name of the cross compiler. -You can also use --prefix to set the Win32 install path which defaults to @file{c:/Program Files/Qemu}. +You can also use --prefix to set the Win32 install path which defaults to @file{c:/Program Files/QEMU}. Under Fedora Linux, you can run: @example diff --git a/qemu-nbd.texi b/qemu-nbd.texi index 44996cc650..6955d90327 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -6,7 +6,7 @@ usage: qemu-nbd [OPTION]... @var{filename} @c man begin DESCRIPTION -Export Qemu disk image using NBD protocol. +Export QEMU disk image using NBD protocol. @c man end diff --git a/qemu-options.hx b/qemu-options.hx index f72f9a0fdf..a169792f07 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1310,7 +1310,7 @@ and a @var{name} can be assigned for use in monitor commands. Optionally, for PCI cards, you can specify the number @var{v} of MSI-X vectors that the card should have; this option currently only affects virtio cards; set @var{v} = 0 to disable MSI-X. If no @option{-net} option is specified, a single -NIC is created. Qemu can emulate several different models of network card. +NIC is created. QEMU can emulate several different models of network card. Valid values for @var{type} are @code{virtio}, @code{i82551}, @code{i82557b}, @code{i82559er}, @code{ne2k_pci}, @code{ne2k_isa}, @code{pcnet}, @code{rtl8139}, @@ -2133,7 +2133,7 @@ activates telnet remote echo and single char transfer, then you can use the following options to step up a netcat redirector to allow telnet on port 5555 to access the qemu port. @table @code -@item Qemu Options: +@item QEMU Options: -serial udp::4555@@:4556 @item netcat options: -u -P 4555 -L 0.0.0.0:4556 -t -p 5555 -I -T diff --git a/qemu-queue.h b/qemu-queue.h index 74d7122e4d..9288cd8e82 100644 --- a/qemu-queue.h +++ b/qemu-queue.h @@ -1,7 +1,7 @@ /* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */ /* - * Qemu version: Copy from netbsd, removed debug code, removed some of + * QEMU version: Copy from netbsd, removed debug code, removed some of * the implementations. Left in singly-linked lists, lists, simple * queues, and tail queues. */ diff --git a/qemu_socket.h b/qemu_socket.h index fe4cf6ca61..51ad210a7f 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -8,7 +8,9 @@ #include <ws2tcpip.h> #define socket_error() WSAGetLastError() +#undef EWOULDBLOCK #undef EINTR +#undef EINPROGRESS #define EWOULDBLOCK WSAEWOULDBLOCK #define EINTR WSAEINTR #define EINPROGRESS WSAEINPROGRESS @@ -156,7 +156,8 @@ static void qtest_send_prefix(CharDriverState *chr) tv.tv_sec, tv.tv_usec); } -static void qtest_send(CharDriverState *chr, const char *fmt, ...) +static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr, + const char *fmt, ...) { va_list ap; char buffer[1024]; diff --git a/target-alpha/STATUS b/target-alpha/STATUS index 742e370b90..6c9744569e 100644 --- a/target-alpha/STATUS +++ b/target-alpha/STATUS @@ -4,7 +4,7 @@ Alpha emulation structure: cpu.h : CPU definitions globally exported exec.h : CPU definitions used only for translated code execution helper.c : helpers that can be called either by the translated code - or the Qemu core, including the exception handler. + or the QEMU core, including the exception handler. op_helper.c : helpers that can be called only from TCG helper.h : TCG helpers prototypes translate.c : Alpha instructions to micro-operations translator diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 6c5d28bae1..74bf7f7ff4 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -276,7 +276,7 @@ struct CPUAlphaState { target_ulong t0, t1; #endif - /* Those resources are used only in Qemu core */ + /* Those resources are used only in QEMU core */ CPU_COMMON int error_code; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index e176c5f65c..c208c804aa 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -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 diff --git a/target-arm/helper.c b/target-arm/helper.c index d974b579dc..28f127baf8 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -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; diff --git a/target-arm/translate.c b/target-arm/translate.c index 46d1d3ef9f..7a3c7d650c 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -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 diff --git a/target-mips/TODO b/target-mips/TODO index 9101881a97..2a3546f624 100644 --- a/target-mips/TODO +++ b/target-mips/TODO @@ -16,7 +16,7 @@ General Existing documentation is x86-centric. - Reverse endianness bit not implemented - The TLB emulation is very inefficient: - Qemu's softmmu implements a x86-style MMU, with separate entries + QEMU's softmmu implements a x86-style MMU, with separate entries for read/write/execute, a TLB index which is just a modulo of the virtual address, and a set of TLBs for each user/kernel/supervisor MMU mode. @@ -25,7 +25,7 @@ General up to 256 ASID tags as additional matching criterion (which roughly equates to 256 MMU modes). It also has a global flag which causes entries to match regardless of ASID. - To cope with these differences, Qemu currently flushes the TLB at + To cope with these differences, QEMU currently flushes the TLB at each ASID change. Using the MMU modes to implement ASIDs hinges on implementing the global bit efficiently. - save/restore of the CPU state is not implemented (see machine.c). diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 7430aa5086..257c4c462b 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -418,7 +418,7 @@ struct CPUMIPSState { /* We waste some space so we can handle shadow registers like TCs. */ TCState tcs[MIPS_SHADOW_SET_MAX]; CPUMIPSFPUContext fpus[MIPS_FPU_MAX]; - /* Qemu */ + /* QEMU */ int error_code; uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index ca6f1cb58c..e7fb3641a7 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -233,10 +233,10 @@ enum { POWERPC_EXCP_DTLBE = 93, /* Data TLB error */ /* EOL */ POWERPC_EXCP_NB = 96, - /* Qemu exceptions: used internally during code translation */ + /* QEMU exceptions: used internally during code translation */ POWERPC_EXCP_STOP = 0x200, /* stop translation */ POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */ - /* Qemu exceptions: special cases we want to stop translation */ + /* QEMU exceptions: special cases we want to stop translation */ POWERPC_EXCP_SYNC = 0x202, /* context synchronizing instruction */ POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only */ POWERPC_EXCP_STCX = 0x204 /* Conditional stores in user mode */ @@ -1041,7 +1041,7 @@ struct CPUPPCState { /* opcode handlers */ opc_handler_t *opcodes[0x40]; - /* Those resources are used only in Qemu core */ + /* Those resources are used only in QEMU core */ target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */ target_ulong hflags_nmsr; /* specific hflags, not coming from MSR */ int mmu_idx; /* precomputed MMU index to speed up mem accesses */ diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 39dcc273e5..e13b74993d 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -365,7 +365,7 @@ void ppc6xx_tlb_store (CPUPPCState *env, target_ulong EPN, int way, int is_code, tlb = &env->tlb.tlb6[nr]; LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1); - /* Invalidate any pending reference in Qemu for this virtual address */ + /* Invalidate any pending reference in QEMU for this virtual address */ __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1); tlb->pte0 = pte0; tlb->pte1 = pte1; @@ -729,7 +729,7 @@ void ppc_slb_invalidate_all (CPUPPCState *env) slb->esid &= ~SLB_ESID_V; /* XXX: given the fact that segment size is 256 MB or 1TB, * and we still don't have a tlb_flush_mask(env, n, mask) - * in Qemu, we just invalidate all TLBs + * in QEMU, we just invalidate all TLBs */ do_invalidate = 1; } @@ -752,7 +752,7 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0) /* XXX: given the fact that segment size is 256 MB or 1TB, * and we still don't have a tlb_flush_mask(env, n, mask) - * in Qemu, we just invalidate all TLBs + * in QEMU, we just invalidate all TLBs */ tlb_flush(env, 1); } @@ -2319,7 +2319,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) case POWERPC_MMU_2_06: /* tlbie invalidate TLBs for all segments */ /* XXX: given the fact that there are too many segments to invalidate, - * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu, + * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU, * we just invalidate all TLBs */ tlb_flush(env, 1); diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 724f4c7815..d929213a04 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -470,7 +470,7 @@ void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run) int r; unsigned irq; - /* PowerPC Qemu tracks the various core input pins (interrupt, critical + /* PowerPC QEMU tracks the various core input pins (interrupt, critical * interrupt, reset, etc) in PPC-specific env->irq_input_state. */ if (!cap_interrupt_level && run->ready_for_interrupt_injection && diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c index 24fc6bce3b..a2e49cd423 100644 --- a/target-ppc/kvm_ppc.c +++ b/target-ppc/kvm_ppc.c @@ -31,7 +31,7 @@ void kvmppc_init(void) { /* XXX The only reason KVM yields control back to qemu is device IO. Since * an idle guest does no IO, qemu's device model will never get a chance to - * run. So, until Qemu gains IO threads, we create this timer to ensure + * run. So, until QEMU gains IO threads, we create this timer to ensure * that the device model gets a chance to run. */ kvmppc_timer_rate = get_ticks_per_sec() / 10; kvmppc_timer = qemu_new_timer_ns(vm_clock, &kvmppc_timer_hack, NULL); diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 367eefaf9e..b1f87854a0 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -1796,17 +1796,17 @@ static void gen_spr_440 (CPUPPCState *env) static void gen_spr_40x (CPUPPCState *env) { /* Cache */ - /* not emulated, as Qemu do not emulate caches */ + /* not emulated, as QEMU do not emulate caches */ spr_register(env, SPR_40x_DCCR, "DCCR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x00000000); - /* not emulated, as Qemu do not emulate caches */ + /* not emulated, as QEMU do not emulate caches */ spr_register(env, SPR_40x_ICCR, "ICCR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x00000000); - /* not emulated, as Qemu do not emulate caches */ + /* not emulated, as QEMU do not emulate caches */ spr_register(env, SPR_BOOKE_ICDBDR, "ICDBDR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, SPR_NOACCESS, @@ -1974,7 +1974,7 @@ static void gen_spr_401_403 (CPUPPCState *env) SPR_NOACCESS, &spr_write_tbu, 0x00000000); /* Debug */ - /* not emulated, as Qemu do not emulate caches */ + /* not emulated, as QEMU do not emulate caches */ spr_register(env, SPR_403_CDBCR, "CDBCR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, @@ -2012,12 +2012,12 @@ static void gen_spr_401 (CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_40x_sler, 0x00000000); - /* not emulated, as Qemu never does speculative access */ + /* not emulated, as QEMU never does speculative access */ spr_register(env, SPR_40x_SGR, "SGR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0xFFFFFFFF); - /* not emulated, as Qemu do not emulate caches */ + /* not emulated, as QEMU do not emulate caches */ spr_register(env, SPR_40x_DCWR, "DCWR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, @@ -3436,12 +3436,12 @@ static void init_proc_403GCX (CPUPPCState *env) gen_spr_403_real(env); gen_spr_403_mmu(env); /* Bus access control */ - /* not emulated, as Qemu never does speculative access */ + /* not emulated, as QEMU never does speculative access */ spr_register(env, SPR_40x_SGR, "SGR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0xFFFFFFFF); - /* not emulated, as Qemu do not emulate caches */ + /* not emulated, as QEMU do not emulate caches */ spr_register(env, SPR_40x_DCWR, "DCWR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, @@ -3488,12 +3488,12 @@ static void init_proc_405 (CPUPPCState *env) gen_spr_40x(env); gen_spr_405(env); /* Bus access control */ - /* not emulated, as Qemu never does speculative access */ + /* not emulated, as QEMU never does speculative access */ spr_register(env, SPR_40x_SGR, "SGR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0xFFFFFFFF); - /* not emulated, as Qemu do not emulate caches */ + /* not emulated, as QEMU do not emulate caches */ spr_register(env, SPR_40x_DCWR, "DCWR", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, @@ -9442,13 +9442,13 @@ static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def) } if (env->irq_inputs == NULL) { fprintf(stderr, "WARNING: no internal IRQ controller registered.\n" - " Attempt Qemu to crash very soon !\n"); + " Attempt QEMU to crash very soon !\n"); } #endif if (env->check_pow == NULL) { fprintf(stderr, "WARNING: no power management check handler " "registered.\n" - " Attempt Qemu to crash very soon !\n"); + " Attempt QEMU to crash very soon !\n"); } } diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h new file mode 100644 index 0000000000..3d3ac0fcef --- /dev/null +++ b/target-sparc/cpu-qom.h @@ -0,0 +1,75 @@ +/* + * QEMU SPARC CPU + * + * Copyright (c) 2012 SUSE LINUX Products GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * <http://www.gnu.org/licenses/lgpl-2.1.html> + */ +#ifndef QEMU_SPARC_CPU_QOM_H +#define QEMU_SPARC_CPU_QOM_H + +#include "qemu/cpu.h" +#include "cpu.h" + +#ifdef TARGET_SPARC64 +#define TYPE_SPARC_CPU "sparc64-cpu" +#else +#define TYPE_SPARC_CPU "sparc-cpu" +#endif + +#define SPARC_CPU_CLASS(klass) \ + OBJECT_CLASS_CHECK(SPARCCPUClass, (klass), TYPE_SPARC_CPU) +#define SPARC_CPU(obj) \ + OBJECT_CHECK(SPARCCPU, (obj), TYPE_SPARC_CPU) +#define SPARC_CPU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SPARCCPUClass, (obj), TYPE_SPARC_CPU) + +/** + * SPARCCPUClass: + * @parent_reset: The parent class' reset handler. + * + * A SPARC CPU model. + */ +typedef struct SPARCCPUClass { + /*< private >*/ + CPUClass parent_class; + /*< public >*/ + + void (*parent_reset)(CPUState *cpu); +} SPARCCPUClass; + +/** + * SPARCCPU: + * @env: #CPUSPARCState + * + * A SPARC CPU. + */ +typedef struct SPARCCPU { + /*< private >*/ + CPUState parent_obj; + /*< public >*/ + + CPUSPARCState env; +} SPARCCPU; + +static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env) +{ + return SPARC_CPU(container_of(env, SPARCCPU, env)); +} + +#define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e)) + + +#endif diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu.c index 5c03f0b893..24f90f1ded 100644 --- a/target-sparc/cpu_init.c +++ b/target-sparc/cpu.c @@ -25,11 +25,23 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model); void cpu_state_reset(CPUSPARCState *env) { + cpu_reset(ENV_GET_CPU(env)); +} + +/* CPUClass::reset() */ +static void sparc_cpu_reset(CPUState *s) +{ + SPARCCPU *cpu = SPARC_CPU(s); + SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu); + CPUSPARCState *env = &cpu->env; + if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); log_cpu_state(env, 0); } + scc->parent_reset(s); + memset(env, 0, offsetof(CPUSPARCState, breakpoints)); tlb_flush(env, 1); env->cwp = 0; @@ -99,23 +111,18 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model) return 0; } -static void cpu_sparc_close(CPUSPARCState *env) -{ - g_free(env->def); - g_free(env); -} - CPUSPARCState *cpu_sparc_init(const char *cpu_model) { + SPARCCPU *cpu; CPUSPARCState *env; - env = g_new0(CPUSPARCState, 1); - cpu_exec_init(env); + cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU)); + env = &cpu->env; gen_intermediate_code_init(env); if (cpu_sparc_register(env, cpu_model) < 0) { - cpu_sparc_close(env); + object_delete(OBJECT(cpu)); return NULL; } qemu_init_vcpu(env); @@ -847,3 +854,46 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf, env->fsr, env->y); #endif } + +static void sparc_cpu_initfn(Object *obj) +{ + SPARCCPU *cpu = SPARC_CPU(obj); + CPUSPARCState *env = &cpu->env; + + cpu_exec_init(env); +} + +static void sparc_cpu_uninitfn(Object *obj) +{ + SPARCCPU *cpu = SPARC_CPU(obj); + CPUSPARCState *env = &cpu->env; + + g_free(env->def); +} + +static void sparc_cpu_class_init(ObjectClass *oc, void *data) +{ + SPARCCPUClass *scc = SPARC_CPU_CLASS(oc); + CPUClass *cc = CPU_CLASS(oc); + + scc->parent_reset = cc->reset; + cc->reset = sparc_cpu_reset; +} + +static const TypeInfo sparc_cpu_type_info = { + .name = TYPE_SPARC_CPU, + .parent = TYPE_CPU, + .instance_size = sizeof(SPARCCPU), + .instance_init = sparc_cpu_initfn, + .instance_finalize = sparc_cpu_uninitfn, + .abstract = false, + .class_size = sizeof(SPARCCPUClass), + .class_init = sparc_cpu_class_init, +}; + +static void sparc_cpu_register_types(void) +{ + type_register_static(&sparc_cpu_type_info); +} + +type_init(sparc_cpu_register_types) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 885ad45c3a..865288cc94 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -691,6 +691,7 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp) #endif #include "cpu-all.h" +#include "cpu-qom.h" #ifdef TARGET_SPARC64 /* sun4u.c */ @@ -63,6 +63,17 @@ void *tci_tb_ptr; static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS]; +#if !defined(CONFIG_TCG_PASS_AREG0) +# define helper_ldb_mmu(env, addr, mmu_idx) __ldb_mmu(addr, mmu_idx) +# define helper_ldw_mmu(env, addr, mmu_idx) __ldw_mmu(addr, mmu_idx) +# define helper_ldl_mmu(env, addr, mmu_idx) __ldl_mmu(addr, mmu_idx) +# define helper_ldq_mmu(env, addr, mmu_idx) __ldq_mmu(addr, mmu_idx) +# define helper_stb_mmu(env, addr, val, mmu_idx) __stb_mmu(addr, val, mmu_idx) +# define helper_stw_mmu(env, addr, val, mmu_idx) __stw_mmu(addr, val, mmu_idx) +# define helper_stl_mmu(env, addr, val, mmu_idx) __stl_mmu(addr, val, mmu_idx) +# define helper_stq_mmu(env, addr, val, mmu_idx) __stq_mmu(addr, val, mmu_idx) +#endif /* !CONFIG_TCG_PASS_AREG0 */ + static tcg_target_ulong tci_read_reg(TCGReg index) { assert(index < ARRAY_SIZE(tci_reg)); @@ -1049,7 +1060,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp8 = __ldb_mmu(taddr, tci_read_i(&tb_ptr)); + tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1061,7 +1072,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp8 = __ldb_mmu(taddr, tci_read_i(&tb_ptr)); + tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1073,7 +1084,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp16 = __ldw_mmu(taddr, tci_read_i(&tb_ptr)); + tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1085,7 +1096,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp16 = __ldw_mmu(taddr, tci_read_i(&tb_ptr)); + tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1098,7 +1109,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr)); + tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1110,7 +1121,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr)); + tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1123,7 +1134,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp32 = __ldl_mmu(taddr, tci_read_i(&tb_ptr)); + tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1138,7 +1149,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) #endif taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU - tmp64 = __ldq_mmu(taddr, tci_read_i(&tb_ptr)); + tmp64 = helper_ldq_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1154,7 +1165,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); - __stb_mmu(taddr, t0, t2); + helper_stb_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1166,7 +1177,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); - __stw_mmu(taddr, t0, t2); + helper_stw_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1178,7 +1189,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); - __stl_mmu(taddr, t0, t2); + helper_stl_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -1190,7 +1201,7 @@ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr) taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); - __stq_mmu(taddr, tmp64, t2); + helper_stq_mmu(env, taddr, tmp64, t2); #else host_addr = (tcg_target_ulong)taddr; assert(taddr == host_addr); @@ -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; @@ -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: diff --git a/translate-all.c b/translate-all.c index 8c7d303d86..5bd2d3711a 100644 --- a/translate-all.c +++ b/translate-all.c @@ -109,11 +109,11 @@ int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr /* The cpu state corresponding to 'searched_pc' is restored. */ int cpu_restore_state(TranslationBlock *tb, - CPUArchState *env, unsigned long searched_pc) + CPUArchState *env, uintptr_t searched_pc) { TCGContext *s = &tcg_ctx; int j; - unsigned long tc_ptr; + uintptr_t tc_ptr; #ifdef CONFIG_PROFILER int64_t ti; #endif @@ -133,7 +133,7 @@ int cpu_restore_state(TranslationBlock *tb, } /* find opc index corresponding to search_pc */ - tc_ptr = (unsigned long)tb->tc_ptr; + tc_ptr = (uintptr_t)tb->tc_ptr; if (searched_pc < tc_ptr) return -1; diff --git a/ui/cocoa.m b/ui/cocoa.m index 0711205cbe..e7d6e898ee 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -772,7 +772,7 @@ QemuCocoaView *cocoaView; modalForWindow:normalWindow modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; } else { - // or Launch Qemu, with the global args + // or launch QEMU, with the global args [self startEmulationWithArgc:gArgc argv:(char **)gArgv]; } } diff --git a/ui/spice-display.c b/ui/spice-display.c index cb8a7addfc..5418eb3c7c 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -219,7 +219,7 @@ static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd) /* * Called from spice server thread context (via interface_release_ressource) * We do *not* hold the global qemu mutex here, so extra care is needed - * when calling qemu functions. Qemu interfaces used: + * when calling qemu functions. QEMU interfaces used: * - g_free (underlying glibc free is re-entrant). */ void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update) |