Merge remote-tracking branch 'stefanha/trivial-patches' into staging
* stefanha/trivial-patches:
make: fix clean rule by removing build file in qom/
configure: Link qga against UST tracing related libraries
configure: Link QEMU against 'liburcu-bp'
main-loop: make qemu_event_handle static
block/curl: Replace usleep by g_usleep
qtest: Add missing GCC_FMT_ATTR
w32: Undefine error constants before their redefinition
configure: fix mingw32 libs_qga typo
diff --git a/CODING_STYLE b/CODING_STYLE
index 7c82d4d..dcbce28 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
diff --git a/Makefile.target b/Makefile.target
index cff15f0..14c8fa1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -93,9 +93,10 @@
libobj-$(CONFIG_NEED_MMU) += mmu.o
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
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/configure b/configure
index 520bd93..e05f34b 100755
--- a/configure
+++ b/configure
@@ -519,7 +519,7 @@
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}"
@@ -1993,13 +1993,21 @@
##########################################
# 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
diff --git a/cpu-all.h b/cpu-all.h
index 9621c3c..4512518 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -204,7 +204,8 @@
#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
diff --git a/disas.c b/disas.c
index 9485824..4f2c4e4 100644
--- a/disas.c
+++ b/disas.c
@@ -138,7 +138,7 @@
/* 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 @@
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
diff --git a/dma.h b/dma.h
index 20e86d2..5bd1fc8 100644
--- a/dma.h
+++ b/dma.h
@@ -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 b8e504a..450a66a 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 23dd2ba..667a862 100644
--- a/docs/specs/ivshmem_device_spec.txt
+++ b/docs/specs/ivshmem_device_spec.txt
@@ -24,7 +24,7 @@
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 {
diff --git a/elf.h b/elf.h
index 36bcac4..e1422b8 100644
--- a/elf.h
+++ b/elf.h
@@ -538,6 +538,27 @@
#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 93a5b22..fa7bdfe 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -85,15 +85,15 @@
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 @@
#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 @@
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 @@
#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 @@
/* 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 @@
# 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)
diff --git a/exec.c b/exec.c
index 6731ab8..03d3a6b 100644
--- a/exec.c
+++ b/exec.c
@@ -1380,7 +1380,7 @@
/* 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 @@
/* 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 @@
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 81a7d1a..d37090a 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -117,7 +117,7 @@
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 @@
{
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 @@
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 @@
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 @@
flag aSign;
int32 aExp, shiftCount;
uint64_t aSig, savedASig;
- int32 z;
+ int32_t z;
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
@@ -5277,7 +5277,7 @@
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 faa0434..e60e3b9 100644
--- a/fsdev/virtfs-proxy-helper.texi
+++ b/fsdev/virtfs-proxy-helper.texi
@@ -24,7 +24,7 @@
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 64e1cd9..b80aa8f 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -565,7 +565,7 @@
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));
}
diff --git a/hw/pc.c b/hw/pc.c
index 83a1b5b..67f0479 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -776,7 +776,7 @@
}
/* 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 ff154c7..8b37336 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 220c81d..f0a3ae4 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 5ee8cb3..f1dfbe1 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.
*
diff --git a/hw/ps2.c b/hw/ps2.c
index b1a67bc..f93cd24 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -88,7 +88,7 @@
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 7bcbf37..34088ad 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -932,8 +932,8 @@
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 @@
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 @@
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);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 237e20c..fe33138 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -248,6 +248,10 @@
uint32_t pil = env->pil_in |
(env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
+ /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
+ if (env->ivec_status & 0x20) {
+ return;
+ }
/* check if TM or SM in SOFTINT are set
setting these also causes interrupt 14 */
if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
@@ -275,7 +279,8 @@
int old_interrupt = env->interrupt_index;
int new_interrupt = TT_EXTINT | i;
- if (env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt) {
+ if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
+ && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
"current %x >= pending %x\n",
env->tl, cpu_tsptr(env)->tt, new_interrupt);
@@ -309,19 +314,22 @@
CPUSPARCState *env = opaque;
if (level) {
- CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
- env->interrupt_index = TT_IVEC;
- env->pil_in |= 1 << 5;
- env->ivec_status |= 0x20;
- env->ivec_data[0] = (0x1f << 6) | irq;
- env->ivec_data[1] = 0;
- env->ivec_data[2] = 0;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- } else {
- CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
- env->pil_in &= ~(1 << 5);
- env->ivec_status &= ~0x20;
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ if (!(env->ivec_status & 0x20)) {
+ CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+ env->halted = 0;
+ env->interrupt_index = TT_IVEC;
+ env->ivec_status |= 0x20;
+ env->ivec_data[0] = (0x1f << 6) | irq;
+ env->ivec_data[1] = 0;
+ env->ivec_data[2] = 0;
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ }
+ } else {
+ if (env->ivec_status & 0x20) {
+ CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+ env->ivec_status &= ~0x20;
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ }
}
}
diff --git a/ioport.c b/ioport.c
index 78a3b89..6e4ca0d 100644
--- a/ioport.c
+++ b/ioport.c
@@ -385,7 +385,7 @@
* 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 7f05879..5356395 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 e502b39..f3b1552 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -375,10 +375,33 @@
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 @@
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 6514502..eb96a08 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 962677e..191b750 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 @@
#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 @@
#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 @@
/* 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 @@
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 @@
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 @@
_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 @@
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 994c02b..7125d1c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -212,7 +212,7 @@
#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 @@
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 @@
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
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 6889567..7b299b7 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -51,6 +51,7 @@
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_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 9f5e53a..8a92162 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -95,6 +95,7 @@
#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 @@
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 @@
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 @@
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 @@
#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 41f0ff8..a79b67d 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -832,9 +832,11 @@
#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 @@
#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 c370125..601618d 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -83,9 +83,9 @@
/* 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 @@
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 fc738d1..1ebdc4b 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -218,17 +218,19 @@
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 @@
}
}
- 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 @@
}
}
-#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 @@
/* 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 @@
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 @@
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 @@
}
}
-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]);
- }
-
- /* 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);
- }
- }
- } else if (ret != WAIT_TIMEOUT) {
- err = GetLastError();
- fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
+ if (nfds >= 0) {
+ ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
+ if (ret != 0) {
+ timeout = 0;
}
}
- *timeout = 0;
-}
-#else
-static inline void os_host_main_loop_wait(int *timeout)
-{
+ 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));
+
+ 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]);
+ }
+ }
+ }
+
+ 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 @@
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 @@
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 4987041..e743aa0 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -359,6 +359,7 @@
/* 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);
diff --git a/memory.c b/memory.c
index 22b0352..aab4a31 100644
--- a/memory.c
+++ b/memory.c
@@ -1444,6 +1444,11 @@
{
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 @@
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 @@
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 ce3021e..ffbc6d0 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 socket_set_block(int fd)
{
unsigned long opt = 0;
+ WSAEventSelect(fd, NULL, 0);
ioctlsocket(fd, FIONBIO, &opt);
}
@@ -83,6 +85,7 @@
{
unsigned long opt = 1;
ioctlsocket(fd, FIONBIO, &opt);
+ qemu_fd_register(fd);
}
int inet_aton(const char *cp, struct in_addr *ia)
diff --git a/ppc-dis.c b/ppc-dis.c
index ffdbec1..bc98cbe 100644
--- a/ppc-dis.c
+++ b/ppc-dis.c
@@ -5152,7 +5152,7 @@
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 83b2ad5..9e07ba6 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -968,7 +968,7 @@
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 @@
@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 @@
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 44996cc..6955d90 100644
--- a/qemu-nbd.texi
+++ b/qemu-nbd.texi
@@ -6,7 +6,7 @@
@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 f72f9a0..a169792 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1310,7 +1310,7 @@
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 @@
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 74d7122..9288cd8 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/target-alpha/STATUS b/target-alpha/STATUS
index 742e370..6c97445 100644
--- a/target-alpha/STATUS
+++ b/target-alpha/STATUS
@@ -4,7 +4,7 @@
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 6c5d28b..74bf7f7 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -276,7 +276,7 @@
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 e176c5f..c208c80 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -216,6 +216,9 @@
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 @@
#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 @@
(((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 @@
*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 @@
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 d974b57..28f127b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -842,7 +842,7 @@
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 @@
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 @@
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 46d1d3e..7a3c7d6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -59,6 +59,7 @@
struct TranslationBlock *tb;
int singlestep_enabled;
int thumb;
+ int bswap_code;
#if !defined(CONFIG_USER_ONLY)
int user;
#endif
@@ -6705,7 +6706,7 @@
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 @@
/* 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 @@
}
}
- insn = lduw_code(s->pc);
+ insn = arm_lduw_code(s->pc, s->bswap_code);
s->pc += 2;
switch (insn >> 12) {
@@ -9872,6 +9873,7 @@
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 @@
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 9101881..2a3546f 100644
--- a/target-mips/TODO
+++ b/target-mips/TODO
@@ -16,7 +16,7 @@
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 @@
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 7430aa5..257c4c4 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -418,7 +418,7 @@
/* 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 ca6f1cb..e7fb364 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -233,10 +233,10 @@
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 @@
/* 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 39dcc27..e13b749 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -365,7 +365,7 @@
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 @@
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 @@
/* 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 @@
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 724f4c7..d929213 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -470,7 +470,7 @@
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 24fc6bc..a2e49cd 100644
--- a/target-ppc/kvm_ppc.c
+++ b/target-ppc/kvm_ppc.c
@@ -31,7 +31,7 @@
{
/* 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 367eefa..b1f8785 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -1796,17 +1796,17 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
new file mode 100644
index 0000000..6fa55a8
--- /dev/null
+++ b/target-s390x/cpu-qom.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU S/390 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_S390_CPU_QOM_H
+#define QEMU_S390_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_S390_CPU "s390-cpu"
+
+#define S390_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(S390CPUClass, (klass), TYPE_S390_CPU)
+#define S390_CPU(obj) \
+ OBJECT_CHECK(S390CPU, (obj), TYPE_S390_CPU)
+#define S390_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(S390CPUClass, (obj), TYPE_S390_CPU)
+
+/**
+ * S390CPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An S/390 CPU model.
+ */
+typedef struct S390CPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} S390CPUClass;
+
+/**
+ * S390CPU:
+ * @env: #CPUS390XState.
+ *
+ * An S/390 CPU.
+ */
+typedef struct S390CPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUS390XState env;
+} S390CPU;
+
+static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
+{
+ return S390_CPU(container_of(env, S390CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e))
+
+
+#endif
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
new file mode 100644
index 0000000..f183213
--- /dev/null
+++ b/target-s390x/cpu.c
@@ -0,0 +1,96 @@
+/*
+ * QEMU S/390 CPU
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ * Copyright (c) 2011 Alexander Graf
+ * 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>
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+#include "qemu-timer.h"
+
+
+/* CPUClass::reset() */
+static void s390_cpu_reset(CPUState *s)
+{
+ S390CPU *cpu = S390_CPU(s);
+ S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
+ CPUS390XState *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(CPUS390XState, breakpoints));
+ /* FIXME: reset vector? */
+ tlb_flush(env, 1);
+ s390_add_running_cpu(env);
+}
+
+static void s390_cpu_initfn(Object *obj)
+{
+ S390CPU *cpu = S390_CPU(obj);
+ CPUS390XState *env = &cpu->env;
+ static int cpu_num = 0;
+#if !defined(CONFIG_USER_ONLY)
+ struct tm tm;
+#endif
+
+ cpu_exec_init(env);
+#if !defined(CONFIG_USER_ONLY)
+ qemu_get_timedate(&tm, 0);
+ env->tod_offset = TOD_UNIX_EPOCH +
+ (time2tod(mktimegm(&tm)) * 1000000000ULL);
+ env->tod_basetime = 0;
+ env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu);
+ env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu);
+#endif
+ env->cpu_num = cpu_num++;
+ env->ext_index = -1;
+
+ cpu_reset(CPU(cpu));
+}
+
+static void s390_cpu_class_init(ObjectClass *oc, void *data)
+{
+ S390CPUClass *scc = S390_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(scc);
+
+ scc->parent_reset = cc->reset;
+ cc->reset = s390_cpu_reset;
+}
+
+static const TypeInfo s390_cpu_type_info = {
+ .name = TYPE_S390_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(S390CPU),
+ .instance_init = s390_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(S390CPUClass),
+ .class_init = s390_cpu_class_init,
+};
+
+static void s390_cpu_register_types(void)
+{
+ type_register_static(&s390_cpu_type_info);
+}
+
+type_init(s390_cpu_register_types)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index ea849fc..2f3f394 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -288,6 +288,9 @@
#ifndef CONFIG_USER_ONLY
+void s390x_tod_timer(void *opaque);
+void s390x_cpu_timer(void *opaque);
+
int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall);
#ifdef CONFIG_KVM
@@ -991,4 +994,6 @@
env->psw.addr = tb->pc;
}
+#include "cpu-qom.h"
+
#endif
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 44d5048..209a696 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -51,17 +51,19 @@
#endif
#ifndef CONFIG_USER_ONLY
-static void s390x_tod_timer(void *opaque)
+void s390x_tod_timer(void *opaque)
{
- CPUS390XState *env = opaque;
+ S390CPU *cpu = opaque;
+ CPUS390XState *env = &cpu->env;
env->pending_int |= INTERRUPT_TOD;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
}
-static void s390x_cpu_timer(void *opaque)
+void s390x_cpu_timer(void *opaque)
{
- CPUS390XState *env = opaque;
+ S390CPU *cpu = opaque;
+ CPUS390XState *env = &cpu->env;
env->pending_int |= INTERRUPT_CPUTIMER;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -70,32 +72,19 @@
CPUS390XState *cpu_s390x_init(const char *cpu_model)
{
+ S390CPU *cpu;
CPUS390XState *env;
-#if !defined (CONFIG_USER_ONLY)
- struct tm tm;
-#endif
static int inited = 0;
- static int cpu_num = 0;
- env = g_malloc0(sizeof(CPUS390XState));
- cpu_exec_init(env);
+ cpu = S390_CPU(object_new(TYPE_S390_CPU));
+ env = &cpu->env;
+
if (tcg_enabled() && !inited) {
inited = 1;
s390x_translate_init();
}
-#if !defined(CONFIG_USER_ONLY)
- qemu_get_timedate(&tm, 0);
- env->tod_offset = TOD_UNIX_EPOCH +
- (time2tod(mktimegm(&tm)) * 1000000000ULL);
- env->tod_basetime = 0;
- env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, env);
- env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, env);
-#endif
env->cpu_model_str = cpu_model;
- env->cpu_num = cpu_num++;
- env->ext_index = -1;
- cpu_state_reset(env);
qemu_init_vcpu(env);
return env;
}
@@ -121,15 +110,7 @@
void cpu_state_reset(CPUS390XState *env)
{
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- memset(env, 0, offsetof(CPUS390XState, breakpoints));
- /* FIXME: reset vector? */
- tlb_flush(env, 1);
- s390_add_running_cpu(env);
+ cpu_reset(ENV_GET_CPU(env));
}
#ifndef CONFIG_USER_ONLY
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
new file mode 100644
index 0000000..3d3ac0f
--- /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
similarity index 95%
rename from target-sparc/cpu_init.c
rename to target-sparc/cpu.c
index 5c03f0b..24f90f1 100644
--- a/target-sparc/cpu_init.c
+++ b/target-sparc/cpu.c
@@ -25,11 +25,23 @@
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 @@
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 @@
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 885ad45..865288c 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -691,6 +691,7 @@
#endif
#include "cpu-all.h"
+#include "cpu-qom.h"
#ifdef TARGET_SPARC64
/* sun4u.c */
diff --git a/tci.c b/tci.c
index 70e7bfb..c43fe7d 100644
--- a/tci.c
+++ b/tci.c
@@ -63,6 +63,17 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
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);
diff --git a/thunk.c b/thunk.c
index 0657188..8ebbbb4 100644
--- a/thunk.c
+++ b/thunk.c
@@ -46,6 +46,7 @@
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 @@
#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;
diff --git a/thunk.h b/thunk.h
index 9810743..5be8f91 100644
--- a/thunk.h
+++ b/thunk.h
@@ -37,6 +37,7 @@
TYPE_PTR,
TYPE_ARRAY,
TYPE_STRUCT,
+ TYPE_OLDDEVT,
} argtype;
#define MK_PTR(type) TYPE_PTR, type
@@ -104,6 +105,31 @@
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 @@
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 8c7d303..5bd2d37 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -109,11 +109,11 @@
/* 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 @@
}
/* 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 0711205..e7d6e89 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -772,7 +772,7 @@
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 cb8a7ad..5418eb3 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -219,7 +219,7 @@
/*
* 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)