aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--Makefile.target9
-rw-r--r--arch_init.c2
-rw-r--r--bsd-user/main.c1
-rwxr-xr-xconfigure22
-rw-r--r--coroutine-gthread.c96
-rw-r--r--cpu-all.h12
-rw-r--r--cpu-defs.h14
-rw-r--r--cpu-exec.c4
-rw-r--r--cpus.c3
-rw-r--r--disas.c8
-rw-r--r--exec-all.h11
-rw-r--r--exec.c107
-rw-r--r--hw/a15mpcore.c46
-rw-r--r--hw/a9mpcore.c72
-rw-r--r--hw/arm11mpcore.c56
-rw-r--r--hw/arm_gic.c157
-rw-r--r--hw/armv7m_nvic.c24
-rw-r--r--hw/exynos4210.c30
-rw-r--r--hw/exynos4210.h3
-rw-r--r--hw/exynos4210_combiner.c10
-rw-r--r--hw/exynos4210_gic.c48
-rw-r--r--hw/exynos4210_uart.c6
-rw-r--r--hw/exynos4_boards.c1
-rw-r--r--hw/ivshmem.c8
-rw-r--r--hw/kvm/clock.c16
-rw-r--r--hw/pc.c8
-rw-r--r--hw/ps2.h29
-rw-r--r--hw/realview_gic.c46
-rw-r--r--hw/rtl8139.c26
-rw-r--r--hw/spapr.h2
-rw-r--r--hw/spapr_llan.c26
-rw-r--r--hw/spapr_pci.c117
-rw-r--r--hw/spapr_rtas.c17
-rw-r--r--hw/spapr_vio.c62
-rw-r--r--hw/spapr_vio.h5
-rw-r--r--hw/spapr_vscsi.c15
-rw-r--r--hw/spapr_vty.c4
-rw-r--r--hw/xen.h1
-rw-r--r--hw/xen_apic.c90
-rw-r--r--hw/xen_backend.c17
-rw-r--r--hw/xen_disk.c4
-rw-r--r--kvm-all.c23
-rw-r--r--kvm-stub.c8
-rw-r--r--kvm.h5
-rw-r--r--linux-headers/asm-powerpc/kvm.h1
-rw-r--r--linux-headers/asm-s390/kvm.h2
-rw-r--r--linux-headers/linux/kvm.h9
-rw-r--r--linux-user/syscall.c4
-rw-r--r--main-loop.c2
-rw-r--r--nbd.c2
-rw-r--r--qemu-os-win32.h35
-rw-r--r--qemu_socket.h6
-rw-r--r--savevm.c3
-rwxr-xr-xscripts/kvm/kvm_flightrecorder126
-rw-r--r--slirp/slirp.h12
-rw-r--r--softmmu_header.h15
-rw-r--r--softmmu_template.h42
-rw-r--r--target-alpha/cpu-qom.h71
-rw-r--r--target-alpha/cpu.c58
-rw-r--r--target-alpha/cpu.h7
-rw-r--r--target-alpha/fpu_helper.c6
-rw-r--r--target-alpha/helper.c13
-rw-r--r--target-alpha/mem_helper.c6
-rw-r--r--target-alpha/translate.c16
-rw-r--r--target-arm/op_helper.c8
-rw-r--r--target-cris/op_helper.c12
-rw-r--r--target-i386/cpu-qom.h75
-rw-r--r--target-i386/cpu.c (renamed from target-i386/cpuid.c)134
-rw-r--r--target-i386/cpu.h3
-rw-r--r--target-i386/helper.c100
-rw-r--r--target-i386/op_helper.c8
-rw-r--r--target-lm32/cpu-qom.h71
-rw-r--r--target-lm32/cpu.c81
-rw-r--r--target-lm32/cpu.h1
-rw-r--r--target-lm32/helper.c17
-rw-r--r--target-lm32/op_helper.c8
-rw-r--r--target-m68k/op_helper.c8
-rw-r--r--target-microblaze/helper.c1
-rw-r--r--target-microblaze/mmu.c1
-rw-r--r--target-microblaze/op_helper.c9
-rw-r--r--target-microblaze/translate.c1
-rw-r--r--target-mips/op_helper.c20
-rw-r--r--target-ppc/cpu-qom.h77
-rw-r--r--target-ppc/cpu.h3
-rw-r--r--target-ppc/helper.c67
-rw-r--r--target-ppc/kvm.c14
-rw-r--r--target-ppc/kvm_ppc.h5
-rw-r--r--target-ppc/machine.c8
-rw-r--r--target-ppc/op_helper.c8
-rw-r--r--target-ppc/translate.c2
-rw-r--r--target-ppc/translate_init.c152
-rw-r--r--target-s390x/op_helper.c8
-rw-r--r--target-sh4/op_helper.c14
-rw-r--r--target-sparc/cpu.h2
-rw-r--r--target-sparc/ldst_helper.c12
-rw-r--r--target-xtensa/core-dc232b.c27
-rw-r--r--target-xtensa/core-dc233c.c55
-rw-r--r--target-xtensa/core-dc233c/core-isa.h474
-rw-r--r--target-xtensa/core-dc233c/gdb-config.c145
-rw-r--r--target-xtensa/core-fsf.c27
-rw-r--r--target-xtensa/cpu-qom.h80
-rw-r--r--target-xtensa/cpu.c88
-rw-r--r--target-xtensa/cpu.h2
-rw-r--r--target-xtensa/helper.c20
-rw-r--r--target-xtensa/helper.h (renamed from target-xtensa/helpers.h)0
-rw-r--r--target-xtensa/op_helper.c40
-rw-r--r--target-xtensa/translate.c8
-rw-r--r--tcg/i386/tcg-target.c45
-rw-r--r--tests/Makefile2
-rw-r--r--tests/tcg/xtensa/Makefile3
-rw-r--r--tests/tcg/xtensa/macros.inc17
-rw-r--r--tests/tcg/xtensa/test_break.S34
-rw-r--r--tests/tcg/xtensa/test_loop.S50
-rw-r--r--user-exec.c2
-rw-r--r--xen-all.c50
-rw-r--r--xen-mapcache.c15
-rw-r--r--xen-stub.c4
-rw-r--r--xtensa-semi.c2
119 files changed, 3018 insertions, 811 deletions
diff --git a/Makefile b/Makefile
index a78f53d4c9..e0fe680c39 100644
--- a/Makefile
+++ b/Makefile
@@ -328,7 +328,7 @@ TEXIFLAG=$(if $(V),,--quiet)
$(call quiet-command,texi2dvi $(TEXIFLAG) -I . $<," GEN $@")
%.html: %.texi
- $(call quiet-command,$(MAKEINFO) $(MAKEINFOFLAGS) --html $< -o $@, \
+ $(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --html $< -o $@, \
" GEN $@")
%.info: %.texi
diff --git a/Makefile.target b/Makefile.target
index 14c8fa18fc..84951a09ec 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -87,12 +87,13 @@ endif
endif
libobj-y += helper.o
ifeq ($(TARGET_BASE_ARCH), i386)
-libobj-y += cpuid.o
+libobj-y += cpu.o
endif
libobj-$(TARGET_SPARC64) += vis_helper.o
libobj-$(CONFIG_NEED_MMU) += mmu.o
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
libobj-$(TARGET_ARM) += cpu.o
+libobj-$(TARGET_LM32) += 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
@@ -101,7 +102,9 @@ endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_UNICORE32) += cpu.o
+libobj-$(TARGET_XTENSA) += cpu.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
+libobj-$(TARGET_ALPHA) += cpu.o
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
@@ -236,7 +239,7 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
obj-$(CONFIG_NO_XEN) += xen-stub.o
-obj-i386-$(CONFIG_XEN) += xen_platform.o
+obj-i386-$(CONFIG_XEN) += xen_platform.o xen_apic.o
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
@@ -365,6 +368,7 @@ obj-arm-y += cadence_uart.o
obj-arm-y += cadence_ttc.o
obj-arm-y += cadence_gem.o
obj-arm-y += xilinx_zynq.o zynq_slcr.o
+obj-arm-y += arm_gic.o
obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
@@ -413,6 +417,7 @@ obj-xtensa-y += xtensa_sim.o
obj-xtensa-y += xtensa_lx60.o
obj-xtensa-y += xtensa-semi.o
obj-xtensa-y += core-dc232b.o
+obj-xtensa-y += core-dc233c.o
obj-xtensa-y += core-fsf.o
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/arch_init.c b/arch_init.c
index 595badf50f..9a35aeea30 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -475,7 +475,7 @@ struct soundhw {
static struct soundhw soundhw[] = {
#ifdef HAS_AUDIO_CHOICE
-#if defined(TARGET_I386) || defined(TARGET_MIPS)
+#ifdef CONFIG_PCSPK
{
"pcspk",
"PC speaker",
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 48cb715d2d..0689e38fb8 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -41,6 +41,7 @@ int singlestep;
unsigned long mmap_min_addr;
unsigned long guest_base;
int have_guest_base;
+unsigned long reserved_va;
#endif
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
diff --git a/configure b/configure
index e05f34b9c0..1d94acda2c 100755
--- a/configure
+++ b/configure
@@ -1242,6 +1242,14 @@ if ! has $python; then
exit 1
fi
+# Note that if the Python conditional here evaluates True we will exit
+# with status 1 which is a shell 'false' value.
+if ! "$python" -c 'import sys; sys.exit(sys.version_info[0] >= 3)'; then
+ echo "Python 2 required but '$python' is version 3 or better."
+ echo "Use --python=/path/to/python to specify a Python 2."
+ exit 1
+fi
+
if test -z "$target_list" ; then
target_list="$default_target_list"
else
@@ -2369,7 +2377,7 @@ int main(void)
return 0;
}
EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
fallocate=yes
fi
@@ -2384,7 +2392,7 @@ int main(void)
return 0;
}
EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
sync_file_range=yes
fi
@@ -2401,7 +2409,7 @@ int main(void)
return 0;
}
EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
fiemap=yes
fi
@@ -2431,7 +2439,7 @@ int main(void)
return 0;
}
EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
epoll=yes
fi
@@ -2454,7 +2462,7 @@ int main(void)
return epoll_create1 == epoll_create1;
}
EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
epoll_create1=yes
fi
@@ -2468,7 +2476,7 @@ int main(void)
return 0;
}
EOF
-if compile_prog "$ARCH_CFLAGS" "" ; then
+if compile_prog "" "" ; then
epoll_pwait=yes
fi
@@ -2624,7 +2632,7 @@ int main(void) {
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
return fdatasync(0);
#else
-#abort Not supported
+#error Not supported
#endif
}
EOF
diff --git a/coroutine-gthread.c b/coroutine-gthread.c
index 662801b2fa..30c24c94b8 100644
--- a/coroutine-gthread.c
+++ b/coroutine-gthread.c
@@ -26,13 +26,93 @@ typedef struct {
Coroutine base;
GThread *thread;
bool runnable;
+ bool free_on_thread_exit;
CoroutineAction action;
} CoroutineGThread;
-static GCond *coroutine_cond;
static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT;
+
+/* GLib 2.31 and beyond deprecated various parts of the thread API,
+ * but the new interfaces are not available in older GLib versions
+ * so we have to cope with both.
+ */
+#if GLIB_CHECK_VERSION(2, 31, 0)
+/* Default zero-initialisation is sufficient for 2.31+ GCond */
+static GCond the_coroutine_cond;
+static GCond *coroutine_cond = &the_coroutine_cond;
+static inline void init_coroutine_cond(void)
+{
+}
+
+/* Awkwardly, the GPrivate API doesn't provide a way to update the
+ * GDestroyNotify handler for the coroutine key dynamically. So instead
+ * we track whether or not the CoroutineGThread should be freed on
+ * thread exit / coroutine key update using the free_on_thread_exit
+ * field.
+ */
+static void coroutine_destroy_notify(gpointer data)
+{
+ CoroutineGThread *co = data;
+ if (co && co->free_on_thread_exit) {
+ g_free(co);
+ }
+}
+
+static GPrivate coroutine_key = G_PRIVATE_INIT(coroutine_destroy_notify);
+
+static inline CoroutineGThread *get_coroutine_key(void)
+{
+ return g_private_get(&coroutine_key);
+}
+
+static inline void set_coroutine_key(CoroutineGThread *co,
+ bool free_on_thread_exit)
+{
+ /* Unlike g_static_private_set() this does not call the GDestroyNotify
+ * if the previous value of the key was NULL. Fortunately we only need
+ * the GDestroyNotify in the non-NULL key case.
+ */
+ co->free_on_thread_exit = free_on_thread_exit;
+ g_private_replace(&coroutine_key, co);
+}
+
+static inline GThread *create_thread(GThreadFunc func, gpointer data)
+{
+ return g_thread_new("coroutine", func, data);
+}
+
+#else
+
+/* Handle older GLib versions */
+static GCond *coroutine_cond;
+static inline void init_coroutine_cond(void)
+{
+ coroutine_cond = g_cond_new();
+}
+
static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
+static inline CoroutineGThread *get_coroutine_key(void)
+{
+ return g_static_private_get(&coroutine_key);
+}
+
+static inline void set_coroutine_key(CoroutineGThread *co,
+ bool free_on_thread_exit)
+{
+ g_static_private_set(&coroutine_key, co,
+ free_on_thread_exit ? (GDestroyNotify)g_free : NULL);
+}
+
+static inline GThread *create_thread(GThreadFunc func, gpointer data)
+{
+ return g_thread_create_full(func, data, 0, TRUE, TRUE,
+ G_THREAD_PRIORITY_NORMAL, NULL);
+}
+
+#endif
+
+
static void __attribute__((constructor)) coroutine_init(void)
{
if (!g_thread_supported()) {
@@ -44,7 +124,7 @@ static void __attribute__((constructor)) coroutine_init(void)
#endif
}
- coroutine_cond = g_cond_new();
+ init_coroutine_cond();
}
static void coroutine_wait_runnable_locked(CoroutineGThread *co)
@@ -65,7 +145,7 @@ static gpointer coroutine_thread(gpointer opaque)
{
CoroutineGThread *co = opaque;
- g_static_private_set(&coroutine_key, co, NULL);
+ set_coroutine_key(co, false);
coroutine_wait_runnable(co);
co->base.entry(co->base.entry_arg);
qemu_coroutine_switch(&co->base, co->base.caller, COROUTINE_TERMINATE);
@@ -77,8 +157,7 @@ Coroutine *qemu_coroutine_new(void)
CoroutineGThread *co;
co = g_malloc0(sizeof(*co));
- co->thread = g_thread_create_full(coroutine_thread, co, 0, TRUE, TRUE,
- G_THREAD_PRIORITY_NORMAL, NULL);
+ co->thread = create_thread(coroutine_thread, co);
if (!co->thread) {
g_free(co);
return NULL;
@@ -117,12 +196,11 @@ CoroutineAction qemu_coroutine_switch(Coroutine *from_,
Coroutine *qemu_coroutine_self(void)
{
- CoroutineGThread *co = g_static_private_get(&coroutine_key);
-
+ CoroutineGThread *co = get_coroutine_key();
if (!co) {
co = g_malloc0(sizeof(*co));
co->runnable = true;
- g_static_private_set(&coroutine_key, co, (GDestroyNotify)g_free);
+ set_coroutine_key(co, true);
}
return &co->base;
@@ -130,7 +208,7 @@ Coroutine *qemu_coroutine_self(void)
bool qemu_in_coroutine(void)
{
- CoroutineGThread *co = g_static_private_get(&coroutine_key);
+ CoroutineGThread *co = get_coroutine_key();
return co && co->base.caller;
}
diff --git a/cpu-all.h b/cpu-all.h
index 4512518065..f7d6867b0d 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -222,8 +222,8 @@ extern unsigned long reserved_va;
#else /* !CONFIG_USER_ONLY */
/* NOTE: we use double casts if pointers and target_ulong have
different sizes */
-#define saddr(x) (uint8_t *)(long)(x)
-#define laddr(x) (uint8_t *)(long)(x)
+#define saddr(x) (uint8_t *)(intptr_t)(x)
+#define laddr(x) (uint8_t *)(intptr_t)(x)
#endif
#define ldub_raw(p) ldub_p(laddr((p)))
@@ -299,10 +299,10 @@ extern unsigned long reserved_va;
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
-/* ??? These should be the larger of unsigned long and target_ulong. */
-extern unsigned long qemu_real_host_page_size;
-extern unsigned long qemu_host_page_size;
-extern unsigned long qemu_host_page_mask;
+/* ??? These should be the larger of uintptr_t and target_ulong. */
+extern uintptr_t qemu_real_host_page_size;
+extern uintptr_t qemu_host_page_size;
+extern uintptr_t qemu_host_page_mask;
#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
diff --git a/cpu-defs.h b/cpu-defs.h
index 326896826e..f49e9500a9 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -98,12 +98,12 @@ typedef struct CPUTLBEntry {
target_ulong addr_code;
/* Addend to virtual address to get host address. IO accesses
use the corresponding iotlb value. */
- unsigned long addend;
+ uintptr_t addend;
/* padding to get a power of two size */
- uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) -
- (sizeof(target_ulong) * 3 +
- ((-sizeof(target_ulong) * 3) & (sizeof(unsigned long) - 1)) +
- sizeof(unsigned long))];
+ uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) -
+ (sizeof(target_ulong) * 3 +
+ ((-sizeof(target_ulong) * 3) & (sizeof(uintptr_t) - 1)) +
+ sizeof(uintptr_t))];
} CPUTLBEntry;
extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BITS) ? 1 : -1];
@@ -166,8 +166,8 @@ typedef struct CPUWatchpoint {
/* in order to avoid passing too many arguments to the MMIO \
helpers, we store some rarely used information in the CPU \
context) */ \
- unsigned long mem_io_pc; /* host pc at which the memory was \
- accessed */ \
+ uintptr_t mem_io_pc; /* host pc at which the memory was \
+ accessed */ \
target_ulong mem_io_vaddr; /* target virtual addr at which the \
memory was accessed */ \
uint32_t halted; /* Nonzero if the CPU is in suspend state */ \
diff --git a/cpu-exec.c b/cpu-exec.c
index d153f978e1..0344cd5c59 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -541,8 +541,8 @@ int cpu_exec(CPUArchState *env)
tb_invalidated_flag = 0;
}
#ifdef CONFIG_DEBUG_EXEC
- qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
- (long)tb->tc_ptr, tb->pc,
+ qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
+ tb->tc_ptr, tb->pc,
lookup_symbol(tb->pc));
#endif
/* see if we can patch the calling TB. When the TB
diff --git a/cpus.c b/cpus.c
index eb22bd5df1..b182b3d7d9 100644
--- a/cpus.c
+++ b/cpus.c
@@ -441,8 +441,7 @@ static bool cpu_thread_is_idle(CPUArchState *env)
if (env->stopped || !runstate_is_running()) {
return true;
}
- if (!env->halted || qemu_cpu_has_work(env) ||
- (kvm_enabled() && kvm_irqchip_in_kernel())) {
+ if (!env->halted || qemu_cpu_has_work(env) || kvm_irqchip_in_kernel()) {
return false;
}
return true;
diff --git a/disas.c b/disas.c
index 4f2c4e4cb9..27071c3bc1 100644
--- a/disas.c
+++ b/disas.c
@@ -268,7 +268,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size)
{
- unsigned long pc;
+ uintptr_t pc;
int count;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
@@ -276,7 +276,7 @@ void disas(FILE *out, void *code, unsigned long size)
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
disasm_info.buffer = code;
- disasm_info.buffer_vma = (unsigned long)code;
+ disasm_info.buffer_vma = (uintptr_t)code;
disasm_info.buffer_length = size;
#ifdef HOST_WORDS_BIGENDIAN
@@ -320,8 +320,8 @@ void disas(FILE *out, void *code, unsigned long size)
(long) code);
return;
#endif
- for (pc = (unsigned long)code; size > 0; pc += count, size -= count) {
- fprintf(out, "0x%08lx: ", pc);
+ for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
+ fprintf(out, "0x%08" PRIxPTR ": ", pc);
count = print_insn(pc, &disasm_info);
fprintf(out, "\n");
if (count < 0)
diff --git a/exec-all.h b/exec-all.h
index fa7bdfecd8..6bcc07538f 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -87,7 +87,7 @@ int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
int cpu_restore_state(struct TranslationBlock *tb,
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);
+void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, uintptr_t retaddr);
TranslationBlock *tb_gen_code(CPUArchState *env,
target_ulong pc, target_ulong cs_base, int flags,
int cflags);
@@ -102,6 +102,7 @@ void tlb_flush(CPUArchState *env, int flush_global);
void tlb_set_page(CPUArchState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
int mmu_idx, target_ulong size);
+void tb_invalidate_phys_addr(target_phys_addr_t addr);
#endif
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
@@ -287,13 +288,13 @@ extern void *tci_tb_ptr;
# endif
#elif defined(__s390__) && !defined(__s390x__)
# define GETPC() \
- ((void *)(((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1))
+ (((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 *)((uintptr_t)__builtin_return_address(0) - 2))
+# define GETPC() ((uintptr_t)__builtin_return_address(0) - 2)
#else
-# define GETPC() ((void *)((uintptr_t)__builtin_return_address(0) - 1))
+# define GETPC() ((uintptr_t)__builtin_return_address(0) - 1)
#endif
#if !defined(CONFIG_USER_ONLY)
@@ -305,7 +306,7 @@ void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr,
uint64_t value, unsigned size);
void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr);
+ uintptr_t retaddr);
#include "softmmu_defs.h"
diff --git a/exec.c b/exec.c
index 03d3a6b609..77d6866c38 100644
--- a/exec.c
+++ b/exec.c
@@ -93,8 +93,7 @@ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
#define code_gen_section \
__attribute__((__section__(".gen_code"))) \
__attribute__((aligned (32)))
-#elif defined(_WIN32)
-/* Maximum alignment for Win32 is 16. */
+#elif defined(_WIN32) && !defined(_WIN64)
#define code_gen_section \
__attribute__((aligned (16)))
#else
@@ -177,9 +176,9 @@ typedef struct PageDesc {
#define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS)
-unsigned long qemu_real_host_page_size;
-unsigned long qemu_host_page_size;
-unsigned long qemu_host_page_mask;
+uintptr_t qemu_real_host_page_size;
+uintptr_t qemu_host_page_size;
+uintptr_t qemu_host_page_mask;
/* This is a multi-level map on the virtual address space.
The bottom level has pointers to PageDesc. */
@@ -888,8 +887,8 @@ static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
for(;;) {
tb1 = *ptb;
- n1 = (long)tb1 & 3;
- tb1 = (TranslationBlock *)((long)tb1 & ~3);
+ n1 = (uintptr_t)tb1 & 3;
+ tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
if (tb1 == tb) {
*ptb = tb1->page_next[n1];
break;
@@ -909,8 +908,8 @@ static inline void tb_jmp_remove(TranslationBlock *tb, int n)
/* find tb(n) in circular list */
for(;;) {
tb1 = *ptb;
- n1 = (long)tb1 & 3;
- tb1 = (TranslationBlock *)((long)tb1 & ~3);
+ n1 = (uintptr_t)tb1 & 3;
+ tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
if (n1 == n && tb1 == tb)
break;
if (n1 == 2) {
@@ -930,7 +929,7 @@ static inline void tb_jmp_remove(TranslationBlock *tb, int n)
another TB */
static inline void tb_reset_jump(TranslationBlock *tb, int n)
{
- tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
+ tb_set_jmp_target(tb, n, (uintptr_t)(tb->tc_ptr + tb->tb_next_offset[n]));
}
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
@@ -975,16 +974,16 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
/* suppress any remaining jumps to this TB */
tb1 = tb->jmp_first;
for(;;) {
- n1 = (long)tb1 & 3;
+ n1 = (uintptr_t)tb1 & 3;
if (n1 == 2)
break;
- tb1 = (TranslationBlock *)((long)tb1 & ~3);
+ tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
tb2 = tb1->jmp_next[n1];
tb_reset_jump(tb1, n1);
tb1->jmp_next[n1] = NULL;
tb1 = tb2;
}
- tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
+ tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */
tb_phys_invalidate_count++;
}
@@ -1025,8 +1024,8 @@ static void build_page_bitmap(PageDesc *p)
tb = p->first_tb;
while (tb != NULL) {
- n = (long)tb & 3;
- tb = (TranslationBlock *)((long)tb & ~3);
+ n = (uintptr_t)tb & 3;
+ tb = (TranslationBlock *)((uintptr_t)tb & ~3);
/* NOTE: this is subtle as a TB may span two physical pages */
if (n == 0) {
/* NOTE: tb_end may be after the end of the page, but
@@ -1070,7 +1069,8 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
tb->flags = flags;
tb->cflags = cflags;
cpu_gen_code(env, tb, &code_gen_size);
- code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
+ code_gen_ptr = (void *)(((uintptr_t)code_gen_ptr + code_gen_size +
+ CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
/* check next page if needed */
virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
@@ -1118,8 +1118,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
/* XXX: see if in some cases it could be faster to invalidate all the code */
tb = p->first_tb;
while (tb != NULL) {
- n = (long)tb & 3;
- tb = (TranslationBlock *)((long)tb & ~3);
+ n = (uintptr_t)tb & 3;
+ tb = (TranslationBlock *)((uintptr_t)tb & ~3);
tb_next = tb->page_next[n];
/* NOTE: this is subtle as a TB may span two physical pages */
if (n == 0) {
@@ -1202,7 +1202,8 @@ static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len)
qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
cpu_single_env->mem_io_vaddr, len,
cpu_single_env->eip,
- cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
+ cpu_single_env->eip +
+ (intptr_t)cpu_single_env->segs[R_CS].base);
}
#endif
p = page_find(start >> TARGET_PAGE_BITS);
@@ -1221,7 +1222,7 @@ static inline void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len)
#if !defined(CONFIG_SOFTMMU)
static void tb_invalidate_phys_page(tb_page_addr_t addr,
- unsigned long pc, void *puc)
+ uintptr_t pc, void *puc)
{
TranslationBlock *tb;
PageDesc *p;
@@ -1246,8 +1247,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
}
#endif
while (tb != NULL) {
- n = (long)tb & 3;
- tb = (TranslationBlock *)((long)tb & ~3);
+ n = (uintptr_t)tb & 3;
+ tb = (TranslationBlock *)((uintptr_t)tb & ~3);
#ifdef TARGET_HAS_PRECISE_SMC
if (current_tb == tb &&
(current_tb->cflags & CF_COUNT_MASK) != 1) {
@@ -1295,7 +1296,7 @@ static inline void tb_alloc_page(TranslationBlock *tb,
#ifndef CONFIG_USER_ONLY
page_already_protected = p->first_tb != NULL;
#endif
- p->first_tb = (TranslationBlock *)((long)tb | n);
+ p->first_tb = (TranslationBlock *)((uintptr_t)tb | n);
invalidate_page_bitmap(p);
#if defined(TARGET_HAS_SMC) || 1
@@ -1362,7 +1363,7 @@ void tb_link_page(TranslationBlock *tb,
else
tb->page_addr[1] = -1;
- tb->jmp_first = (TranslationBlock *)((long)tb | 2);
+ tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2);
tb->jmp_next[0] = NULL;
tb->jmp_next[1] = NULL;
@@ -1383,21 +1384,22 @@ void tb_link_page(TranslationBlock *tb,
TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
{
int m_min, m_max, m;
- unsigned long v;
+ uintptr_t v;
TranslationBlock *tb;
if (nb_tbs <= 0)
return NULL;
- if (tc_ptr < (unsigned long)code_gen_buffer ||
- tc_ptr >= (unsigned long)code_gen_ptr)
+ if (tc_ptr < (uintptr_t)code_gen_buffer ||
+ tc_ptr >= (uintptr_t)code_gen_ptr) {
return NULL;
+ }
/* binary search (cf Knuth) */
m_min = 0;
m_max = nb_tbs - 1;
while (m_min <= m_max) {
m = (m_min + m_max) >> 1;
tb = &tbs[m];
- v = (unsigned long)tb->tc_ptr;
+ v = (uintptr_t)tb->tc_ptr;
if (v == tc_ptr)
return tb;
else if (tc_ptr < v) {
@@ -1420,8 +1422,8 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
if (tb1 != NULL) {
/* find head of list */
for(;;) {
- n1 = (long)tb1 & 3;
- tb1 = (TranslationBlock *)((long)tb1 & ~3);
+ n1 = (uintptr_t)tb1 & 3;
+ tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
if (n1 == 2)
break;
tb1 = tb1->jmp_next[n1];
@@ -1433,8 +1435,8 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
ptb = &tb_next->jmp_first;
for(;;) {
tb1 = *ptb;
- n1 = (long)tb1 & 3;
- tb1 = (TranslationBlock *)((long)tb1 & ~3);
+ n1 = (uintptr_t)tb1 & 3;
+ tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
if (n1 == n && tb1 == tb)
break;
ptb = &tb1->jmp_next[n1];
@@ -1463,13 +1465,11 @@ static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
tb_invalidate_phys_page_range(pc, pc + 1, 0);
}
#else
-static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
+void tb_invalidate_phys_addr(target_phys_addr_t addr)
{
- target_phys_addr_t addr;
ram_addr_t ram_addr;
MemoryRegionSection *section;
- addr = cpu_get_phys_page_debug(env, pc);
section = phys_page_find(addr >> TARGET_PAGE_BITS);
if (!(memory_region_is_ram(section->mr)
|| (section->mr->rom_device && section->mr->readable))) {
@@ -1479,6 +1479,11 @@ static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
+ section_addr(section, addr);
tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
}
+
+static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
+{
+ tb_invalidate_phys_addr(cpu_get_phys_page_debug(env, pc));
+}
#endif
#endif /* TARGET_HAS_ICE */
@@ -2038,9 +2043,9 @@ static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
}
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
- unsigned long start, unsigned long length)
+ uintptr_t start, uintptr_t length)
{
- unsigned long addr;
+ uintptr_t addr;
if (tlb_is_dirty_ram(tlb_entry)) {
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
if ((addr - start) < length) {
@@ -2054,7 +2059,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
int dirty_flags)
{
CPUArchState *env;
- unsigned long length, start1;
+ uintptr_t length, start1;
int i;
start &= TARGET_PAGE_MASK;
@@ -2067,10 +2072,10 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
/* we modify the TLB cache so that the dirty bit will be set again
when accessing the range */
- start1 = (unsigned long)qemu_safe_ram_ptr(start);
+ start1 = (uintptr_t)qemu_safe_ram_ptr(start);
/* Check that we don't span multiple blocks - this breaks the
address comparisons below. */
- if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
+ if ((uintptr_t)qemu_safe_ram_ptr(end - 1) - start1
!= (end - 1) - start) {
abort();
}
@@ -2098,7 +2103,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
void *p;
if (tlb_is_dirty_ram(tlb_entry)) {
- p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
+ p = (void *)(uintptr_t)((tlb_entry->addr_write & TARGET_PAGE_MASK)
+ tlb_entry->addend);
ram_addr = qemu_ram_addr_from_host_nofail(p);
if (!cpu_physical_memory_is_dirty(ram_addr)) {
@@ -2188,7 +2193,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
unsigned int index;
target_ulong address;
target_ulong code_address;
- unsigned long addend;
+ uintptr_t addend;
CPUTLBEntry *te;
CPUWatchpoint *wp;
target_phys_addr_t iotlb;
@@ -2210,7 +2215,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
address |= TLB_MMIO;
}
if (is_ram_rom_romd(section)) {
- addend = (unsigned long)memory_region_get_ram_ptr(section->mr)
+ addend = (uintptr_t)memory_region_get_ram_ptr(section->mr)
+ section_addr(section, paddr);
} else {
addend = 0;
@@ -2300,7 +2305,7 @@ struct walk_memory_regions_data
{
walk_memory_regions_fn fn;
void *priv;
- unsigned long start;
+ uintptr_t start;
int prot;
};
@@ -2361,7 +2366,7 @@ static int walk_memory_regions_1(struct walk_memory_regions_data *data,
int walk_memory_regions(void *priv, walk_memory_regions_fn fn)
{
struct walk_memory_regions_data data;
- unsigned long i;
+ uintptr_t i;
data.fn = fn;
data.priv = priv;
@@ -2549,7 +2554,7 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
}
static inline void tlb_set_dirty(CPUArchState *env,
- unsigned long addr, target_ulong vaddr)
+ uintptr_t addr, target_ulong vaddr)
{
}
#endif /* defined(CONFIG_USER_ONLY) */
@@ -4477,20 +4482,20 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
/* in deterministic execution mode, instructions doing device I/Os
must be at the end of the TB */
-void cpu_io_recompile(CPUArchState *env, void *retaddr)
+void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
{
TranslationBlock *tb;
uint32_t n, cflags;
target_ulong pc, cs_base;
uint64_t flags;
- tb = tb_find_pc((uintptr_t)retaddr);
+ tb = tb_find_pc(retaddr);
if (!tb) {
cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
- retaddr);
+ (void *)retaddr);
}
n = env->icount_decr.u16.low + tb->icount;
- cpu_restore_state(tb, env, (unsigned long)retaddr);
+ cpu_restore_state(tb, env, retaddr);
/* Calculate how many instructions had been executed before the fault
occurred. */
n = n - env->icount_decr.u16.low;
@@ -4638,7 +4643,7 @@ bool virtio_is_big_endian(void)
#define MMUSUFFIX _cmmu
#undef GETPC
-#define GETPC() NULL
+#define GETPC() ((uintptr_t)0)
#define env cpu_single_env
#define SOFTMMU_CODE_ACCESS
diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index 71142e51f5..5a7b365548 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -20,36 +20,38 @@
#include "sysbus.h"
-/* Configuration for arm_gic.c:
- * max number of CPUs, how to ID current CPU
- */
-#define NCPU 4
-
-static inline int gic_get_current_cpu(void)
-{
- return cpu_single_env->cpu_index;
-}
-
-#include "arm_gic.c"
-
/* A15MP private memory region. */
typedef struct A15MPPrivState {
- gic_state gic;
+ SysBusDevice busdev;
uint32_t num_cpu;
uint32_t num_irq;
MemoryRegion container;
+ DeviceState *gic;
} A15MPPrivState;
+static void a15mp_priv_set_irq(void *opaque, int irq, int level)
+{
+ A15MPPrivState *s = (A15MPPrivState *)opaque;
+ qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+}
+
static int a15mp_priv_init(SysBusDevice *dev)
{
- A15MPPrivState *s = FROM_SYSBUSGIC(A15MPPrivState, dev);
+ A15MPPrivState *s = FROM_SYSBUS(A15MPPrivState, dev);
+ SysBusDevice *busdev;
+
+ s->gic = qdev_create(NULL, "arm_gic");
+ qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+ qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
+ qdev_init_nofail(s->gic);
+ busdev = sysbus_from_qdev(s->gic);
- if (s->num_cpu > NCPU) {
- hw_error("a15mp_priv_init: num-cpu may not be more than %d\n", NCPU);
- }
+ /* Pass through outbound IRQ lines from the GIC */
+ sysbus_pass_irq(dev, busdev);
- gic_init(&s->gic, s->num_cpu, s->num_irq);
+ /* Pass through inbound GPIO lines to the GIC */
+ qdev_init_gpio_in(&s->busdev.qdev, a15mp_priv_set_irq, s->num_irq - 32);
/* Memory map (addresses are offsets from PERIPHBASE):
* 0x0000-0x0fff -- reserved
@@ -60,8 +62,10 @@ static int a15mp_priv_init(SysBusDevice *dev)
* 0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
*/
memory_region_init(&s->container, "a15mp-priv-container", 0x8000);
- memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
- memory_region_add_subregion(&s->container, 0x2000, &s->gic.cpuiomem[0]);
+ memory_region_add_subregion(&s->container, 0x1000,
+ sysbus_mmio_get_region(busdev, 0));
+ memory_region_add_subregion(&s->container, 0x2000,
+ sysbus_mmio_get_region(busdev, 1));
sysbus_init_mmio(dev, &s->container);
return 0;
@@ -85,7 +89,7 @@ static void a15mp_priv_class_init(ObjectClass *klass, void *data)
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = a15mp_priv_init;
dc->props = a15mp_priv_properties;
- /* We currently have no savable state outside the common GIC state */
+ /* We currently have no savable state */
}
static TypeInfo a15mp_priv_info = {
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 03b128ce5b..c2ff74d4b6 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -10,32 +10,19 @@
#include "sysbus.h"
-/* Configuration for arm_gic.c:
- * max number of CPUs, how to ID current CPU
- */
-#define NCPU 4
-
-static inline int
-gic_get_current_cpu(void)
-{
- return cpu_single_env->cpu_index;
-}
-
-#include "arm_gic.c"
-
/* A9MP private memory region. */
typedef struct a9mp_priv_state {
- gic_state gic;
+ SysBusDevice busdev;
uint32_t scu_control;
uint32_t scu_status;
uint32_t old_timer_status[8];
uint32_t num_cpu;
- qemu_irq *timer_irq;
MemoryRegion scu_iomem;
MemoryRegion ptimer_iomem;
MemoryRegion container;
DeviceState *mptimer;
+ DeviceState *gic;
uint32_t num_irq;
} a9mp_priv_state;
@@ -124,18 +111,9 @@ static const MemoryRegionOps a9_scu_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void a9mpcore_timer_irq_handler(void *opaque, int irq, int level)
-{
- a9mp_priv_state *s = (a9mp_priv_state *)opaque;
- if (level && !s->old_timer_status[irq]) {
- gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
- }
- s->old_timer_status[irq] = level;
-}
-
static void a9mp_priv_reset(DeviceState *dev)
{
- a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, sysbus_from_qdev(dev));
+ a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, sysbus_from_qdev(dev));
int i;
s->scu_control = 0;
for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
@@ -143,17 +121,29 @@ static void a9mp_priv_reset(DeviceState *dev)
}
}
+static void a9mp_priv_set_irq(void *opaque, int irq, int level)
+{
+ a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+ qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+}
+
static int a9mp_priv_init(SysBusDevice *dev)
{
- a9mp_priv_state *s = FROM_SYSBUSGIC(a9mp_priv_state, dev);
- SysBusDevice *busdev;
+ a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, dev);
+ SysBusDevice *busdev, *gicbusdev;
int i;
- if (s->num_cpu > NCPU) {
- hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
- }
+ s->gic = qdev_create(NULL, "arm_gic");
+ qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+ qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
+ qdev_init_nofail(s->gic);
+ gicbusdev = sysbus_from_qdev(s->gic);
- gic_init(&s->gic, s->num_cpu, s->num_irq);
+ /* Pass through outbound IRQ lines from the GIC */
+ sysbus_pass_irq(dev, gicbusdev);
+
+ /* Pass through inbound GPIO lines to the GIC */
+ qdev_init_gpio_in(&s->busdev.qdev, a9mp_priv_set_irq, s->num_irq - 32);
s->mptimer = qdev_create(NULL, "arm_mptimer");
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -175,7 +165,8 @@ static int a9mp_priv_init(SysBusDevice *dev)
memory_region_init_io(&s->scu_iomem, &a9_scu_ops, s, "a9mp-scu", 0x100);
memory_region_add_subregion(&s->container, 0, &s->scu_iomem);
/* GIC CPU interface */
- memory_region_add_subregion(&s->container, 0x100, &s->gic.cpuiomem[0]);
+ memory_region_add_subregion(&s->container, 0x100,
+ sysbus_mmio_get_region(gicbusdev, 1));
/* Note that the A9 exposes only the "timer/watchdog for this core"
* memory region, not the "timer/watchdog for core X" ones 11MPcore has.
*/
@@ -183,15 +174,20 @@ static int a9mp_priv_init(SysBusDevice *dev)
sysbus_mmio_get_region(busdev, 0));
memory_region_add_subregion(&s->container, 0x620,
sysbus_mmio_get_region(busdev, 1));
- memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+ memory_region_add_subregion(&s->container, 0x1000,
+ sysbus_mmio_get_region(gicbusdev, 0));
sysbus_init_mmio(dev, &s->container);
- /* Wire up the interrupt from each watchdog and timer. */
- s->timer_irq = qemu_allocate_irqs(a9mpcore_timer_irq_handler,
- s, (s->num_cpu + 1) * 2);
- for (i = 0; i < s->num_cpu * 2; i++) {
- sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+ /* Wire up the interrupt from each watchdog and timer.
+ * For each core the timer is PPI 29 and the watchdog PPI 30.
+ */
+ for (i = 0; i < s->num_cpu; i++) {
+ int ppibase = (s->num_irq - 32) + i * 32;
+ sysbus_connect_irq(busdev, i * 2,
+ qdev_get_gpio_in(s->gic, ppibase + 29));
+ sysbus_connect_irq(busdev, i * 2 + 1,
+ qdev_get_gpio_in(s->gic, ppibase + 30));
}
return 0;
}
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index ba6a89d3ed..c528d7aa01 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,28 +10,18 @@
#include "sysbus.h"
#include "qemu-timer.h"
-#define NCPU 4
-
-static inline int
-gic_get_current_cpu(void)
-{
- return cpu_single_env->cpu_index;
-}
-
-#include "arm_gic.c"
-
/* MPCore private memory region. */
typedef struct mpcore_priv_state {
- gic_state gic;
+ SysBusDevice busdev;
uint32_t scu_control;
int iomemtype;
uint32_t old_timer_status[8];
uint32_t num_cpu;
- qemu_irq *timer_irq;
MemoryRegion iomem;
MemoryRegion container;
DeviceState *mptimer;
+ DeviceState *gic;
uint32_t num_irq;
} mpcore_priv_state;
@@ -81,18 +71,16 @@ static const MemoryRegionOps mpcore_scu_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void mpcore_timer_irq_handler(void *opaque, int irq, int level)
+static void mpcore_priv_set_irq(void *opaque, int irq, int level)
{
mpcore_priv_state *s = (mpcore_priv_state *)opaque;
- if (level && !s->old_timer_status[irq]) {
- gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
- }
- s->old_timer_status[irq] = level;
+ qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
}
static void mpcore_priv_map_setup(mpcore_priv_state *s)
{
int i;
+ SysBusDevice *gicbusdev = sysbus_from_qdev(s->gic);
SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
@@ -102,31 +90,47 @@ static void mpcore_priv_map_setup(mpcore_priv_state *s)
*/
for (i = 0; i < (s->num_cpu + 1); i++) {
target_phys_addr_t offset = 0x100 + (i * 0x100);
- memory_region_add_subregion(&s->container, offset, &s->gic.cpuiomem[i]);
+ memory_region_add_subregion(&s->container, offset,
+ sysbus_mmio_get_region(gicbusdev, i + 1));
}
/* Add the regions for timer and watchdog for "current CPU" and
* for each specific CPU.
*/
- s->timer_irq = qemu_allocate_irqs(mpcore_timer_irq_handler,
- s, (s->num_cpu + 1) * 2);
for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
/* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
memory_region_add_subregion(&s->container, offset,
sysbus_mmio_get_region(busdev, i));
}
- memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
- /* Wire up the interrupt from each watchdog and timer. */
- for (i = 0; i < s->num_cpu * 2; i++) {
- sysbus_connect_irq(busdev, i, s->timer_irq[i]);
+ memory_region_add_subregion(&s->container, 0x1000,
+ sysbus_mmio_get_region(gicbusdev, 0));
+ /* Wire up the interrupt from each watchdog and timer.
+ * For each core the timer is PPI 29 and the watchdog PPI 30.
+ */
+ for (i = 0; i < s->num_cpu; i++) {
+ int ppibase = (s->num_irq - 32) + i * 32;
+ sysbus_connect_irq(busdev, i * 2,
+ qdev_get_gpio_in(s->gic, ppibase + 29));
+ sysbus_connect_irq(busdev, i * 2 + 1,
+ qdev_get_gpio_in(s->gic, ppibase + 30));
}
}
static int mpcore_priv_init(SysBusDevice *dev)
{
- mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
+ mpcore_priv_state *s = FROM_SYSBUS(mpcore_priv_state, dev);
+
+ s->gic = qdev_create(NULL, "arm_gic");
+ qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+ qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
+ qdev_init_nofail(s->gic);
+
+ /* Pass through outbound IRQ lines from the GIC */
+ sysbus_pass_irq(dev, sysbus_from_qdev(s->gic));
+
+ /* Pass through inbound GPIO lines to the GIC */
+ qdev_init_gpio_in(&s->busdev.qdev, mpcore_priv_set_irq, s->num_irq - 32);
- gic_init(&s->gic, s->num_cpu, s->num_irq);
s->mptimer = qdev_create(NULL, "arm_mptimer");
qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
qdev_init_nofail(s->mptimer);
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 6b34c06a8f..72298b4b41 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -8,13 +8,29 @@
*/
/* This file contains implementation code for the RealView EB interrupt
- controller, MPCore distributed interrupt controller and ARMv7-M
- Nested Vectored Interrupt Controller. */
+ * controller, MPCore distributed interrupt controller and ARMv7-M
+ * Nested Vectored Interrupt Controller.
+ * It is compiled in two ways:
+ * (1) as a standalone file to produce a sysbus device which is a GIC
+ * that can be used on the realview board and as one of the builtin
+ * private peripherals for the ARM MP CPUs (11MPCore, A9, etc)
+ * (2) by being directly #included into armv7m_nvic.c to produce the
+ * armv7m_nvic device.
+ */
+
+#include "sysbus.h"
/* Maximum number of possible interrupts, determined by the GIC architecture */
#define GIC_MAXIRQ 1020
/* First 32 are private to each CPU (SGIs and PPIs). */
#define GIC_INTERNAL 32
+/* Maximum number of possible CPU interfaces, determined by GIC architecture */
+#ifdef NVIC
+#define NCPU 1
+#else
+#define NCPU 8
+#endif
+
//#define DEBUG_GIC
#ifdef DEBUG_GIC
@@ -50,7 +66,7 @@ typedef struct gic_irq_state
unsigned trigger:1; /* nonzero = edge triggered. */
} gic_irq_state;
-#define ALL_CPU_MASK ((1 << NCPU) - 1)
+#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1)))
#if NCPU > 1
#define NUM_CPU(s) ((s)->num_cpu)
#else
@@ -105,7 +121,7 @@ typedef struct gic_state
int current_pending[NCPU];
#if NCPU > 1
- int num_cpu;
+ uint32_t num_cpu;
#endif
MemoryRegion iomem; /* Distributor */
@@ -119,6 +135,16 @@ typedef struct gic_state
uint32_t num_irq;
} gic_state;
+static inline int gic_get_current_cpu(gic_state *s)
+{
+#if NCPU > 1
+ if (s->num_cpu > 1) {
+ return cpu_single_env->cpu_index;
+ }
+#endif
+ return 0;
+}
+
/* TODO: Many places that call this routine could be optimized. */
/* Update interrupt status after enabled or pending bits have been changed. */
static void gic_update(gic_state *s)
@@ -134,7 +160,7 @@ static void gic_update(gic_state *s)
cm = 1 << cpu;
s->current_pending[cpu] = 1023;
if (!s->enabled || !s->cpu_enabled[cpu]) {
- qemu_irq_lower(s->parent_irq[cpu]);
+ qemu_irq_lower(s->parent_irq[cpu]);
return;
}
best_prio = 0x100;
@@ -159,8 +185,8 @@ static void gic_update(gic_state *s)
}
}
-static void __attribute__((unused))
-gic_set_pending_private(gic_state *s, int cpu, int irq)
+#ifdef NVIC
+static void gic_set_pending_private(gic_state *s, int cpu, int irq)
{
int cm = 1 << cpu;
@@ -171,24 +197,45 @@ gic_set_pending_private(gic_state *s, int cpu, int irq)
GIC_SET_PENDING(irq, cm);
gic_update(s);
}
+#endif
/* Process a change in an external IRQ input. */
static void gic_set_irq(void *opaque, int irq, int level)
{
+ /* Meaning of the 'irq' parameter:
+ * [0..N-1] : external interrupts
+ * [N..N+31] : PPI (internal) interrupts for CPU 0
+ * [N+32..N+63] : PPI (internal interrupts for CPU 1
+ * ...
+ */
gic_state *s = (gic_state *)opaque;
- /* The first external input line is internal interrupt 32. */
- irq += GIC_INTERNAL;
- if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
+ int cm, target;
+ if (irq < (s->num_irq - GIC_INTERNAL)) {
+ /* The first external input line is internal interrupt 32. */
+ cm = ALL_CPU_MASK;
+ irq += GIC_INTERNAL;
+ target = GIC_TARGET(irq);
+ } else {
+ int cpu;
+ irq -= (s->num_irq - GIC_INTERNAL);
+ cpu = irq / GIC_INTERNAL;
+ irq %= GIC_INTERNAL;
+ cm = 1 << cpu;
+ target = cm;
+ }
+
+ if (level == GIC_TEST_LEVEL(irq, cm)) {
return;
+ }
if (level) {
- GIC_SET_LEVEL(irq, ALL_CPU_MASK);
- if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, ALL_CPU_MASK)) {
- DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
- GIC_SET_PENDING(irq, GIC_TARGET(irq));
+ GIC_SET_LEVEL(irq, cm);
+ if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
+ DPRINTF("Set %d pending mask %x\n", irq, target);
+ GIC_SET_PENDING(irq, target);
}
} else {
- GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
+ GIC_CLEAR_LEVEL(irq, cm);
}
gic_update(s);
}
@@ -278,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
int cm;
int mask;
- cpu = gic_get_current_cpu();
+ cpu = gic_get_current_cpu(s);
cm = 1 << cpu;
if (offset < 0x100) {
#ifndef NVIC
@@ -413,7 +460,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
int i;
int cpu;
- cpu = gic_get_current_cpu();
+ cpu = gic_get_current_cpu(s);
if (offset < 0x100) {
#ifdef NVIC
goto bad_reg;
@@ -575,7 +622,7 @@ static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
int irq;
int mask;
- cpu = gic_get_current_cpu();
+ cpu = gic_get_current_cpu(s);
irq = value & 0x3ff;
switch ((value >> 24) & 3) {
case 0:
@@ -658,14 +705,14 @@ static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
gic_state *s = (gic_state *)opaque;
- return gic_cpu_read(s, gic_get_current_cpu(), addr);
+ return gic_cpu_read(s, gic_get_current_cpu(s), addr);
}
static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
uint64_t value, unsigned size)
{
gic_state *s = (gic_state *)opaque;
- gic_cpu_write(s, gic_get_current_cpu(), addr, value);
+ gic_cpu_write(s, gic_get_current_cpu(s), addr, value);
}
/* Wrappers to read/write the GIC CPU interface for a specific CPU.
@@ -702,8 +749,9 @@ static const MemoryRegionOps gic_cpu_ops = {
};
#endif
-static void gic_reset(gic_state *s)
+static void gic_reset(DeviceState *dev)
{
+ gic_state *s = FROM_SYSBUS(gic_state, sysbus_from_qdev(dev));
int i;
memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
for (i = 0 ; i < NUM_CPU(s); i++) {
@@ -813,6 +861,10 @@ static void gic_init(gic_state *s, int num_irq)
#if NCPU > 1
s->num_cpu = num_cpu;
+ if (s->num_cpu > NCPU) {
+ hw_error("requested %u CPUs exceeds GIC maximum %d\n",
+ num_cpu, NCPU);
+ }
#endif
s->num_irq = num_irq + GIC_BASE_IRQ;
if (s->num_irq > GIC_MAXIRQ) {
@@ -828,7 +880,18 @@ static void gic_init(gic_state *s, int num_irq)
num_irq);
}
- qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - GIC_INTERNAL);
+ i = s->num_irq - GIC_INTERNAL;
+#ifndef NVIC
+ /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+ * GPIO array layout is thus:
+ * [0..N-1] SPIs
+ * [N..N+31] PPIs for CPU 0
+ * [N+32..N+63] PPIs for CPU 1
+ * ...
+ */
+ i += (GIC_INTERNAL * num_cpu);
+#endif
+ qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, i);
for (i = 0; i < NUM_CPU(s); i++) {
sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
}
@@ -851,6 +914,54 @@ static void gic_init(gic_state *s, int num_irq)
}
#endif
- gic_reset(s);
register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
}
+
+#ifndef NVIC
+
+static int arm_gic_init(SysBusDevice *dev)
+{
+ /* Device instance init function for the GIC sysbus device */
+ int i;
+ gic_state *s = FROM_SYSBUS(gic_state, dev);
+ gic_init(s, s->num_cpu, s->num_irq);
+ /* Distributor */
+ sysbus_init_mmio(dev, &s->iomem);
+ /* cpu interfaces (one for "current cpu" plus one per cpu) */
+ for (i = 0; i <= NUM_CPU(s); i++) {
+ sysbus_init_mmio(dev, &s->cpuiomem[i]);
+ }
+ return 0;
+}
+
+static Property arm_gic_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", gic_state, num_cpu, 1),
+ DEFINE_PROP_UINT32("num-irq", gic_state, num_irq, 32),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_gic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+ sbc->init = arm_gic_init;
+ dc->props = arm_gic_properties;
+ dc->reset = gic_reset;
+ dc->no_user = 1;
+}
+
+static TypeInfo arm_gic_info = {
+ .name = "arm_gic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(gic_state),
+ .class_init = arm_gic_class_init,
+};
+
+static void arm_gic_register_types(void)
+{
+ type_register_static(&arm_gic_info);
+}
+
+type_init(arm_gic_register_types)
+
+#endif
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 3210129c3f..986a6bbd0c 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,16 +15,8 @@
#include "arm-misc.h"
#include "exec-memory.h"
-#define NCPU 1
#define NVIC 1
-/* Only a single "CPU" interface is present. */
-static inline int
-gic_get_current_cpu(void)
-{
- return 0;
-}
-
static uint32_t nvic_readl(void *opaque, uint32_t offset);
static void nvic_writel(void *opaque, uint32_t offset, uint32_t value);
@@ -83,6 +75,14 @@ static void systick_timer_tick(void * opaque)
}
}
+static void systick_reset(nvic_state *s)
+{
+ s->systick.control = 0;
+ s->systick.reload = 0;
+ s->systick.tick = 0;
+ qemu_del_timer(s->systick.timer);
+}
+
/* The external routines use the hardware vector numbering, ie. the first
IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
void armv7m_nvic_set_pending(void *opaque, int irq)
@@ -378,6 +378,13 @@ static const VMStateDescription vmstate_nvic = {
}
};
+static void armv7m_nvic_reset(DeviceState *dev)
+{
+ nvic_state *s = FROM_SYSBUSGIC(nvic_state, sysbus_from_qdev(dev));
+ gic_reset(&s->gic.busdev.qdev);
+ systick_reset(s);
+}
+
static int armv7m_nvic_init(SysBusDevice *dev)
{
nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
@@ -407,6 +414,7 @@ static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
sdc->init = armv7m_nvic_init;
dc->vmsd = &vmstate_nvic;
+ dc->reset = armv7m_nvic_reset;
dc->props = armv7m_nvic_properties;
}
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index f904370505..afc4bdc7e0 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -25,6 +25,7 @@
#include "sysemu.h"
#include "sysbus.h"
#include "arm-misc.h"
+#include "loader.h"
#include "exynos4210.h"
#define EXYNOS4210_CHIPID_ADDR 0x10000000
@@ -64,6 +65,35 @@
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
0x09, 0x00, 0x00, 0x00 };
+void exynos4210_write_secondary(CPUARMState *env,
+ const struct arm_boot_info *info)
+{
+ int n;
+ uint32_t smpboot[] = {
+ 0xe59f3024, /* ldr r3, External gic_cpu_if */
+ 0xe59f2024, /* ldr r2, Internal gic_cpu_if */
+ 0xe59f0024, /* ldr r0, startaddr */
+ 0xe3a01001, /* mov r1, #1 */
+ 0xe5821000, /* str r1, [r2] */
+ 0xe5831000, /* str r1, [r3] */
+ 0xe320f003, /* wfi */
+ 0xe5901000, /* ldr r1, [r0] */
+ 0xe1110001, /* tst r1, r1 */
+ 0x0afffffb, /* beq <wfi> */
+ 0xe12fff11, /* bx r1 */
+ EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
+ 0, /* gic_cpu_if: base address of Internal GIC CPU interface */
+ 0 /* bootreg: Boot register address is held here */
+ };
+ smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+ smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
+ for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+ smpboot[n] = tswap32(smpboot[n]);
+ }
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+ info->smp_loader_start);
+}
+
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
unsigned long ram_size)
{
diff --git a/hw/exynos4210.h b/hw/exynos4210.h
index c112e03bfb..f7c7027302 100644
--- a/hw/exynos4210.h
+++ b/hw/exynos4210.h
@@ -97,6 +97,9 @@ typedef struct Exynos4210State {
MemoryRegion bootreg_mem;
} Exynos4210State;
+void exynos4210_write_secondary(CPUARMState *env,
+ const struct arm_boot_info *info);
+
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
unsigned long ram_size);
diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c
index 6110c19d5d..80af22cc33 100644
--- a/hw/exynos4210_combiner.c
+++ b/hw/exynos4210_combiner.c
@@ -184,11 +184,6 @@ exynos4210_combiner_read(void *opaque, target_phys_addr_t offset, unsigned size)
uint32_t reg_n; /* Register number inside the quad */
uint32_t val;
- if (s->external && (offset > 0x3c && offset != 0x100)) {
- hw_error("exynos4210.combiner: unallowed read access at offset 0x"
- TARGET_FMT_plx "\n", offset);
- }
-
req_quad_base_n = offset >> 4;
grp_quad_base_n = req_quad_base_n << 2;
reg_n = (offset - (req_quad_base_n << 4)) >> 2;
@@ -281,11 +276,6 @@ static void exynos4210_combiner_write(void *opaque, target_phys_addr_t offset,
uint32_t grp_quad_base_n; /* Base of group quad */
uint32_t reg_n; /* Register number inside the quad */
- if (s->external && (offset > 0x3c && offset != 0x100)) {
- hw_error("exynos4210.combiner: unallowed write access at offset 0x"
- TARGET_FMT_plx "\n", offset);
- }
-
req_quad_base_n = offset >> 4;
grp_quad_base_n = req_quad_base_n << 2;
reg_n = (offset - (req_quad_base_n << 4)) >> 2;
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index ec13140f9f..e1b215eff0 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -174,7 +174,6 @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
};
#define EXYNOS4210_GIC_NIRQ 160
-#define NCPU EXYNOS4210_NCPUS
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
#define EXYNOS4210_EXT_GIC_DIST_REGION_SIZE 0x10000
@@ -263,33 +262,44 @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
/********* GIC part *********/
-static inline int
-gic_get_current_cpu(void)
-{
- return cpu_single_env->cpu_index;
-}
-
-#include "arm_gic.c"
-
typedef struct {
- gic_state gic;
+ SysBusDevice busdev;
MemoryRegion cpu_container;
MemoryRegion dist_container;
- MemoryRegion cpu_alias[NCPU];
- MemoryRegion dist_alias[NCPU];
+ MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
+ MemoryRegion dist_alias[EXYNOS4210_NCPUS];
uint32_t num_cpu;
+ DeviceState *gic;
} Exynos4210GicState;
+static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
+{
+ Exynos4210GicState *s = (Exynos4210GicState *)opaque;
+ qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+}
+
static int exynos4210_gic_init(SysBusDevice *dev)
{
- Exynos4210GicState *s = FROM_SYSBUSGIC(Exynos4210GicState, dev);
+ Exynos4210GicState *s = FROM_SYSBUS(Exynos4210GicState, dev);
uint32_t i;
const char cpu_prefix[] = "exynos4210-gic-alias_cpu";
const char dist_prefix[] = "exynos4210-gic-alias_dist";
char cpu_alias_name[sizeof(cpu_prefix) + 3];
char dist_alias_name[sizeof(cpu_prefix) + 3];
+ SysBusDevice *busdev;
+
+ s->gic = qdev_create(NULL, "arm_gic");
+ qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+ qdev_prop_set_uint32(s->gic, "num-irq", EXYNOS4210_GIC_NIRQ);
+ qdev_init_nofail(s->gic);
+ busdev = sysbus_from_qdev(s->gic);
- gic_init(&s->gic, s->num_cpu, EXYNOS4210_GIC_NIRQ);
+ /* Pass through outbound IRQ lines from the GIC */
+ sysbus_pass_irq(dev, busdev);
+
+ /* Pass through inbound GPIO lines to the GIC */
+ qdev_init_gpio_in(&s->busdev.qdev, exynos4210_gic_set_irq,
+ EXYNOS4210_GIC_NIRQ - 32);
memory_region_init(&s->cpu_container, "exynos4210-cpu-container",
EXYNOS4210_EXT_GIC_CPU_REGION_SIZE);
@@ -301,7 +311,7 @@ static int exynos4210_gic_init(SysBusDevice *dev)
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
memory_region_init_alias(&s->cpu_alias[i],
cpu_alias_name,
- &s->gic.cpuiomem[0],
+ sysbus_mmio_get_region(busdev, 1),
0,
EXYNOS4210_GIC_CPU_REGION_SIZE);
memory_region_add_subregion(&s->cpu_container,
@@ -311,7 +321,7 @@ static int exynos4210_gic_init(SysBusDevice *dev)
sprintf(dist_alias_name, "%s%x", dist_prefix, i);
memory_region_init_alias(&s->dist_alias[i],
dist_alias_name,
- &s->gic.iomem,
+ sysbus_mmio_get_region(busdev, 0),
0,
EXYNOS4210_GIC_DIST_REGION_SIZE);
memory_region_add_subregion(&s->dist_container,
@@ -321,8 +331,6 @@ static int exynos4210_gic_init(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->cpu_container);
sysbus_init_mmio(dev, &s->dist_container);
- gic_cpu_write(&s->gic, 1, 0, 1);
-
return 0;
}
@@ -361,7 +369,7 @@ type_init(exynos4210_gic_register_types)
typedef struct {
SysBusDevice busdev;
- qemu_irq pic_irq[NCPU]; /* output IRQs to PICs */
+ qemu_irq pic_irq[EXYNOS4210_NCPUS]; /* output IRQs to PICs */
uint32_t gpio_level[EXYNOS4210_IRQ_GATE_NINPUTS]; /* Input levels */
} Exynos4210IRQGateState;
@@ -426,7 +434,7 @@ static int exynos4210_irq_gate_init(SysBusDevice *dev)
EXYNOS4210_IRQ_GATE_NINPUTS);
/* Connect SysBusDev irqs to device specific irqs */
- for (i = 0; i < NCPU; i++) {
+ for (i = 0; i < EXYNOS4210_NCPUS; i++) {
sysbus_init_irq(dev, &s->pic_irq[i]);
}
diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
index 73a9c18f30..ccc47804f9 100644
--- a/hw/exynos4210_uart.c
+++ b/hw/exynos4210_uart.c
@@ -246,7 +246,7 @@ static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(Exynos4210UartState *s)
uint32_t level = 0;
uint32_t reg;
- reg = (s->reg[I_(UFCON)] && UFCON_Tx_FIFO_TRIGGER_LEVEL) >>
+ reg = (s->reg[I_(UFCON)] & UFCON_Tx_FIFO_TRIGGER_LEVEL) >>
UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT;
switch (s->channel) {
@@ -275,9 +275,9 @@ static void exynos4210_uart_update_irq(Exynos4210UartState *s)
* The Tx interrupt is always requested if the number of data in the
* transmit FIFO is smaller than the trigger level.
*/
- if (s->reg[I_(UFCON)] && UFCON_FIFO_ENABLE) {
+ if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
- uint32_t count = (s->reg[I_(UFSTAT)] && UFSTAT_Tx_FIFO_COUNT) >>
+ uint32_t count = (s->reg[I_(UFSTAT)] & UFSTAT_Tx_FIFO_COUNT) >>
UFSTAT_Tx_FIFO_COUNT_SHIFT;
if (count <= exynos4210_uart_Tx_FIFO_trigger_level(s)) {
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
index 553a02b910..ea32c51dcc 100644
--- a/hw/exynos4_boards.c
+++ b/hw/exynos4_boards.c
@@ -70,6 +70,7 @@ static struct arm_boot_info exynos4_board_binfo = {
.loader_start = EXYNOS4210_BASE_BOOT_ADDR,
.smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
.nb_cpus = EXYNOS4210_NCPUS,
+ .write_secondary_boot = exynos4210_write_secondary,
};
static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS];
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index c2bdd926c5..d48e5f9906 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -354,8 +354,8 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
guest_curr_max = s->peers[posn].nb_eventfds;
for (i = 0; i < guest_curr_max; i++) {
- kvm_set_ioeventfd_mmio_long(s->peers[posn].eventfds[i],
- s->mmio_addr + DOORBELL, (posn << 16) | i, 0);
+ kvm_set_ioeventfd_mmio(s->peers[posn].eventfds[i],
+ s->mmio_addr + DOORBELL, (posn << 16) | i, 0, 4);
close(s->peers[posn].eventfds[i]);
}
@@ -500,8 +500,8 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
}
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
- if (kvm_set_ioeventfd_mmio_long(incoming_fd, s->mmio_addr + DOORBELL,
- (incoming_posn << 16) | guest_max_eventfd, 1) < 0) {
+ if (kvm_set_ioeventfd_mmio(incoming_fd, s->mmio_addr + DOORBELL,
+ (incoming_posn << 16) | guest_max_eventfd, 1, 4) < 0) {
fprintf(stderr, "ivshmem: ioeventfd not available\n");
}
}
diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c
index 446bd62176..824b978397 100644
--- a/hw/kvm/clock.c
+++ b/hw/kvm/clock.c
@@ -65,9 +65,25 @@ static void kvmclock_vm_state_change(void *opaque, int running,
RunState state)
{
KVMClockState *s = opaque;
+ CPUArchState *penv = first_cpu;
+ int cap_clock_ctrl = kvm_check_extension(kvm_state, KVM_CAP_KVMCLOCK_CTRL);
+ int ret;
if (running) {
s->clock_valid = false;
+
+ if (!cap_clock_ctrl) {
+ return;
+ }
+ for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
+ ret = kvm_vcpu_ioctl(penv, KVM_KVMCLOCK_CTRL, 0);
+ if (ret) {
+ if (ret != -EINVAL) {
+ fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
+ }
+ return;
+ }
+ }
}
}
diff --git a/hw/pc.c b/hw/pc.c
index 67f0479f40..1f5aacb2d2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -42,6 +42,7 @@
#include "sysbus.h"
#include "sysemu.h"
#include "kvm.h"
+#include "xen.h"
#include "blockdev.h"
#include "ui/qemu-spice.h"
#include "memory.h"
@@ -891,9 +892,12 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
if (kvm_irqchip_in_kernel()) {
dev = qdev_create(NULL, "kvm-apic");
+ } else if (xen_enabled()) {
+ dev = qdev_create(NULL, "xen-apic");
} else {
dev = qdev_create(NULL, "apic");
}
+
qdev_prop_set_uint8(dev, "id", apic_id);
qdev_prop_set_ptr(dev, "cpu_env", env);
qdev_init_nofail(dev);
@@ -912,6 +916,10 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
msi_supported = true;
}
+ if (xen_enabled()) {
+ msi_supported = true;
+ }
+
return dev;
}
diff --git a/hw/ps2.h b/hw/ps2.h
index 32a4231e32..7c45ce7ced 100644
--- a/hw/ps2.h
+++ b/hw/ps2.h
@@ -1,3 +1,30 @@
+/*
+ * QEMU PS/2 keyboard/mouse emulation
+ *
+ * Copyright (C) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_PS2_H
+#define HW_PS2_H
+
/* ps2.c */
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);
@@ -7,3 +34,5 @@ uint32_t ps2_read_data(void *);
void ps2_queue(void *, int b);
void ps2_keyboard_set_translation(void *opaque, int mode);
void ps2_mouse_fake_event(void *opaque);
+
+#endif /* !HW_PS2_H */
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 071ef13c9e..5bc37a7120 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,39 +9,45 @@
#include "sysbus.h"
-#define NCPU 1
-
-/* Only a single "CPU" interface is present. */
-static inline int
-gic_get_current_cpu(void)
-{
- return 0;
-}
-
-#include "arm_gic.c"
-
typedef struct {
- gic_state gic;
+ SysBusDevice busdev;
+ DeviceState *gic;
MemoryRegion container;
} RealViewGICState;
-static void realview_gic_map_setup(RealViewGICState *s)
+static void realview_gic_set_irq(void *opaque, int irq, int level)
{
- memory_region_init(&s->container, "realview-gic-container", 0x2000);
- memory_region_add_subregion(&s->container, 0, &s->gic.cpuiomem[0]);
- memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
+ RealViewGICState *s = (RealViewGICState *)opaque;
+ qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
}
static int realview_gic_init(SysBusDevice *dev)
{
- RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
-
+ RealViewGICState *s = FROM_SYSBUS(RealViewGICState, dev);
+ SysBusDevice *busdev;
/* The GICs on the RealView boards have a fixed nonconfigurable
* number of interrupt lines, so we don't need to expose this as
* a qdev property.
*/
- gic_init(&s->gic, 96);
- realview_gic_map_setup(s);
+ int numirq = 96;
+
+ s->gic = qdev_create(NULL, "arm_gic");
+ qdev_prop_set_uint32(s->gic, "num-cpu", 1);
+ qdev_prop_set_uint32(s->gic, "num-irq", numirq);
+ qdev_init_nofail(s->gic);
+ busdev = sysbus_from_qdev(s->gic);
+
+ /* Pass through outbound IRQ lines from the GIC */
+ sysbus_pass_irq(dev, busdev);
+
+ /* Pass through inbound GPIO lines to the GIC */
+ qdev_init_gpio_in(&s->busdev.qdev, realview_gic_set_irq, numirq - 32);
+
+ memory_region_init(&s->container, "realview-gic-container", 0x2000);
+ memory_region_add_subregion(&s->container, 0,
+ sysbus_mmio_get_region(busdev, 1));
+ memory_region_add_subregion(&s->container, 0x1000,
+ sysbus_mmio_get_region(busdev, 0));
sysbus_init_mmio(dev, &s->container);
return 0;
}
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 4d553a8a59..4d0f5ba518 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2482,15 +2482,17 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
rtl8139_transmit(s);
}
-static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint8_t addr, int size)
+static uint32_t rtl8139_TxStatus_TxAddr_read(RTL8139State *s, uint32_t regs[],
+ uint32_t base, uint8_t addr,
+ int size)
{
- uint32_t reg = (addr - TxStatus0) / 4;
+ uint32_t reg = (addr - base) / 4;
uint32_t offset = addr & 0x3;
uint32_t ret = 0;
if (addr & (size - 1)) {
- DPRINTF("not implemented read for TxStatus addr=0x%x size=0x%x\n", addr,
- size);
+ DPRINTF("not implemented read for TxStatus/TxAddr "
+ "addr=0x%x size=0x%x\n", addr, size);
return ret;
}
@@ -2498,12 +2500,12 @@ static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint8_t addr, int size)
case 1: /* fall through */
case 2: /* fall through */
case 4:
- ret = (s->TxStatus[reg] >> offset * 8) & ((1 << (size * 8)) - 1);
- DPRINTF("TxStatus[%d] read addr=0x%x size=0x%x val=0x%08x\n", reg, addr,
- size, ret);
+ ret = (regs[reg] >> offset * 8) & ((1 << (size * 8)) - 1);
+ DPRINTF("TxStatus/TxAddr[%d] read addr=0x%x size=0x%x val=0x%08x\n",
+ reg, addr, size, ret);
break;
default:
- DPRINTF("unsupported size 0x%x of TxStatus reading\n", size);
+ DPRINTF("unsupported size 0x%x of TxStatus/TxAddr reading\n", size);
break;
}
@@ -2977,7 +2979,8 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
ret = s->mult[addr - MAR0];
break;
case TxStatus0 ... TxStatus0+4*4-1:
- ret = rtl8139_TxStatus_read(s, addr, 1);
+ ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0,
+ addr, 1);
break;
case ChipCmd:
ret = rtl8139_ChipCmd_read(s);
@@ -3043,7 +3046,7 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
switch (addr)
{
case TxAddr0 ... TxAddr0+4*4-1:
- ret = rtl8139_TxStatus_read(s, addr, 2);
+ ret = rtl8139_TxStatus_TxAddr_read(s, s->TxAddr, TxAddr0, addr, 2);
break;
case IntrMask:
ret = rtl8139_IntrMask_read(s);
@@ -3135,7 +3138,8 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
break;
case TxStatus0 ... TxStatus0+4*4-1:
- ret = rtl8139_TxStatus_read(s, addr, 4);
+ ret = rtl8139_TxStatus_TxAddr_read(s, s->TxStatus, TxStatus0,
+ addr, 4);
break;
case TxAddr0 ... TxAddr0+4*4-1:
diff --git a/hw/spapr.h b/hw/spapr.h
index 11160b02da..654a7a8a34 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -272,7 +272,7 @@ extern sPAPREnvironment *spapr;
#ifdef DEBUG_SPAPR_HCALLS
#define hcall_dprintf(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+ do { fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); } while (0)
#else
#define hcall_dprintf(fmt, ...) \
do { } while (0)
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index cfc777804b..e18d2eb901 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -182,6 +182,15 @@ static NetClientInfo net_spapr_vlan_info = {
.receive = spapr_vlan_receive,
};
+static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
+{
+ VIOsPAPRVLANDevice *dev = DO_UPCAST(VIOsPAPRVLANDevice, sdev, sdev);
+
+ dev->buf_list = 0;
+ dev->rx_bufs = 0;
+ dev->isopen = 0;
+}
+
static int spapr_vlan_init(VIOsPAPRDevice *sdev)
{
VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
@@ -279,21 +288,19 @@ static target_ulong h_register_logical_lan(CPUPPCState *env,
if (check_bd(dev, VLAN_VALID_BD(buf_list, SPAPR_VIO_TCE_PAGE_SIZE),
SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
- hcall_dprintf("Bad buf_list 0x" TARGET_FMT_lx " for "
- "H_REGISTER_LOGICAL_LAN\n", buf_list);
+ hcall_dprintf("Bad buf_list 0x" TARGET_FMT_lx "\n", buf_list);
return H_PARAMETER;
}
filter_list_bd = VLAN_VALID_BD(filter_list, SPAPR_VIO_TCE_PAGE_SIZE);
if (check_bd(dev, filter_list_bd, SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
- hcall_dprintf("Bad filter_list 0x" TARGET_FMT_lx " for "
- "H_REGISTER_LOGICAL_LAN\n", filter_list);
+ hcall_dprintf("Bad filter_list 0x" TARGET_FMT_lx "\n", filter_list);
return H_PARAMETER;
}
if (!(rec_queue & VLAN_BD_VALID)
|| (check_bd(dev, rec_queue, VLAN_RQ_ALIGNMENT) < 0)) {
- hcall_dprintf("Bad receive queue for H_REGISTER_LOGICAL_LAN\n");
+ hcall_dprintf("Bad receive queue\n");
return H_PARAMETER;
}
@@ -337,9 +344,7 @@ static target_ulong h_free_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr
return H_RESOURCE;
}
- dev->buf_list = 0;
- dev->rx_bufs = 0;
- dev->isopen = 0;
+ spapr_vlan_reset(sdev);
return H_SUCCESS;
}
@@ -358,13 +363,13 @@ static target_ulong h_add_logical_lan_buffer(CPUPPCState *env,
", 0x" TARGET_FMT_lx ")\n", reg, buf);
if (!sdev) {
- hcall_dprintf("Wrong device in h_add_logical_lan_buffer\n");
+ hcall_dprintf("Bad device\n");
return H_PARAMETER;
}
if ((check_bd(dev, buf, 4) < 0)
|| (VLAN_BD_LEN(buf) < 16)) {
- hcall_dprintf("Bad buffer enqueued in h_add_logical_lan_buffer\n");
+ hcall_dprintf("Bad buffer enqueued\n");
return H_PARAMETER;
}
@@ -486,6 +491,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
k->init = spapr_vlan_init;
+ k->reset = spapr_vlan_reset;
k->devnode = spapr_vlan_devnode;
k->dt_name = "l-lan";
k->dt_type = "network";
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index e7ef551c1c..a564c007b4 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -57,26 +57,38 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr,
static uint32_t rtas_pci_cfgaddr(uint32_t arg)
{
+ /* This handles the encoding of extended config space addresses */
return ((arg >> 20) & 0xf00) | (arg & 0xff);
}
-static uint32_t rtas_read_pci_config_do(PCIDevice *pci_dev, uint32_t addr,
- uint32_t limit, uint32_t len)
+static void finish_read_pci_config(sPAPREnvironment *spapr, uint64_t buid,
+ uint32_t addr, uint32_t size,
+ target_ulong rets)
{
- if ((addr + len) <= limit) {
- return pci_host_config_read_common(pci_dev, addr, limit, len);
- } else {
- return ~0x0;
+ PCIDevice *pci_dev;
+ uint32_t val;
+
+ if ((size != 1) && (size != 2) && (size != 4)) {
+ /* access must be 1, 2 or 4 bytes */
+ rtas_st(rets, 0, -1);
+ return;
}
-}
-static void rtas_write_pci_config_do(PCIDevice *pci_dev, uint32_t addr,
- uint32_t limit, uint32_t val,
- uint32_t len)
-{
- if ((addr + len) <= limit) {
- pci_host_config_write_common(pci_dev, addr, limit, val, len);
+ pci_dev = find_dev(spapr, buid, addr);
+ addr = rtas_pci_cfgaddr(addr);
+
+ if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
+ /* Access must be to a valid device, within bounds and
+ * naturally aligned */
+ rtas_st(rets, 0, -1);
+ return;
}
+
+ val = pci_host_config_read_common(pci_dev, addr,
+ pci_config_size(pci_dev), size);
+
+ rtas_st(rets, 0, 0);
+ rtas_st(rets, 1, val);
}
static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
@@ -84,19 +96,19 @@ static void rtas_ibm_read_pci_config(sPAPREnvironment *spapr,
target_ulong args,
uint32_t nret, target_ulong rets)
{
- uint32_t val, size, addr;
- uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
- PCIDevice *dev = find_dev(spapr, buid, rtas_ld(args, 0));
+ uint64_t buid;
+ uint32_t size, addr;
- if (!dev) {
+ if ((nargs != 4) || (nret != 2)) {
rtas_st(rets, 0, -1);
return;
}
+
+ buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
size = rtas_ld(args, 3);
- addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
- val = rtas_read_pci_config_do(dev, addr, pci_config_size(dev), size);
- rtas_st(rets, 0, 0);
- rtas_st(rets, 1, val);
+ addr = rtas_ld(args, 0);
+
+ finish_read_pci_config(spapr, buid, addr, size, rets);
}
static void rtas_read_pci_config(sPAPREnvironment *spapr,
@@ -104,18 +116,45 @@ static void rtas_read_pci_config(sPAPREnvironment *spapr,
target_ulong args,
uint32_t nret, target_ulong rets)
{
- uint32_t val, size, addr;
- PCIDevice *dev = find_dev(spapr, 0, rtas_ld(args, 0));
+ uint32_t size, addr;
- if (!dev) {
+ if ((nargs != 2) || (nret != 2)) {
rtas_st(rets, 0, -1);
return;
}
+
size = rtas_ld(args, 1);
- addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
- val = rtas_read_pci_config_do(dev, addr, pci_config_size(dev), size);
+ addr = rtas_ld(args, 0);
+
+ finish_read_pci_config(spapr, 0, addr, size, rets);
+}
+
+static void finish_write_pci_config(sPAPREnvironment *spapr, uint64_t buid,
+ uint32_t addr, uint32_t size,
+ uint32_t val, target_ulong rets)
+{
+ PCIDevice *pci_dev;
+
+ if ((size != 1) && (size != 2) && (size != 4)) {
+ /* access must be 1, 2 or 4 bytes */
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ pci_dev = find_dev(spapr, buid, addr);
+ addr = rtas_pci_cfgaddr(addr);
+
+ if (!pci_dev || (addr % size) || (addr >= pci_config_size(pci_dev))) {
+ /* Access must be to a valid device, within bounds and
+ * naturally aligned */
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ pci_host_config_write_common(pci_dev, addr, pci_config_size(pci_dev),
+ val, size);
+
rtas_st(rets, 0, 0);
- rtas_st(rets, 1, val);
}
static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
@@ -123,19 +162,20 @@ static void rtas_ibm_write_pci_config(sPAPREnvironment *spapr,
target_ulong args,
uint32_t nret, target_ulong rets)
{
+ uint64_t buid;
uint32_t val, size, addr;
- uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
- PCIDevice *dev = find_dev(spapr, buid, rtas_ld(args, 0));
- if (!dev) {
+ if ((nargs != 5) || (nret != 1)) {
rtas_st(rets, 0, -1);
return;
}
+
+ buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
val = rtas_ld(args, 4);
size = rtas_ld(args, 3);
- addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
- rtas_write_pci_config_do(dev, addr, pci_config_size(dev), val, size);
- rtas_st(rets, 0, 0);
+ addr = rtas_ld(args, 0);
+
+ finish_write_pci_config(spapr, buid, addr, size, val, rets);
}
static void rtas_write_pci_config(sPAPREnvironment *spapr,
@@ -144,17 +184,18 @@ static void rtas_write_pci_config(sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
uint32_t val, size, addr;
- PCIDevice *dev = find_dev(spapr, 0, rtas_ld(args, 0));
- if (!dev) {
+ if ((nargs != 3) || (nret != 1)) {
rtas_st(rets, 0, -1);
return;
}
+
+
val = rtas_ld(args, 2);
size = rtas_ld(args, 1);
- addr = rtas_pci_cfgaddr(rtas_ld(args, 0));
- rtas_write_pci_config_do(dev, addr, pci_config_size(dev), val, size);
- rtas_st(rets, 0, 0);
+ addr = rtas_ld(args, 0);
+
+ finish_write_pci_config(spapr, 0, addr, size, val, rets);
}
static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num)
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 09465853ba..ae18595150 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -44,8 +44,7 @@ static void rtas_display_character(sPAPREnvironment *spapr,
uint32_t nret, target_ulong rets)
{
uint8_t c = rtas_ld(args, 0);
- VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus,
- SPAPR_VTY_BASE_ADDRESS);
+ VIOsPAPRDevice *sdev = vty_lookup(spapr, 0);
if (!sdev) {
rtas_st(rets, 0, -1);
@@ -112,6 +111,19 @@ static void rtas_power_off(sPAPREnvironment *spapr,
rtas_st(rets, 0, 0);
}
+static void rtas_system_reboot(sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ if (nargs != 0 || nret != 1) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+ qemu_system_reset_request();
+ rtas_st(rets, 0, 0);
+}
+
static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
@@ -294,6 +306,7 @@ static void core_rtas_register_types(void)
spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
spapr_rtas_register("power-off", rtas_power_off);
+ spapr_rtas_register("system-reboot", rtas_system_reboot);
spapr_rtas_register("query-cpu-stopped-state",
rtas_query_cpu_stopped_state);
spapr_rtas_register("start-cpu", rtas_start_cpu);
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index dbf5a9017e..fccf48bd67 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -204,8 +204,7 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
VIOsPAPR_RTCE *rtce;
if (!dev) {
- hcall_dprintf("spapr_vio_put_tce on non-existent LIOBN "
- TARGET_FMT_lx "\n", liobn);
+ hcall_dprintf("LIOBN 0x" TARGET_FMT_lx " does not exist\n", liobn);
return H_PARAMETER;
}
@@ -217,8 +216,7 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
#endif
if (ioba >= dev->rtce_window_size) {
- hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
- TARGET_FMT_lx "\n", ioba);
+ hcall_dprintf("Out-of-bounds IOBA 0x" TARGET_FMT_lx "\n", ioba);
return H_PARAMETER;
}
@@ -414,33 +412,32 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
if (!dev) {
- hcall_dprintf("h_reg_crq on non-existent unit 0x"
- TARGET_FMT_lx "\n", reg);
+ hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
return H_PARAMETER;
}
/* We can't grok a queue size bigger than 256M for now */
if (queue_len < 0x1000 || queue_len > 0x10000000) {
- hcall_dprintf("h_reg_crq, queue size too small or too big (0x%llx)\n",
- (unsigned long long)queue_len);
+ hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
+ ")\n", queue_len);
return H_PARAMETER;
}
/* Check queue alignment */
if (queue_addr & 0xfff) {
- hcall_dprintf("h_reg_crq, queue not aligned (0x%llx)\n",
- (unsigned long long)queue_addr);
+ hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
return H_PARAMETER;
}
/* Check if device supports CRQs */
if (!dev->crq.SendFunc) {
+ hcall_dprintf("Device does not support CRQ\n");
return H_NOT_FOUND;
}
-
/* Already a queue ? */
if (dev->crq.qsize) {
+ hcall_dprintf("CRQ already registered\n");
return H_RESOURCE;
}
dev->crq.qladdr = queue_addr;
@@ -453,6 +450,17 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
return H_SUCCESS;
}
+static target_ulong free_crq(VIOsPAPRDevice *dev)
+{
+ dev->crq.qladdr = 0;
+ dev->crq.qsize = 0;
+ dev->crq.qnext = 0;
+
+ dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
+
+ return H_SUCCESS;
+}
+
static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
@@ -460,18 +468,11 @@ static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
if (!dev) {
- hcall_dprintf("h_free_crq on non-existent unit 0x"
- TARGET_FMT_lx "\n", reg);
+ hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
return H_PARAMETER;
}
- dev->crq.qladdr = 0;
- dev->crq.qsize = 0;
- dev->crq.qnext = 0;
-
- dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg);
-
- return H_SUCCESS;
+ return free_crq(dev);
}
static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
@@ -484,8 +485,7 @@ static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
uint64_t crq_mangle[2];
if (!dev) {
- hcall_dprintf("h_send_crq on non-existent unit 0x"
- TARGET_FMT_lx "\n", reg);
+ hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
return H_PARAMETER;
}
crq_mangle[0] = cpu_to_be64(msg_hi);
@@ -505,8 +505,7 @@ static target_ulong h_enable_crq(CPUPPCState *env, sPAPREnvironment *spapr,
VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
if (!dev) {
- hcall_dprintf("h_enable_crq on non-existent unit 0x"
- TARGET_FMT_lx "\n", reg);
+ hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
return H_PARAMETER;
}
@@ -649,6 +648,20 @@ static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
return 0;
}
+static void spapr_vio_busdev_reset(DeviceState *qdev)
+{
+ VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+ VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+
+ if (dev->crq.qsize) {
+ free_crq(dev);
+ }
+
+ if (pc->reset) {
+ pc->reset(dev);
+ }
+}
+
static int spapr_vio_busdev_init(DeviceState *qdev)
{
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
@@ -766,6 +779,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = spapr_vio_busdev_init;
+ k->reset = spapr_vio_busdev_reset;
k->bus_info = &spapr_vio_bus_info;
}
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index d8527bed90..10ab3594c0 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -64,7 +64,7 @@ typedef struct VIOsPAPRDeviceClass {
const char *dt_name, *dt_type, *dt_compatible;
target_ulong signal_mask;
int (*init)(VIOsPAPRDevice *dev);
- void (*hcalls)(VIOsPAPRBus *bus);
+ void (*reset)(VIOsPAPRDevice *dev);
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
} VIOsPAPRDeviceClass;
@@ -89,8 +89,6 @@ struct VIOsPAPRDevice {
struct VIOsPAPRBus {
BusState bus;
- const char *dt_name, *dt_type, *dt_compatible;
- target_ulong signal_mask;
int (*init)(VIOsPAPRDevice *dev);
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
};
@@ -119,6 +117,7 @@ uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr);
int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
+VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev);
void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd);
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 21670170e8..538e0b7938 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -99,10 +99,6 @@ typedef struct {
vscsi_req reqs[VSCSI_REQ_LIMIT];
} VSCSIState;
-/* XXX Debug only */
-static VSCSIState *dbg_vscsi_state;
-
-
static struct vscsi_req *vscsi_get_req(VSCSIState *s)
{
vscsi_req *req;
@@ -897,18 +893,20 @@ static const struct SCSIBusInfo vscsi_scsi_info = {
.cancel = vscsi_request_cancelled
};
-static int spapr_vscsi_init(VIOsPAPRDevice *dev)
+static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
{
VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
int i;
- dbg_vscsi_state = s;
-
- /* Initialize qemu request tags */
memset(s->reqs, 0, sizeof(s->reqs));
for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
s->reqs[i].qtag = i;
}
+}
+
+static int spapr_vscsi_init(VIOsPAPRDevice *dev)
+{
+ VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
dev->crq.SendFunc = vscsi_do_crq;
@@ -958,6 +956,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
k->init = spapr_vscsi_init;
+ k->reset = spapr_vscsi_reset;
k->devnode = spapr_vscsi_devnode;
k->dt_name = "v-scsi";
k->dt_type = "vscsi";
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index 60e22b1600..a30c040b97 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -70,8 +70,6 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
}
/* Forward declaration */
-static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
-
static target_ulong h_put_term_char(CPUPPCState *env, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
@@ -195,7 +193,7 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
return selected;
}
-static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
+VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
{
VIOsPAPRDevice *sdev;
diff --git a/hw/xen.h b/hw/xen.h
index b46879c6f7..e5926b7b8a 100644
--- a/hw/xen.h
+++ b/hw/xen.h
@@ -34,6 +34,7 @@ static inline int xen_enabled(void)
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
void xen_piix3_set_irq(void *opaque, int irq_num, int level);
void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data);
void xen_cmos_set_s3_resume(void *opaque, int irq, int level);
qemu_irq *xen_interrupt_controller_init(void);
diff --git a/hw/xen_apic.c b/hw/xen_apic.c
new file mode 100644
index 0000000000..1725ff67dd
--- /dev/null
+++ b/hw/xen_apic.c
@@ -0,0 +1,90 @@
+/*
+ * Xen basic APIC support
+ *
+ * Copyright (c) 2012 Citrix
+ *
+ * Authors:
+ * Wei Liu <wei.liu2@citrix.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+#include "hw/apic_internal.h"
+#include "hw/msi.h"
+#include "xen.h"
+
+static uint64_t xen_apic_mem_read(void *opaque, target_phys_addr_t addr,
+ unsigned size)
+{
+ return ~(uint64_t)0;
+}
+
+static void xen_apic_mem_write(void *opaque, target_phys_addr_t addr,
+ uint64_t data, unsigned size)
+{
+ if (size != sizeof(uint32_t)) {
+ fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
+ return;
+ }
+
+ xen_hvm_inject_msi(addr, data);
+}
+
+static const MemoryRegionOps xen_apic_io_ops = {
+ .read = xen_apic_mem_read,
+ .write = xen_apic_mem_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void xen_apic_init(APICCommonState *s)
+{
+ memory_region_init_io(&s->io_memory, &xen_apic_io_ops, s, "xen-apic-msi",
+ MSI_SPACE_SIZE);
+}
+
+static void xen_apic_set_base(APICCommonState *s, uint64_t val)
+{
+}
+
+static void xen_apic_set_tpr(APICCommonState *s, uint8_t val)
+{
+}
+
+static uint8_t xen_apic_get_tpr(APICCommonState *s)
+{
+ return 0;
+}
+
+static void xen_apic_vapic_base_update(APICCommonState *s)
+{
+}
+
+static void xen_apic_external_nmi(APICCommonState *s)
+{
+}
+
+static void xen_apic_class_init(ObjectClass *klass, void *data)
+{
+ APICCommonClass *k = APIC_COMMON_CLASS(klass);
+
+ k->init = xen_apic_init;
+ k->set_base = xen_apic_set_base;
+ k->set_tpr = xen_apic_set_tpr;
+ k->get_tpr = xen_apic_get_tpr;
+ k->vapic_base_update = xen_apic_vapic_base_update;
+ k->external_nmi = xen_apic_external_nmi;
+}
+
+static TypeInfo xen_apic_info = {
+ .name = "xen-apic",
+ .parent = TYPE_APIC_COMMON,
+ .instance_size = sizeof(APICCommonState),
+ .class_init = xen_apic_class_init,
+};
+
+static void xen_apic_register_types(void)
+{
+ type_register_static(&xen_apic_info);
+}
+
+type_init(xen_apic_register_types)
diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 2673ace185..66cb144397 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -592,7 +592,7 @@ static void xenstore_update_be(char *watch, char *type, int dom,
struct XenDevOps *ops)
{
struct XenDevice *xendev;
- char path[XEN_BUFSIZE], *dom0;
+ char path[XEN_BUFSIZE], *dom0, *bepath;
unsigned int len, dev;
dom0 = xs_get_domain_path(xenstore, 0);
@@ -611,15 +611,16 @@ static void xenstore_update_be(char *watch, char *type, int dom,
return;
}
- if (0) {
- /* FIXME: detect devices being deleted from xenstore ... */
- xen_be_del_xendev(dom, dev);
- }
-
xendev = xen_be_get_xendev(type, dom, dev, ops);
if (xendev != NULL) {
- xen_be_backend_changed(xendev, path);
- xen_be_check_state(xendev);
+ bepath = xs_read(xenstore, 0, xendev->be, &len);
+ if (bepath == NULL) {
+ xen_be_del_xendev(dom, dev);
+ } else {
+ free(bepath);
+ xen_be_backend_changed(xendev, path);
+ xen_be_check_state(xendev);
+ }
}
}
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 9719395b09..22dbd10303 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -745,6 +745,10 @@ static int blk_free(struct XenDevice *xendev)
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
struct ioreq *ioreq;
+ if (blkdev->bs || blkdev->sring) {
+ blk_disconnect(xendev);
+ }
+
while (!QLIST_EMPTY(&blkdev->freelist)) {
ioreq = QLIST_FIRST(&blkdev->freelist);
QLIST_REMOVE(ioreq, list);
diff --git a/kvm-all.c b/kvm-all.c
index ba2cee10f2..b8e9dc69de 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -75,7 +75,6 @@ struct KVMState
#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
- int pit_in_kernel;
int pit_state2;
int xsave, xcrs;
int many_ioeventfds;
@@ -198,11 +197,6 @@ static void kvm_reset_vcpu(void *opaque)
kvm_arch_reset_vcpu(env);
}
-int kvm_pit_in_kernel(void)
-{
- return kvm_state->pit_in_kernel;
-}
-
int kvm_init_vcpu(CPUArchState *env)
{
KVMState *s = kvm_state;
@@ -747,10 +741,10 @@ static void kvm_mem_ioeventfd_add(MemoryRegionSection *section,
{
int r;
- assert(match_data && section->size == 4);
+ assert(match_data && section->size <= 8);
- r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
- data, true);
+ r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
+ data, true, section->size);
if (r < 0) {
abort();
}
@@ -761,8 +755,8 @@ static void kvm_mem_ioeventfd_del(MemoryRegionSection *section,
{
int r;
- r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
- data, false);
+ r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,
+ data, false, section->size);
if (r < 0) {
abort();
}
@@ -877,7 +871,7 @@ static void kvm_init_irq_routing(KVMState *s)
unsigned int gsi_bits, i;
/* Round up so we can search ints using ffs */
- gsi_bits = (gsi_count + 31) / 32;
+ gsi_bits = ALIGN(gsi_count, 32);
s->used_gsi_bitmap = g_malloc0(gsi_bits / 8);
s->max_gsi = gsi_bits;
@@ -1642,14 +1636,15 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
return r;
}
-int kvm_set_ioeventfd_mmio_long(int fd, uint32_t addr, uint32_t val, bool assign)
+int kvm_set_ioeventfd_mmio(int fd, uint32_t addr, uint32_t val, bool assign,
+ uint32_t size)
{
int ret;
struct kvm_ioeventfd iofd;
iofd.datamatch = val;
iofd.addr = addr;
- iofd.len = 4;
+ iofd.len = size;
iofd.flags = KVM_IOEVENTFD_FLAG_DATAMATCH;
iofd.fd = fd;
diff --git a/kvm-stub.c b/kvm-stub.c
index 69a1228756..47c573d6f3 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -16,12 +16,6 @@
#include "gdbstub.h"
#include "kvm.h"
-int kvm_pit_in_kernel(void)
-{
- return 0;
-}
-
-
int kvm_init_vcpu(CPUArchState *env)
{
return -ENOSYS;
@@ -120,7 +114,7 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
return -ENOSYS;
}
-int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign)
+int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign, uint32_t len)
{
return -ENOSYS;
}
diff --git a/kvm.h b/kvm.h
index 330f17b1db..4ccae8c0c8 100644
--- a/kvm.h
+++ b/kvm.h
@@ -83,8 +83,6 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset);
#endif
-int kvm_pit_in_kernel(void);
-
int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr);
int kvm_on_sigbus(int code, void *addr);
@@ -210,7 +208,8 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
#endif
#endif
-int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign);
+int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign,
+ uint32_t size);
int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
#endif
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index b921c3f489..1bea4d8ea6 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -277,6 +277,7 @@ struct kvm_sync_regs {
#define KVM_CPU_E500V2 2
#define KVM_CPU_3S_32 3
#define KVM_CPU_3S_64 4
+#define KVM_CPU_E500MC 5
/* for KVM_CAP_SPAPR_TCE */
struct kvm_create_spapr_tce {
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index 9acbde4af2..96076676e2 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -44,10 +44,12 @@ struct kvm_guest_debug_arch {
#define KVM_SYNC_PREFIX (1UL << 0)
#define KVM_SYNC_GPRS (1UL << 1)
#define KVM_SYNC_ACRS (1UL << 2)
+#define KVM_SYNC_CRS (1UL << 3)
/* definition of registers in kvm_run */
struct kvm_sync_regs {
__u64 prefix; /* prefix register */
__u64 gprs[16]; /* general purpose registers */
__u32 acrs[16]; /* access registers */
+ __u64 crs[16]; /* control registers */
};
#endif
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index f6b53432db..ee7bd9cc32 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -588,6 +588,8 @@ struct kvm_ppc_pvinfo {
#define KVM_CAP_TSC_DEADLINE_TIMER 72
#define KVM_CAP_S390_UCONTROL 73
#define KVM_CAP_SYNC_REGS 74
+#define KVM_CAP_PCI_2_3 75
+#define KVM_CAP_KVMCLOCK_CTRL 76
#ifdef KVM_CAP_IRQ_ROUTING
@@ -784,6 +786,9 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_TSC_CONTROL */
#define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2)
#define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3)
+/* Available with KVM_CAP_PCI_2_3 */
+#define KVM_ASSIGN_SET_INTX_MASK _IOW(KVMIO, 0xa4, \
+ struct kvm_assigned_pci_dev)
/*
* ioctls for vcpu fds
@@ -855,8 +860,12 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_ONE_REG */
#define KVM_GET_ONE_REG _IOW(KVMIO, 0xab, struct kvm_one_reg)
#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg)
+/* VM is being stopped by host */
+#define KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad)
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
+#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
+#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
struct kvm_assigned_pci_dev {
__u32 assigned_dev_id;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8a92162155..712861829a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5045,7 +5045,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
NULL, NULL, 0);
}
thread_env = NULL;
+#ifdef ENV_GET_CPU
+ object_delete(OBJECT(ENV_GET_CPU(cpu_env)));
+#else
g_free(cpu_env);
+#endif
g_free(ts);
pthread_exit(NULL);
}
diff --git a/main-loop.c b/main-loop.c
index 1ebdc4baf1..4887c732fa 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -430,7 +430,7 @@ static int os_host_main_loop_wait(int timeout)
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].fd = (DWORD_PTR)w->events[i];
poll_fds[n_poll_fds + i].events = G_IO_IN;
}
diff --git a/nbd.c b/nbd.c
index 567e94e27a..406e555bc6 100644
--- a/nbd.c
+++ b/nbd.c
@@ -813,7 +813,7 @@ static void nbd_trip(void *opaque)
LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
", Offset: %" PRIu64 "\n",
request.from, request.len,
- (uint64_t)exp->size, exp->dev_offset);
+ (uint64_t)exp->size, (uint64_t)exp->dev_offset);
LOG("requested operation past EOF--bad client?");
goto invalid_request;
}
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 8eda4bdc20..753679b194 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -30,6 +30,41 @@
#include <winsock2.h>
#include "main-loop.h"
+/* Workaround for older versions of MinGW. */
+#ifndef ECONNREFUSED
+# define ECONNREFUSED WSAECONNREFUSED
+#endif
+#ifndef EINPROGRESS
+# define EINPROGRESS WSAEINPROGRESS
+#endif
+#ifndef EHOSTUNREACH
+# define EHOSTUNREACH WSAEHOSTUNREACH
+#endif
+#ifndef EINTR
+# define EINTR WSAEINTR
+#endif
+#ifndef EINPROGRESS
+# define EINPROGRESS WSAEINPROGRESS
+#endif
+#ifndef ENETUNREACH
+# define ENETUNREACH WSAENETUNREACH
+#endif
+#ifndef ENOTCONN
+# define ENOTCONN WSAENOTCONN
+#endif
+#ifndef EWOULDBLOCK
+# define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+
+#if defined(_WIN64)
+/* On w64, setjmp is implemented by _setjmp which needs a second parameter.
+ * If this parameter is NULL, longjump does no stack unwinding.
+ * That is what we need for QEMU. Passing the value of register rsp (default)
+ * lets longjmp try a stack unwinding which will crash with generated code. */
+# undef setjmp
+# define setjmp(env) _setjmp(env, NULL)
+#endif
+
/* Declaration of ffs() is missing in MinGW's strings.h. */
int ffs(int i);
diff --git a/qemu_socket.h b/qemu_socket.h
index 51ad210a7f..a5d0a84fb6 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -8,12 +8,6 @@
#include <ws2tcpip.h>
#define socket_error() WSAGetLastError()
-#undef EWOULDBLOCK
-#undef EINTR
-#undef EINPROGRESS
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EINTR WSAEINTR
-#define EINPROGRESS WSAEINPROGRESS
int inet_aton(const char *cp, struct in_addr *ia);
diff --git a/savevm.c b/savevm.c
index 12fb20954f..2d18babd6e 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2106,7 +2106,8 @@ void do_savevm(Monitor *mon, const QDict *qdict)
}
} else {
#ifdef _WIN32
- ptm = localtime(&tb.time);
+ time_t t = tb.time;
+ ptm = localtime(&t);
strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
#else
/* cast below needed for OpenBSD where tv_sec is still 'long' */
diff --git a/scripts/kvm/kvm_flightrecorder b/scripts/kvm/kvm_flightrecorder
new file mode 100755
index 0000000000..7fb1c2d1a7
--- /dev/null
+++ b/scripts/kvm/kvm_flightrecorder
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+#
+# KVM Flight Recorder - ring buffer tracing script
+#
+# Copyright (C) 2012 IBM Corp
+#
+# Author: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+#
+# This script provides a command-line interface to kvm ftrace and is designed
+# to be used as a flight recorder that is always running. To start in-memory
+# recording:
+#
+# sudo kvm_flightrecorder start 8192 # 8 MB per-cpu ring buffers
+#
+# The per-cpu ring buffer size can be given in KB as an optional argument to
+# the 'start' subcommand.
+#
+# To stop the flight recorder:
+#
+# sudo kvm_flightrecorder stop
+#
+# To dump the contents of the flight recorder (this can be done when the
+# recorder is stopped or while it is running):
+#
+# sudo kvm_flightrecorder dump >/path/to/dump.txt
+#
+# To observe the trace while it is running, use the 'tail' subcommand:
+#
+# sudo kvm_flightrecorder tail
+#
+# Note that the flight recorder may impact overall system performance by
+# consuming CPU cycles. No disk I/O is performed since the ring buffer holds a
+# fixed-size in-memory trace.
+
+import sys
+import os
+
+tracing_dir = '/sys/kernel/debug/tracing'
+
+def trace_path(*args):
+ return os.path.join(tracing_dir, *args)
+
+def write_file(path, data):
+ open(path, 'wb').write(data)
+
+def enable_event(subsystem, event, enable):
+ write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0')
+
+def enable_subsystem(subsystem, enable):
+ write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0')
+
+def start_tracing():
+ enable_subsystem('kvm', True)
+ write_file(trace_path('tracing_on'), '1')
+
+def stop_tracing():
+ write_file(trace_path('tracing_on'), '0')
+ enable_subsystem('kvm', False)
+ write_file(trace_path('events', 'enable'), '0')
+ write_file(trace_path('current_tracer'), 'nop')
+
+def dump_trace():
+ tracefile = open(trace_path('trace'), 'r')
+ try:
+ lines = True
+ while lines:
+ lines = tracefile.readlines(64 * 1024)
+ sys.stdout.writelines(lines)
+ except KeyboardInterrupt:
+ pass
+
+def tail_trace():
+ try:
+ for line in open(trace_path('trace_pipe'), 'r'):
+ sys.stdout.write(line)
+ except KeyboardInterrupt:
+ pass
+
+def usage():
+ print 'Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0]
+ print 'Control the KVM flight recorder tracing.'
+ sys.exit(0)
+
+def main():
+ if len(sys.argv) < 2:
+ usage()
+
+ cmd = sys.argv[1]
+ if cmd == '--version':
+ print 'kvm_flightrecorder version 1.0'
+ sys.exit(0)
+
+ if not os.path.isdir(tracing_dir):
+ print 'Unable to tracing debugfs directory, try:'
+ print 'mount -t debugfs none /sys/kernel/debug'
+ sys.exit(1)
+ if not os.access(tracing_dir, os.W_OK):
+ print 'Unable to write to tracing debugfs directory, please run as root'
+ sys.exit(1)
+
+ if cmd == 'start':
+ stop_tracing() # clean up first
+
+ if len(sys.argv) == 3:
+ try:
+ buffer_size_kb = int(sys.argv[2])
+ except ValueError:
+ print 'Invalid per-cpu trace buffer size in KB'
+ sys.exit(1)
+ write_file(trace_path('buffer_size_kb'), str(buffer_size_kb))
+ print 'Per-CPU ring buffer size set to %d KB' % buffer_size_kb
+
+ start_tracing()
+ print 'KVM flight recorder enabled'
+ elif cmd == 'stop':
+ stop_tracing()
+ print 'KVM flight recorder disabled'
+ elif cmd == 'dump':
+ dump_trace()
+ elif cmd == 'tail':
+ tail_trace()
+ else:
+ usage()
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 46bfe4636d..f2c5eca892 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -15,18 +15,6 @@ typedef char *caddr_t;
# include <sys/timeb.h>
# include <iphlpapi.h>
-# undef EWOULDBLOCK
-# undef EINPROGRESS
-# undef ENOTCONN
-# undef EHOSTUNREACH
-# undef ENETUNREACH
-# undef ECONNREFUSED
-# define EWOULDBLOCK WSAEWOULDBLOCK
-# define EINPROGRESS WSAEINPROGRESS
-# define ENOTCONN WSAENOTCONN
-# define EHOSTUNREACH WSAEHOSTUNREACH
-# define ENETUNREACH WSAENETUNREACH
-# define ECONNREFUSED WSAECONNREFUSED
#else
# define ioctlsocket ioctl
# define closesocket(s) close(s)
diff --git a/softmmu_header.h b/softmmu_header.h
index 6b72093a0c..cf1aa38fc7 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -99,7 +99,6 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
int page_index;
RES_TYPE res;
target_ulong addr;
- unsigned long physaddr;
int mmu_idx;
addr = ptr;
@@ -111,8 +110,8 @@ glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
addr,
mmu_idx);
} else {
- physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
- res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
+ uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+ res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
}
return res;
}
@@ -124,7 +123,6 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
{
int res, page_index;
target_ulong addr;
- unsigned long physaddr;
int mmu_idx;
addr = ptr;
@@ -135,8 +133,8 @@ glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
MMUSUFFIX)(ENV_VAR addr, mmu_idx);
} else {
- physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
- res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
+ uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+ res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
}
return res;
}
@@ -152,7 +150,6 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
{
int page_index;
target_ulong addr;
- unsigned long physaddr;
int mmu_idx;
addr = ptr;
@@ -163,8 +160,8 @@ glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
mmu_idx);
} else {
- physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
- glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
+ uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
+ glue(glue(st, SUFFIX), _raw)(hostaddr, v);
}
}
diff --git a/softmmu_template.h b/softmmu_template.h
index afcab1e6a9..b8bd700325 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -69,17 +69,17 @@
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
target_ulong addr,
int mmu_idx,
- void *retaddr);
+ uintptr_t retaddr);
static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM
target_phys_addr_t physaddr,
target_ulong addr,
- void *retaddr)
+ uintptr_t retaddr)
{
DATA_TYPE res;
MemoryRegion *mr = iotlb_to_region(physaddr);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
- env->mem_io_pc = (unsigned long)retaddr;
+ env->mem_io_pc = retaddr;
if (mr != &io_mem_ram && mr != &io_mem_rom
&& mr != &io_mem_unassigned
&& mr != &io_mem_notdirty
@@ -112,8 +112,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
int index;
target_ulong tlb_addr;
target_phys_addr_t ioaddr;
- unsigned long addend;
- void *retaddr;
+ uintptr_t retaddr;
/* test if there is match for unaligned or IO access */
/* XXX: could done more in memory macro in a non portable way */
@@ -139,6 +138,7 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
mmu_idx, retaddr);
} else {
/* unaligned/aligned access in the same page */
+ uintptr_t addend;
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
retaddr = GETPC();
@@ -146,7 +146,8 @@ glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
}
#endif
addend = env->tlb_table[mmu_idx][index].addend;
- res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
+ res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t)
+ (addr + addend));
}
} else {
/* the page is not in the TLB : fill it */
@@ -166,12 +167,11 @@ static DATA_TYPE
glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
target_ulong addr,
int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
DATA_TYPE res, res1, res2;
int index, shift;
target_phys_addr_t ioaddr;
- unsigned long addend;
target_ulong tlb_addr, addr1, addr2;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
@@ -202,8 +202,9 @@ glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
res = (DATA_TYPE)res;
} else {
/* unaligned/aligned access in the same page */
- addend = env->tlb_table[mmu_idx][index].addend;
- res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(long)(addr+addend));
+ uintptr_t addend = env->tlb_table[mmu_idx][index].addend;
+ res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t)
+ (addr + addend));
}
} else {
/* the page is not in the TLB : fill it */
@@ -219,13 +220,13 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
target_ulong addr,
DATA_TYPE val,
int mmu_idx,
- void *retaddr);
+ uintptr_t retaddr);
static inline void glue(io_write, SUFFIX)(ENV_PARAM
target_phys_addr_t physaddr,
DATA_TYPE val,
target_ulong addr,
- void *retaddr)
+ uintptr_t retaddr)
{
MemoryRegion *mr = iotlb_to_region(physaddr);
@@ -238,7 +239,7 @@ static inline void glue(io_write, SUFFIX)(ENV_PARAM
}
env->mem_io_vaddr = addr;
- env->mem_io_pc = (unsigned long)retaddr;
+ env->mem_io_pc = retaddr;
#if SHIFT <= 2
io_mem_write(mr, physaddr, val, 1 << SHIFT);
#else
@@ -258,9 +259,8 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
int mmu_idx)
{
target_phys_addr_t ioaddr;
- unsigned long addend;
target_ulong tlb_addr;
- void *retaddr;
+ uintptr_t retaddr;
int index;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
@@ -284,6 +284,7 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
mmu_idx, retaddr);
} else {
/* aligned/unaligned access in the same page */
+ uintptr_t addend;
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
retaddr = GETPC();
@@ -291,7 +292,8 @@ void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
}
#endif
addend = env->tlb_table[mmu_idx][index].addend;
- glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
+ glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t)
+ (addr + addend), val);
}
} else {
/* the page is not in the TLB : fill it */
@@ -310,10 +312,9 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
target_ulong addr,
DATA_TYPE val,
int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
target_phys_addr_t ioaddr;
- unsigned long addend;
target_ulong tlb_addr;
int index, i;
@@ -345,8 +346,9 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
}
} else {
/* aligned/unaligned access in the same page */
- addend = env->tlb_table[mmu_idx][index].addend;
- glue(glue(st, SUFFIX), _raw)((uint8_t *)(long)(addr+addend), val);
+ uintptr_t addend = env->tlb_table[mmu_idx][index].addend;
+ glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t)
+ (addr + addend), val);
}
} else {
/* the page is not in the TLB : fill it */
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
new file mode 100644
index 0000000000..6b4ca6d1d1
--- /dev/null
+++ b/target-alpha/cpu-qom.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU Alpha 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_ALPHA_CPU_QOM_H
+#define QEMU_ALPHA_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_ALPHA_CPU "alpha-cpu"
+
+#define ALPHA_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(AlphaCPUClass, (klass), TYPE_ALPHA_CPU)
+#define ALPHA_CPU(obj) \
+ OBJECT_CHECK(AlphaCPU, (obj), TYPE_ALPHA_CPU)
+#define ALPHA_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(AlphaCPUClass, (obj), TYPE_ALPHA_CPU)
+
+/**
+ * AlphaCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An Alpha CPU model.
+ */
+typedef struct AlphaCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} AlphaCPUClass;
+
+/**
+ * AlphaCPU:
+ * @env: #CPUAlphaState
+ *
+ * An Alpha CPU.
+ */
+typedef struct AlphaCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUAlphaState env;
+} AlphaCPU;
+
+static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
+{
+ return ALPHA_CPU(container_of(env, AlphaCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
+
+
+#endif
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
new file mode 100644
index 0000000000..62d2a669a9
--- /dev/null
+++ b/target-alpha/cpu.c
@@ -0,0 +1,58 @@
+/*
+ * QEMU Alpha CPU
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ * 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"
+
+
+static void alpha_cpu_initfn(Object *obj)
+{
+ AlphaCPU *cpu = ALPHA_CPU(obj);
+ CPUAlphaState *env = &cpu->env;
+
+ cpu_exec_init(env);
+ tlb_flush(env, 1);
+
+#if defined(CONFIG_USER_ONLY)
+ env->ps = PS_USER_MODE;
+ cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
+ | FPCR_UNFD | FPCR_INED | FPCR_DNOD
+ | FPCR_DYN_NORMAL));
+#endif
+ env->lock_addr = -1;
+ env->fen = 1;
+}
+
+static const TypeInfo alpha_cpu_type_info = {
+ .name = TYPE_ALPHA_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(AlphaCPU),
+ .instance_init = alpha_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(AlphaCPUClass),
+};
+
+static void alpha_cpu_register_types(void)
+{
+ type_register_static(&alpha_cpu_type_info);
+}
+
+type_init(alpha_cpu_register_types)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 74bf7f7ff4..99f9ee168d 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -292,6 +292,7 @@ struct CPUAlphaState {
#define cpu_signal_handler cpu_alpha_signal_handler
#include "cpu-all.h"
+#include "cpu-qom.h"
enum {
FEATURE_ASN = 0x00000001,
@@ -433,9 +434,9 @@ int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
int mmu_idx);
#define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
void do_interrupt (CPUAlphaState *env);
-void do_restore_state(CPUAlphaState *, void *retaddr);
-void QEMU_NORETURN dynamic_excp(CPUAlphaState *, void *, int, int);
-void QEMU_NORETURN arith_excp(CPUAlphaState *, void *, int, uint64_t);
+void do_restore_state(CPUAlphaState *, uintptr_t retaddr);
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
+void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index dda110352e..fe988ec459 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -44,7 +44,7 @@ uint32_t helper_fp_exc_get(CPUAlphaState *env)
return get_float_exception_flags(&FP_STATUS);
}
-static inline void inline_fp_exc_raise(CPUAlphaState *env, void *retaddr,
+static inline void inline_fp_exc_raise(CPUAlphaState *env, uintptr_t retaddr,
uint32_t exc, uint32_t regno)
{
if (exc) {
@@ -160,7 +160,7 @@ static uint64_t float32_to_f(float32 fa)
return r;
}
-static float32 f_to_float32(CPUAlphaState *env, void *retaddr, uint64_t a)
+static float32 f_to_float32(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
{
uint32_t exp, mant_sig;
CPU_FloatU r;
@@ -291,7 +291,7 @@ static uint64_t float64_to_g(float64 fa)
return r;
}
-static float64 g_to_float64(CPUAlphaState *env, void *retaddr, uint64_t a)
+static float64 g_to_float64(CPUAlphaState *env, uintptr_t retaddr, uint64_t a)
{
uint64_t exp, mant_sig;
CPU_DoubleU r;
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 765e650002..81d4763b49 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -494,13 +494,12 @@ void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n");
}
-void do_restore_state(CPUAlphaState *env, void *retaddr)
+void do_restore_state(CPUAlphaState *env, uintptr_t retaddr)
{
- uintptr_t pc = (uintptr_t)retaddr;
- if (pc) {
- TranslationBlock *tb = tb_find_pc(pc);
+ if (retaddr) {
+ TranslationBlock *tb = tb_find_pc(retaddr);
if (tb) {
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
}
@@ -515,7 +514,7 @@ void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error)
}
/* This may be called from any of the helpers to set up EXCEPTION_INDEX. */
-void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, void *retaddr,
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr,
int excp, int error)
{
env->exception_index = excp;
@@ -524,7 +523,7 @@ void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, void *retaddr,
cpu_loop_exit(env);
}
-void QEMU_NORETURN arith_excp(CPUAlphaState *env, void *retaddr,
+void QEMU_NORETURN arith_excp(CPUAlphaState *env, uintptr_t retaddr,
int exc, uint64_t mask)
{
env->trap_arg0 = exc;
diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
index dd5ca4933a..87cada48f9 100644
--- a/target-alpha/mem_helper.c
+++ b/target-alpha/mem_helper.c
@@ -89,7 +89,7 @@ uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
}
static void do_unaligned_access(CPUAlphaState *env, target_ulong addr,
- int is_write, int is_user, void *retaddr)
+ int is_write, int is_user, uintptr_t retaddr)
{
uint64_t pc;
uint32_t insn;
@@ -112,7 +112,7 @@ void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr,
{
env->trap_arg0 = addr;
env->trap_arg1 = is_write;
- dynamic_excp(env, NULL, EXCP_MCHK, 0);
+ dynamic_excp(env, 0, EXCP_MCHK, 0);
}
#include "softmmu_exec.h"
@@ -137,7 +137,7 @@ void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr,
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUAlphaState *env, target_ulong addr, int is_write,
- int mmu_idx, void *retaddr)
+ int mmu_idx, uintptr_t retaddr)
{
int ret;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1f4565d794..12de6a3fb6 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3525,13 +3525,14 @@ static const struct cpu_def_t cpu_defs[] = {
CPUAlphaState * cpu_alpha_init (const char *cpu_model)
{
+ AlphaCPU *cpu;
CPUAlphaState *env;
int implver, amask, i, max;
- env = g_malloc0(sizeof(CPUAlphaState));
- cpu_exec_init(env);
+ cpu = ALPHA_CPU(object_new(TYPE_ALPHA_CPU));
+ env = &cpu->env;
+
alpha_translate_init();
- tlb_flush(env, 1);
/* Default to ev67; no reason not to emulate insns by default. */
implver = IMPLVER_21264;
@@ -3549,15 +3550,6 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
env->implver = implver;
env->amask = amask;
-#if defined (CONFIG_USER_ONLY)
- env->ps = PS_USER_MODE;
- cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
- | FPCR_UNFD | FPCR_INED | FPCR_DNOD
- | FPCR_DYN_NORMAL));
-#endif
- env->lock_addr = -1;
- env->fen = 1;
-
qemu_init_vcpu(env);
return env;
}
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index c728432654..b53369d7cb 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -76,11 +76,10 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPUARMState *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
@@ -89,12 +88,11 @@ void tlb_fill(CPUARMState *env1, target_ulong addr, int is_write, int mmu_idx,
if (unlikely(ret)) {
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
raise_exception(env->exception_index);
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index c568e2b930..b92c106e10 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -57,28 +57,26 @@
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUCRISState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPUCRISState *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
env = env1;
- D_LOG("%s pc=%x tpc=%x ra=%x\n", __func__,
- env->pc, env->debug1, retaddr);
+ D_LOG("%s pc=%x tpc=%x ra=%p\n", __func__,
+ env->pc, env->debug1, (void *)retaddr);
ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret)) {
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
/* Evaluate flags after retranslation. */
helper_top_evaluate_flags();
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
new file mode 100644
index 0000000000..40635c4b1c
--- /dev/null
+++ b/target-i386/cpu-qom.h
@@ -0,0 +1,75 @@
+/*
+ * QEMU x86 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_I386_CPU_QOM_H
+#define QEMU_I386_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#ifdef TARGET_X86_64
+#define TYPE_X86_CPU "x86_64-cpu"
+#else
+#define TYPE_X86_CPU "i386-cpu"
+#endif
+
+#define X86_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(X86CPUClass, (klass), TYPE_X86_CPU)
+#define X86_CPU(obj) \
+ OBJECT_CHECK(X86CPU, (obj), TYPE_X86_CPU)
+#define X86_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(X86CPUClass, (obj), TYPE_X86_CPU)
+
+/**
+ * X86CPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An x86 CPU model or family.
+ */
+typedef struct X86CPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} X86CPUClass;
+
+/**
+ * X86CPU:
+ * @env: #CPUX86State
+ *
+ * An x86 CPU.
+ */
+typedef struct X86CPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUX86State env;
+} X86CPU;
+
+static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
+{
+ return X86_CPU(container_of(env, X86CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e))
+
+
+#endif
diff --git a/target-i386/cpuid.c b/target-i386/cpu.c
index 465ea15f45..3df53ca74b 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpu.c
@@ -1367,3 +1367,137 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
break;
}
}
+
+/* CPUClass::reset() */
+static void x86_cpu_reset(CPUState *s)
+{
+ X86CPU *cpu = X86_CPU(s);
+ X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
+ CPUX86State *env = &cpu->env;
+ int i;
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
+ }
+
+ xcc->parent_reset(s);
+
+
+ memset(env, 0, offsetof(CPUX86State, breakpoints));
+
+ tlb_flush(env, 1);
+
+ env->old_exception = -1;
+
+ /* init to reset state */
+
+#ifdef CONFIG_SOFTMMU
+ env->hflags |= HF_SOFTMMU_MASK;
+#endif
+ env->hflags2 |= HF2_GIF_MASK;
+
+ cpu_x86_update_cr0(env, 0x60000010);
+ env->a20_mask = ~0x0;
+ env->smbase = 0x30000;
+
+ env->idt.limit = 0xffff;
+ env->gdt.limit = 0xffff;
+ env->ldt.limit = 0xffff;
+ env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
+ env->tr.limit = 0xffff;
+ env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
+
+ cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
+ DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
+ DESC_R_MASK | DESC_A_MASK);
+ cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
+ DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+ DESC_A_MASK);
+ cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
+ DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+ DESC_A_MASK);
+ cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
+ DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+ DESC_A_MASK);
+ cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
+ DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+ DESC_A_MASK);
+ cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
+ DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
+ DESC_A_MASK);
+
+ env->eip = 0xfff0;
+ env->regs[R_EDX] = env->cpuid_version;
+
+ env->eflags = 0x2;
+
+ /* FPU init */
+ for (i = 0; i < 8; i++) {
+ env->fptags[i] = 1;
+ }
+ env->fpuc = 0x37f;
+
+ env->mxcsr = 0x1f80;
+
+ env->pat = 0x0007040600070406ULL;
+ env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
+
+ memset(env->dr, 0, sizeof(env->dr));
+ env->dr[6] = DR6_FIXED_1;
+ env->dr[7] = DR7_FIXED_1;
+ cpu_breakpoint_remove_all(env, BP_CPU);
+ cpu_watchpoint_remove_all(env, BP_CPU);
+}
+
+static void mce_init(X86CPU *cpu)
+{
+ CPUX86State *cenv = &cpu->env;
+ unsigned int bank;
+
+ if (((cenv->cpuid_version >> 8) & 0xf) >= 6
+ && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
+ (CPUID_MCE | CPUID_MCA)) {
+ cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
+ cenv->mcg_ctl = ~(uint64_t)0;
+ for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
+ cenv->mce_banks[bank * 4] = ~(uint64_t)0;
+ }
+ }
+}
+
+static void x86_cpu_initfn(Object *obj)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+
+ cpu_exec_init(env);
+ env->cpuid_apic_id = env->cpu_index;
+ mce_init(cpu);
+}
+
+static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
+{
+ X86CPUClass *xcc = X86_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+
+ xcc->parent_reset = cc->reset;
+ cc->reset = x86_cpu_reset;
+}
+
+static const TypeInfo x86_cpu_type_info = {
+ .name = TYPE_X86_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(X86CPU),
+ .instance_init = x86_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(X86CPUClass),
+ .class_init = x86_cpu_common_class_init,
+};
+
+static void x86_cpu_register_types(void)
+{
+ type_register_static(&x86_cpu_type_info);
+}
+
+type_init(x86_cpu_register_types)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a1ed3e72ea..4bb4592db5 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -783,9 +783,10 @@ typedef struct CPUX86State {
TPRAccess tpr_access_type;
} CPUX86State;
+#include "cpu-qom.h"
+
CPUX86State *cpu_x86_init(const char *cpu_model);
int cpu_x86_exec(CPUX86State *s);
-void cpu_x86_close(CPUX86State *s);
void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg);
void x86_cpudef_setup(void);
int cpu_x86_support_mca_broadcast(CPUX86State *env);
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 83122bf617..87954f0919 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -29,81 +29,7 @@
/* NOTE: must be called outside the CPU execute loop */
void cpu_state_reset(CPUX86State *env)
{
- int i;
-
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
- }
-
- memset(env, 0, offsetof(CPUX86State, breakpoints));
-
- tlb_flush(env, 1);
-
- env->old_exception = -1;
-
- /* init to reset state */
-
-#ifdef CONFIG_SOFTMMU
- env->hflags |= HF_SOFTMMU_MASK;
-#endif
- env->hflags2 |= HF2_GIF_MASK;
-
- cpu_x86_update_cr0(env, 0x60000010);
- env->a20_mask = ~0x0;
- env->smbase = 0x30000;
-
- env->idt.limit = 0xffff;
- env->gdt.limit = 0xffff;
- env->ldt.limit = 0xffff;
- env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
- env->tr.limit = 0xffff;
- env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
-
- cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
- DESC_R_MASK | DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
- cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
- DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
- DESC_A_MASK);
-
- env->eip = 0xfff0;
- env->regs[R_EDX] = env->cpuid_version;
-
- env->eflags = 0x2;
-
- /* FPU init */
- for(i = 0;i < 8; i++)
- env->fptags[i] = 1;
- env->fpuc = 0x37f;
-
- env->mxcsr = 0x1f80;
-
- env->pat = 0x0007040600070406ULL;
- env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
-
- memset(env->dr, 0, sizeof(env->dr));
- env->dr[6] = DR6_FIXED_1;
- env->dr[7] = DR7_FIXED_1;
- cpu_breakpoint_remove_all(env, BP_CPU);
- cpu_watchpoint_remove_all(env, BP_CPU);
-}
-
-void cpu_x86_close(CPUX86State *env)
-{
- g_free(env);
+ cpu_reset(ENV_GET_CPU(env));
}
static void cpu_x86_version(CPUX86State *env, int *family, int *model)
@@ -1202,21 +1128,6 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
}
#endif /* !CONFIG_USER_ONLY */
-static void mce_init(CPUX86State *cenv)
-{
- unsigned int bank;
-
- if (((cenv->cpuid_version >> 8) & 0xf) >= 6
- && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
- (CPUID_MCE | CPUID_MCA)) {
- cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
- cenv->mcg_ctl = ~(uint64_t)0;
- for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
- cenv->mce_banks[bank * 4] = ~(uint64_t)0;
- }
- }
-}
-
int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
target_ulong *base, unsigned int *limit,
unsigned int *flags)
@@ -1248,11 +1159,12 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
CPUX86State *cpu_x86_init(const char *cpu_model)
{
+ X86CPU *cpu;
CPUX86State *env;
static int inited;
- env = g_malloc0(sizeof(CPUX86State));
- cpu_exec_init(env);
+ cpu = X86_CPU(object_new(TYPE_X86_CPU));
+ env = &cpu->env;
env->cpu_model_str = cpu_model;
/* init various static tables used in TCG mode */
@@ -1265,11 +1177,9 @@ CPUX86State *cpu_x86_init(const char *cpu_model)
#endif
}
if (cpu_x86_register(env, cpu_model) < 0) {
- cpu_x86_close(env);
+ object_delete(OBJECT(cpu));
return NULL;
}
- env->cpuid_apic_id = env->cpu_index;
- mce_init(env);
qemu_init_vcpu(env);
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index c04ae4464f..bc3b94e149 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -5003,11 +5003,10 @@ void helper_boundl(target_ulong a0, int v)
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
int ret;
- unsigned long pc;
CPUX86State *saved_env;
saved_env = env;
@@ -5017,12 +5016,11 @@ void tlb_fill(CPUX86State *env1, target_ulong addr, int is_write, int mmu_idx,
if (ret) {
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
new file mode 100644
index 0000000000..4ae2eddafb
--- /dev/null
+++ b/target-lm32/cpu-qom.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU LatticeMico32 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_LM32_CPU_QOM_H
+#define QEMU_LM32_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_LM32_CPU "lm32-cpu"
+
+#define LM32_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(LM32CPUClass, (klass), TYPE_LM32_CPU)
+#define LM32_CPU(obj) \
+ OBJECT_CHECK(LM32CPU, (obj), TYPE_LM32_CPU)
+#define LM32_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(LM32CPUClass, (obj), TYPE_LM32_CPU)
+
+/**
+ * LM32CPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A LatticeMico32 CPU model.
+ */
+typedef struct LM32CPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} LM32CPUClass;
+
+/**
+ * LM32CPU:
+ * @env: #CPULM32State
+ *
+ * A LatticeMico32 CPU.
+ */
+typedef struct LM32CPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPULM32State env;
+} LM32CPU;
+
+static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
+{
+ return LM32_CPU(container_of(env, LM32CPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(lm32_env_get_cpu(e))
+
+
+#endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
new file mode 100644
index 0000000000..48a5fe3f86
--- /dev/null
+++ b/target-lm32/cpu.c
@@ -0,0 +1,81 @@
+/*
+ * QEMU LatticeMico32 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>
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+
+
+/* CPUClass::reset() */
+static void lm32_cpu_reset(CPUState *s)
+{
+ LM32CPU *cpu = LM32_CPU(s);
+ LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu);
+ CPULM32State *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);
+ }
+
+ lcc->parent_reset(s);
+
+ tlb_flush(env, 1);
+
+ /* reset cpu state */
+ memset(env, 0, offsetof(CPULM32State, breakpoints));
+}
+
+static void lm32_cpu_initfn(Object *obj)
+{
+ LM32CPU *cpu = LM32_CPU(obj);
+ CPULM32State *env = &cpu->env;
+
+ cpu_exec_init(env);
+
+ env->flags = 0;
+
+ cpu_reset(CPU(cpu));
+}
+
+static void lm32_cpu_class_init(ObjectClass *oc, void *data)
+{
+ LM32CPUClass *lcc = LM32_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+
+ lcc->parent_reset = cc->reset;
+ cc->reset = lm32_cpu_reset;
+}
+
+static const TypeInfo lm32_cpu_type_info = {
+ .name = TYPE_LM32_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(LM32CPU),
+ .instance_init = lm32_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(LM32CPUClass),
+ .class_init = lm32_cpu_class_init,
+};
+
+static void lm32_cpu_register_types(void)
+{
+ type_register_static(&lm32_cpu_type_info);
+}
+
+type_init(lm32_cpu_register_types)
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index a7d95464b8..422a55b063 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -184,6 +184,7 @@ struct CPULM32State {
};
+#include "cpu-qom.h"
CPULM32State *cpu_lm32_init(const char *cpu_model);
void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 78076e4603..d0bc1931d8 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -194,6 +194,7 @@ static uint32_t cfg_by_def(const LM32Def *def)
CPULM32State *cpu_lm32_init(const char *cpu_model)
{
+ LM32CPU *cpu;
CPULM32State *env;
const LM32Def *def;
static int tcg_initialized;
@@ -203,16 +204,14 @@ CPULM32State *cpu_lm32_init(const char *cpu_model)
return NULL;
}
- env = g_malloc0(sizeof(CPULM32State));
+ cpu = LM32_CPU(object_new(TYPE_LM32_CPU));
+ env = &cpu->env;
env->features = def->features;
env->num_bps = def->num_breakpoints;
env->num_wps = def->num_watchpoints;
env->cfg = cfg_by_def(def);
- env->flags = 0;
- cpu_exec_init(env);
- cpu_state_reset(env);
qemu_init_vcpu(env);
if (tcg_enabled() && !tcg_initialized) {
@@ -237,14 +236,6 @@ void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value)
void cpu_state_reset(CPULM32State *env)
{
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- tlb_flush(env, 1);
-
- /* reset cpu state */
- memset(env, 0, offsetof(CPULM32State, breakpoints));
+ cpu_reset(ENV_GET_CPU(env));
}
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index e9c96383af..51edc1a0e1 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -76,11 +76,10 @@ uint32_t helper_rcsr_jrx(void)
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPULM32State *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
@@ -90,12 +89,11 @@ void tlb_fill(CPULM32State *env1, target_ulong addr, int is_write, int mmu_idx,
if (unlikely(ret)) {
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
cpu_loop_exit(env);
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index bc8c1f02c6..1971a57892 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -56,11 +56,10 @@ extern int semihosting_enabled;
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPUM68KState *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
@@ -69,12 +68,11 @@ void tlb_fill(CPUM68KState *env1, target_ulong addr, int is_write, int mmu_idx,
if (unlikely(ret)) {
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
cpu_loop_exit(env);
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 6e0e411c94..2412a583f1 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -2,6 +2,7 @@
* MicroBlaze helper routines.
*
* Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>
+ * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/target-microblaze/mmu.c b/target-microblaze/mmu.c
index 43092e580d..53ad263a05 100644
--- a/target-microblaze/mmu.c
+++ b/target-microblaze/mmu.c
@@ -2,6 +2,7 @@
* Microblaze MMU emulation for qemu.
*
* Copyright (c) 2009 Edgar E. Iglesias
+ * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 76cc0e098b..3b1f07243e 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -2,6 +2,7 @@
* Microblaze helper routines.
*
* Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
+ * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -43,11 +44,10 @@
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPUMBState *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
@@ -57,12 +57,11 @@ void tlb_fill(CPUMBState *env1, target_ulong addr, int is_write, int mmu_idx,
if (unlikely(ret)) {
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
cpu_loop_exit(env);
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 64cbfb815e..b602820bb4 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -2,6 +2,7 @@
* Xilinx MicroBlaze emulation for qemu: main translation routines.
*
* Copyright (c) 2009 Edgar E. Iglesias.
+ * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index ce01225e6c..5627447953 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -101,11 +101,10 @@ void helper_raise_exception (uint32_t exception)
}
#if !defined(CONFIG_USER_ONLY)
-static void do_restore_state (void *pc_ptr)
+static void do_restore_state(uintptr_t pc)
{
TranslationBlock *tb;
- unsigned long pc = (unsigned long) pc_ptr;
-
+
tb = tb_find_pc (pc);
if (tb) {
cpu_restore_state(tb, env, pc);
@@ -2276,7 +2275,7 @@ void helper_pmon (int function)
break;
case 158:
{
- unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
+ unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4];
printf("%s", fmt);
}
break;
@@ -2293,7 +2292,7 @@ void helper_wait (void)
#if !defined(CONFIG_USER_ONLY)
static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
- int is_user, void *retaddr);
+ int is_user, uintptr_t retaddr);
#define MMUSUFFIX _mmu
#define ALIGNED_ONLY
@@ -2310,7 +2309,8 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
#define SHIFT 3
#include "softmmu_template.h"
-static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
+static void do_unaligned_access(target_ulong addr, int is_write,
+ int is_user, uintptr_t retaddr)
{
env->CP0_BadVAddr = addr;
do_restore_state (retaddr);
@@ -2318,11 +2318,10 @@ static void do_unaligned_access (target_ulong addr, int is_write, int is_user, v
}
void tlb_fill(CPUMIPSState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPUMIPSState *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
@@ -2331,12 +2330,11 @@ void tlb_fill(CPUMIPSState *env1, target_ulong addr, int is_write, int mmu_idx,
if (ret) {
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
new file mode 100644
index 0000000000..fef6f95a04
--- /dev/null
+++ b/target-ppc/cpu-qom.h
@@ -0,0 +1,77 @@
+/*
+ * QEMU PowerPC 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_PPC_CPU_QOM_H
+#define QEMU_PPC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#ifdef TARGET_PPC64
+#define TYPE_POWERPC_CPU "powerpc64-cpu"
+#elif defined(TARGET_PPCEMB)
+#define TYPE_POWERPC_CPU "embedded-powerpc-cpu"
+#else
+#define TYPE_POWERPC_CPU "powerpc-cpu"
+#endif
+
+#define POWERPC_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(PowerPCCPUClass, (klass), TYPE_POWERPC_CPU)
+#define POWERPC_CPU(obj) \
+ OBJECT_CHECK(PowerPCCPU, (obj), TYPE_POWERPC_CPU)
+#define POWERPC_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(PowerPCCPUClass, (obj), TYPE_POWERPC_CPU)
+
+/**
+ * PowerPCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A PowerPC CPU model.
+ */
+typedef struct PowerPCCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} PowerPCCPUClass;
+
+/**
+ * PowerPCCPU:
+ * @env: #CPUPPCState
+ *
+ * A PowerPC CPU.
+ */
+typedef struct PowerPCCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUPPCState env;
+} PowerPCCPU;
+
+static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
+{
+ return POWERPC_CPU(container_of(env, PowerPCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
+
+
+#endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index e7fb3641a7..84c9674157 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1096,11 +1096,12 @@ struct mmu_ctx_t {
};
#endif
+#include "cpu-qom.h"
+
/*****************************************************************************/
CPUPPCState *cpu_ppc_init (const char *cpu_model);
void ppc_translate_init(void);
int cpu_ppc_exec (CPUPPCState *s);
-void cpu_ppc_close (CPUPPCState *s);
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index e13b74993d..c610ce3e28 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2960,7 +2960,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
if (asrr1 != -1)
env->spr[asrr1] = env->spr[srr1];
/* If we disactivated any translation, flush TLBs */
- if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
+ if (msr & ((1 << MSR_IR) | (1 << MSR_DR)))
tlb_flush(env, 1);
if (msr_ile) {
@@ -3138,54 +3138,12 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr)
void cpu_state_reset(CPUPPCState *env)
{
- target_ulong msr;
-
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- msr = (target_ulong)0;
- if (0) {
- /* XXX: find a suitable condition to enable the hypervisor mode */
- msr |= (target_ulong)MSR_HVB;
- }
- msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
- msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
- msr |= (target_ulong)1 << MSR_EP;
-#if defined (DO_SINGLE_STEP) && 0
- /* Single step trace mode */
- msr |= (target_ulong)1 << MSR_SE;
- msr |= (target_ulong)1 << MSR_BE;
-#endif
-#if defined(CONFIG_USER_ONLY)
- msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
- msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
- msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
- msr |= (target_ulong)1 << MSR_PR;
-#else
- env->excp_prefix = env->hreset_excp_prefix;
- env->nip = env->hreset_vector | env->excp_prefix;
- if (env->mmu_model != POWERPC_MMU_REAL)
- ppc_tlb_invalidate_all(env);
-#endif
- env->msr = msr & env->msr_mask;
-#if defined(TARGET_PPC64)
- if (env->mmu_model & POWERPC_MMU_64)
- env->msr |= (1ULL << MSR_SF);
-#endif
- hreg_compute_hflags(env);
- env->reserve_addr = (target_ulong)-1ULL;
- /* Be sure no exception or interrupt is pending */
- env->pending_interrupts = 0;
- env->exception_index = POWERPC_EXCP_NONE;
- env->error_code = 0;
- /* Flush all TLBs */
- tlb_flush(env, 1);
+ cpu_reset(ENV_GET_CPU(env));
}
CPUPPCState *cpu_ppc_init (const char *cpu_model)
{
+ PowerPCCPU *cpu;
CPUPPCState *env;
const ppc_def_t *def;
@@ -3193,20 +3151,13 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
if (!def)
return NULL;
- env = g_malloc0(sizeof(CPUPPCState));
- cpu_exec_init(env);
+ cpu = POWERPC_CPU(object_new(TYPE_POWERPC_CPU));
+ env = &cpu->env;
+
if (tcg_enabled()) {
ppc_translate_init();
}
- /* Adjust cpu index for SMT */
-#if !defined(CONFIG_USER_ONLY)
- if (kvm_enabled()) {
- int smt = kvmppc_smt_threads();
- env->cpu_index = (env->cpu_index / smp_threads)*smt
- + (env->cpu_index % smp_threads);
- }
-#endif /* !CONFIG_USER_ONLY */
env->cpu_model_str = cpu_model;
cpu_ppc_register_internal(env, def);
@@ -3214,9 +3165,3 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model)
return env;
}
-
-void cpu_ppc_close (CPUPPCState *env)
-{
- /* Should also remove all opcode tables... */
- g_free(env);
-}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index d929213a04..c09cc39c78 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -27,6 +27,7 @@
#include "kvm.h"
#include "kvm_ppc.h"
#include "cpu.h"
+#include "cpus.h"
#include "device_tree.h"
#include "hw/sysbus.h"
#include "hw/spapr.h"
@@ -938,6 +939,19 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
return spec;
}
+int kvmppc_fixup_cpu(CPUPPCState *env)
+{
+ int smt;
+
+ /* Adjust cpu index for SMT */
+ smt = kvmppc_smt_threads();
+ env->cpu_index = (env->cpu_index / smp_threads) * smt
+ + (env->cpu_index % smp_threads);
+
+ return 0;
+}
+
+
bool kvm_arch_stop_on_emulation_error(CPUPPCState *env)
{
return true;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 8f1267c6cc..34ecad3e26 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -29,6 +29,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
#endif /* !CONFIG_USER_ONLY */
const ppc_def_t *kvmppc_host_cpu_def(void);
+int kvmppc_fixup_cpu(CPUPPCState *env);
#else
@@ -95,6 +96,10 @@ static inline const ppc_def_t *kvmppc_host_cpu_def(void)
return NULL;
}
+static inline int kvmppc_fixup_cpu(CPUPPCState *env)
+{
+ return -1;
+}
#endif
#ifndef CONFIG_KVM
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 70e25825fb..d6c2ee41b3 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -32,7 +32,6 @@ void cpu_save(QEMUFile *f, void *opaque)
}
qemu_put_be32s(f, &env->fpscr);
qemu_put_sbe32s(f, &env->access_type);
-#if !defined(CONFIG_USER_ONLY)
#if defined(TARGET_PPC64)
qemu_put_betls(f, &env->asr);
qemu_put_sbe32s(f, &env->slb_nr);
@@ -62,7 +61,6 @@ void cpu_save(QEMUFile *f, void *opaque)
}
for (i = 0; i < 4; i++)
qemu_put_betls(f, &env->pb[i]);
-#endif
for (i = 0; i < 1024; i++)
qemu_put_betls(f, &env->spr[i]);
qemu_put_be32s(f, &env->vscr);
@@ -72,7 +70,6 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_be32s(f, &env->flags);
qemu_put_sbe32s(f, &env->error_code);
qemu_put_be32s(f, &env->pending_interrupts);
-#if !defined(CONFIG_USER_ONLY)
qemu_put_be32s(f, &env->irq_input_state);
for (i = 0; i < POWERPC_EXCP_NB; i++)
qemu_put_betls(f, &env->excp_vectors[i]);
@@ -81,7 +78,6 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_betls(f, &env->ivor_mask);
qemu_put_betls(f, &env->ivpr_mask);
qemu_put_betls(f, &env->hreset_vector);
-#endif
qemu_put_betls(f, &env->nip);
qemu_put_betls(f, &env->hflags);
qemu_put_betls(f, &env->hflags_nmsr);
@@ -120,7 +116,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
}
qemu_get_be32s(f, &env->fpscr);
qemu_get_sbe32s(f, &env->access_type);
-#if !defined(CONFIG_USER_ONLY)
#if defined(TARGET_PPC64)
qemu_get_betls(f, &env->asr);
qemu_get_sbe32s(f, &env->slb_nr);
@@ -150,7 +145,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
}
for (i = 0; i < 4; i++)
qemu_get_betls(f, &env->pb[i]);
-#endif
for (i = 0; i < 1024; i++)
qemu_get_betls(f, &env->spr[i]);
ppc_store_sdr1(env, sdr1);
@@ -161,7 +155,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be32s(f, &env->flags);
qemu_get_sbe32s(f, &env->error_code);
qemu_get_be32s(f, &env->pending_interrupts);
-#if !defined(CONFIG_USER_ONLY)
qemu_get_be32s(f, &env->irq_input_state);
for (i = 0; i < POWERPC_EXCP_NB; i++)
qemu_get_betls(f, &env->excp_vectors[i]);
@@ -170,7 +163,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_betls(f, &env->ivor_mask);
qemu_get_betls(f, &env->ivpr_mask);
qemu_get_betls(f, &env->hreset_vector);
-#endif
qemu_get_betls(f, &env->nip);
qemu_get_betls(f, &env->hflags);
qemu_get_betls(f, &env->hflags_nmsr);
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 40927b65b1..4ef2332a5a 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3715,11 +3715,10 @@ uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPUPPCState *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
@@ -3728,12 +3727,11 @@ void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
if (unlikely(ret != 0)) {
if (likely(retaddr)) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index c9a503a1db..cf59765405 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9306,8 +9306,8 @@ GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
};
-#include "translate_init.c"
#include "helper_regs.h"
+#include "translate_init.c"
/*****************************************************************************/
/* Misc PowerPC helpers */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index b1f87854a0..ba4b84d86b 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -4462,7 +4462,10 @@ static void init_proc_e500 (CPUPPCState *env, int version)
&spr_read_spefscr, &spr_write_spefscr,
0x00000000);
/* Memory management */
-#if !defined(CONFIG_USER_ONLY)
+#if defined(CONFIG_USER_ONLY)
+ env->dcache_line_size = 32;
+ env->icache_line_size = 32;
+#else /* !defined(CONFIG_USER_ONLY) */
env->nb_pids = 3;
env->nb_ways = 2;
env->id_tlbs = 0;
@@ -9504,12 +9507,12 @@ enum {
static inline int is_indirect_opcode (void *handler)
{
- return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
+ return ((uintptr_t)handler & 0x03) == PPC_INDIRECT;
}
static inline opc_handler_t **ind_table(void *handler)
{
- return (opc_handler_t **)((unsigned long)handler & ~3);
+ return (opc_handler_t **)((uintptr_t)handler & ~3);
}
/* Instruction table creation */
@@ -9528,7 +9531,7 @@ static int create_new_table (opc_handler_t **table, unsigned char idx)
tmp = malloc(0x20 * sizeof(opc_handler_t));
fill_new_table(tmp, 0x20);
- table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
+ table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
return 0;
}
@@ -9889,6 +9892,28 @@ static int gdb_set_spe_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
return 0;
}
+static int ppc_fixup_cpu(CPUPPCState *env)
+{
+ /* TCG doesn't (yet) emulate some groups of instructions that
+ * are implemented on some otherwise supported CPUs (e.g. VSX
+ * and decimal floating point instructions on POWER7). We
+ * remove unsupported instruction groups from the cpu state's
+ * instruction masks and hope the guest can cope. For at
+ * least the pseries machine, the unavailability of these
+ * instructions can be advertised to the guest via the device
+ * tree. */
+ if ((env->insns_flags & ~PPC_TCG_INSNS)
+ || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
+ fprintf(stderr, "Warning: Disabling some instructions which are not "
+ "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")\n",
+ env->insns_flags & ~PPC_TCG_INSNS,
+ env->insns_flags2 & ~PPC_TCG_INSNS2);
+ }
+ env->insns_flags &= PPC_TCG_INSNS;
+ env->insns_flags2 &= PPC_TCG_INSNS2;
+ return 0;
+}
+
int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
{
env->msr_mask = def->msr_mask;
@@ -9897,25 +9922,22 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
env->bus_model = def->bus_model;
env->insns_flags = def->insns_flags;
env->insns_flags2 = def->insns_flags2;
- if (!kvm_enabled()) {
- /* TCG doesn't (yet) emulate some groups of instructions that
- * are implemented on some otherwise supported CPUs (e.g. VSX
- * and decimal floating point instructions on POWER7). We
- * remove unsupported instruction groups from the cpu state's
- * instruction masks and hope the guest can cope. For at
- * least the pseries machine, the unavailability of these
- * instructions can be advertise to the guest via the device
- * tree.
- *
- * FIXME: we should have a similar masking for CPU features
- * not accessible under KVM, but so far, there aren't any of
- * those. */
- env->insns_flags &= PPC_TCG_INSNS;
- env->insns_flags2 &= PPC_TCG_INSNS2;
- }
env->flags = def->flags;
env->bfd_mach = def->bfd_mach;
env->check_pow = def->check_pow;
+
+ if (kvm_enabled()) {
+ if (kvmppc_fixup_cpu(env) != 0) {
+ fprintf(stderr, "Unable to virtualize selected CPU with KVM\n");
+ exit(1);
+ }
+ } else {
+ if (ppc_fixup_cpu(env) != 0) {
+ fprintf(stderr, "Unable to emulate selected CPU with TCG\n");
+ exit(1);
+ }
+ }
+
if (create_ppc_opcodes(env, def) < 0)
return -1;
init_ppc_proc(env, def);
@@ -10185,3 +10207,93 @@ void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf)
ppc_defs[i].name, ppc_defs[i].pvr);
}
}
+
+/* CPUClass::reset() */
+static void ppc_cpu_reset(CPUState *s)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(s);
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ target_ulong msr;
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
+ pcc->parent_reset(s);
+
+ msr = (target_ulong)0;
+ if (0) {
+ /* XXX: find a suitable condition to enable the hypervisor mode */
+ msr |= (target_ulong)MSR_HVB;
+ }
+ msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
+ msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
+ msr |= (target_ulong)1 << MSR_EP;
+#if defined(DO_SINGLE_STEP) && 0
+ /* Single step trace mode */
+ msr |= (target_ulong)1 << MSR_SE;
+ msr |= (target_ulong)1 << MSR_BE;
+#endif
+#if defined(CONFIG_USER_ONLY)
+ msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
+ msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
+ msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
+ msr |= (target_ulong)1 << MSR_PR;
+#else
+ env->excp_prefix = env->hreset_excp_prefix;
+ env->nip = env->hreset_vector | env->excp_prefix;
+ if (env->mmu_model != POWERPC_MMU_REAL) {
+ ppc_tlb_invalidate_all(env);
+ }
+#endif
+ env->msr = msr & env->msr_mask;
+#if defined(TARGET_PPC64)
+ if (env->mmu_model & POWERPC_MMU_64) {
+ env->msr |= (1ULL << MSR_SF);
+ }
+#endif
+ hreg_compute_hflags(env);
+ env->reserve_addr = (target_ulong)-1ULL;
+ /* Be sure no exception or interrupt is pending */
+ env->pending_interrupts = 0;
+ env->exception_index = POWERPC_EXCP_NONE;
+ env->error_code = 0;
+ /* Flush all TLBs */
+ tlb_flush(env, 1);
+}
+
+static void ppc_cpu_initfn(Object *obj)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(obj);
+ CPUPPCState *env = &cpu->env;
+
+ cpu_exec_init(env);
+}
+
+static void ppc_cpu_class_init(ObjectClass *oc, void *data)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+
+ pcc->parent_reset = cc->reset;
+ cc->reset = ppc_cpu_reset;
+}
+
+static const TypeInfo ppc_cpu_type_info = {
+ .name = TYPE_POWERPC_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(PowerPCCPU),
+ .instance_init = ppc_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(PowerPCCPUClass),
+ .class_init = ppc_cpu_class_init,
+};
+
+static void ppc_cpu_register_types(void)
+{
+ type_register_static(&ppc_cpu_type_info);
+}
+
+type_init(ppc_cpu_register_types)
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 18fdbb2e8e..7b7247316e 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -57,11 +57,10 @@
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
TranslationBlock *tb;
CPUS390XState *saved_env;
- unsigned long pc;
int ret;
saved_env = env;
@@ -70,12 +69,11 @@ void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
if (unlikely(ret != 0)) {
if (likely(retaddr)) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
cpu_loop_exit(env);
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 30f762f514..40547911cd 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -22,18 +22,16 @@
#include "dyngen-exec.h"
#include "helper.h"
-static void cpu_restore_state_from_retaddr(void *retaddr)
+static void cpu_restore_state_from_retaddr(uintptr_t retaddr)
{
TranslationBlock *tb;
- unsigned long pc;
if (retaddr) {
- pc = (unsigned long) retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
}
@@ -56,7 +54,7 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
#include "softmmu_template.h"
void tlb_fill(CPUSH4State *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
CPUSH4State *saved_env;
int ret;
@@ -84,7 +82,7 @@ void helper_ldtlb(void)
#endif
}
-static inline void raise_exception(int index, void *retaddr)
+static inline void raise_exception(int index, uintptr_t retaddr)
{
env->exception_index = index;
cpu_restore_state_from_retaddr(retaddr);
@@ -447,7 +445,7 @@ void helper_ld_fpscr(uint32_t val)
set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
}
-static void update_fpscr(void *retaddr)
+static void update_fpscr(uintptr_t retaddr)
{
int xcpt, cause, enable;
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 865288cc94..29c63c711f 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -702,7 +702,7 @@ trap_state* cpu_tsptr(CPUSPARCState* env);
#endif
void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
int is_write, int is_user,
- void *retaddr);
+ uintptr_t retaddr);
#define TB_FLAG_FPU_ENABLED (1 << 4)
#define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 1418205f99..04ffddf3c0 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -2376,25 +2376,23 @@ void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
#if !defined(CONFIG_USER_ONLY)
/* XXX: make it generic ? */
-static void cpu_restore_state2(CPUSPARCState *env, void *retaddr)
+static void cpu_restore_state2(CPUSPARCState *env, uintptr_t retaddr)
{
TranslationBlock *tb;
- unsigned long pc;
if (retaddr) {
/* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
+ tb = tb_find_pc(retaddr);
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
+ cpu_restore_state(tb, env, retaddr);
}
}
}
void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
- int is_user, void *retaddr)
+ int is_user, uintptr_t retaddr)
{
#ifdef DEBUG_UNALIGNED
printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
@@ -2409,7 +2407,7 @@ void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUSPARCState *env, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
int ret;
diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c
index 7c038351b3..804fdef56a 100644
--- a/target-xtensa/core-dc232b.c
+++ b/target-xtensa/core-dc232b.c
@@ -1,3 +1,30 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include "cpu.h"
#include "exec-all.h"
#include "gdbstub.h"
diff --git a/target-xtensa/core-dc233c.c b/target-xtensa/core-dc233c.c
new file mode 100644
index 0000000000..d643f41d37
--- /dev/null
+++ b/target-xtensa/core-dc233c.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "gdbstub.h"
+#include "qemu-common.h"
+#include "host-utils.h"
+
+#include "core-dc233c/core-isa.h"
+#include "overlay_tool.h"
+
+static const XtensaConfig dc233c = {
+ .name = "dc233c",
+ .options = XTENSA_OPTIONS,
+ .gdb_regmap = {
+ .num_regs = 121,
+ .num_core_regs = 52,
+ .reg = {
+#include "core-dc233c/gdb-config.c"
+ }
+ },
+ .nareg = XCHAL_NUM_AREGS,
+ .ndepc = 1,
+ EXCEPTIONS_SECTION,
+ INTERRUPTS_SECTION,
+ TLB_SECTION,
+ .clock_freq_khz = 10000,
+};
+
+REGISTER_CORE(dc233c)
diff --git a/target-xtensa/core-dc233c/core-isa.h b/target-xtensa/core-dc233c/core-isa.h
new file mode 100644
index 0000000000..e82c3cbe48
--- /dev/null
+++ b/target-xtensa/core-dc233c/core-isa.h
@@ -0,0 +1,474 @@
+/*
+ * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa
+ * processor CORE configuration
+ *
+ * See <xtensa/config/core.h>, which includes this file, for more details.
+ */
+
+/* Xtensa processor core configuration information.
+
+ Copyright (c) 1999-2010 Tensilica Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#ifndef _XTENSA_CORE_CONFIGURATION_H
+#define _XTENSA_CORE_CONFIGURATION_H
+
+
+/****************************************************************************
+ Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ * configured, and a value of 0 otherwise. These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+ ISA
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */
+#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE 3 /* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG 1 /* debug option */
+#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */
+#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32 1 /* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */
+#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */
+#define XCHAL_HAVE_L32R 1 /* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS 1 /* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */
+#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */
+#define XCHAL_HAVE_ABS 1 /* ABS instruction */
+/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */
+/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION 0 /* speculation */
+#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS 1 /* */
+#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID 1 /* processor ID register */
+#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */
+#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */
+#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */
+#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS 0 /* boolean registers */
+#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG 8 /* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16 1 /* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */
+#define XCHAL_HAVE_FP 0 /* floating point pkg */
+#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */
+#define XCHAL_HAVE_DFP_accel 0 /* double precision FP acceleration pkg */
+#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */
+#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */
+#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */
+#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */
+#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */
+#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */
+#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */
+#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */
+#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */
+#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */
+#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */
+#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */
+#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */
+
+
+/*----------------------------------------------------------------------
+ MISC
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH 4 /* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH 4 /* data width in bytes */
+/* In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/
+#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */
+#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/
+
+#define XCHAL_SW_VERSION 900001 /* sw version of this header */
+
+#define XCHAL_CORE_ID "dc233c" /* alphanum core name
+(CoreID) set in the Xtensa
+Processor Generator */
+
+#define XCHAL_CORE_DESCRIPTION "dc233c"
+#define XCHAL_BUILD_UNIQUE_ID 0x00004B21 /* 22-bit sw build ID */
+
+/*
+ * These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0 0xC56707FE /* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1 0x14404B21 /* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME "LX4.0.1" /* full version name */
+#define XCHAL_HW_VERSION_MAJOR 2400 /* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */
+#define XCHAL_HW_VERSION 240001 /* major*100+minor */
+#define XCHAL_HW_REL_LX4 1
+#define XCHAL_HW_REL_LX4_0 1
+#define XCHAL_HW_REL_LX4_0_1 1
+#define XCHAL_HW_CONFIGID_RELIABLE 1
+/* If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR 2400 /* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION 240001 /* earliest targeted hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR 2400 /* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION 240001 /* latest targeted hw */
+
+
+/*----------------------------------------------------------------------
+ CACHE
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE 32 /* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE 32 /* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH 5 /* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH 5 /* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE 16384 /* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */
+#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */
+
+#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */
+
+
+
+
+/****************************************************************************
+ Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+ CACHE
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */
+
+/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */
+
+/* Number of cache sets in log2(lines per way): */
+#define XCHAL_ICACHE_SETWIDTH 7
+#define XCHAL_DCACHE_SETWIDTH 7
+
+/* Cache set associativity (number of ways): */
+#define XCHAL_ICACHE_WAYS 4
+#define XCHAL_DCACHE_WAYS 4
+
+/* Cache features: */
+#define XCHAL_ICACHE_LINE_LOCKABLE 1
+#define XCHAL_DCACHE_LINE_LOCKABLE 1
+#define XCHAL_ICACHE_ECC_PARITY 0
+#define XCHAL_DCACHE_ECC_PARITY 0
+
+/* Cache access size in bytes (affects operation of SICW instruction): */
+#define XCHAL_ICACHE_ACCESS_SIZE 4
+#define XCHAL_DCACHE_ACCESS_SIZE 4
+
+/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */
+#define XCHAL_CA_BITS 4
+
+
+/*----------------------------------------------------------------------
+ INTERNAL I/D RAM/ROMs and XLMI
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */
+#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */
+#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */
+
+#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/
+
+
+/*----------------------------------------------------------------------
+ INTERRUPTS and TIMERS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS 22 /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS 17 /* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels
+(not including level zero) */
+#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */
+/* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/* Masks of interrupts at each interrupt level: */
+#define XCHAL_INTLEVEL1_MASK 0x001F80FF
+#define XCHAL_INTLEVEL2_MASK 0x00000100
+#define XCHAL_INTLEVEL3_MASK 0x00200E00
+#define XCHAL_INTLEVEL4_MASK 0x00001000
+#define XCHAL_INTLEVEL5_MASK 0x00002000
+#define XCHAL_INTLEVEL6_MASK 0x00000000
+#define XCHAL_INTLEVEL7_MASK 0x00004000
+
+/* Masks of interrupts at each range 1..n of interrupt levels: */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x001F80FF
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x001F81FF
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x003F8FFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x003F9FFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x003FBFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x003FBFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x003FFFFF
+
+/* Level of each interrupt: */
+#define XCHAL_INT0_LEVEL 1
+#define XCHAL_INT1_LEVEL 1
+#define XCHAL_INT2_LEVEL 1
+#define XCHAL_INT3_LEVEL 1
+#define XCHAL_INT4_LEVEL 1
+#define XCHAL_INT5_LEVEL 1
+#define XCHAL_INT6_LEVEL 1
+#define XCHAL_INT7_LEVEL 1
+#define XCHAL_INT8_LEVEL 2
+#define XCHAL_INT9_LEVEL 3
+#define XCHAL_INT10_LEVEL 3
+#define XCHAL_INT11_LEVEL 3
+#define XCHAL_INT12_LEVEL 4
+#define XCHAL_INT13_LEVEL 5
+#define XCHAL_INT14_LEVEL 7
+#define XCHAL_INT15_LEVEL 1
+#define XCHAL_INT16_LEVEL 1
+#define XCHAL_INT17_LEVEL 1
+#define XCHAL_INT18_LEVEL 1
+#define XCHAL_INT19_LEVEL 1
+#define XCHAL_INT20_LEVEL 1
+#define XCHAL_INT21_LEVEL 3
+#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */
+#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with
+EXCSAVE/EPS/EPC_n, RFI n) */
+
+/* Type of each interrupt: */
+#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT13_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI
+#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+
+/* Masks of interrupts for each type of interrupt: */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFC00000
+#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000880
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x003F8000
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000133F
+#define XCHAL_INTTYPE_MASK_TIMER 0x00002440
+#define XCHAL_INTTYPE_MASK_NMI 0x00004000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000
+
+/* Interrupt numbers assigned to specific interrupt sources: */
+#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT 10 /* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT 13 /* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED
+#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */
+
+/* Interrupt numbers for levels at which only one interrupt is configured: */
+#define XCHAL_INTLEVEL2_NUM 8
+#define XCHAL_INTLEVEL4_NUM 12
+#define XCHAL_INTLEVEL5_NUM 13
+#define XCHAL_INTLEVEL7_NUM 14
+/* (There are many interrupts each at level(s) 1, 3.) */
+
+
+/*
+ * External interrupt vectors/levels.
+ * These macros describe how Xtensa processor interrupt numbers
+ * (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ * map to external BInterrupt<n> pins, for those interrupts
+ * configured as external (level-triggered, edge-triggered, or NMI).
+ * See the Xtensa processor databook for more details.
+ */
+
+/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */
+#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */
+#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */
+#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM 8 /* (intlevel 2) */
+#define XCHAL_EXTINT7_NUM 9 /* (intlevel 3) */
+#define XCHAL_EXTINT8_NUM 12 /* (intlevel 4) */
+#define XCHAL_EXTINT9_NUM 14 /* (intlevel 7) */
+#define XCHAL_EXTINT10_NUM 15 /* (intlevel 1) */
+#define XCHAL_EXTINT11_NUM 16 /* (intlevel 1) */
+#define XCHAL_EXTINT12_NUM 17 /* (intlevel 1) */
+#define XCHAL_EXTINT13_NUM 18 /* (intlevel 1) */
+#define XCHAL_EXTINT14_NUM 19 /* (intlevel 1) */
+#define XCHAL_EXTINT15_NUM 20 /* (intlevel 1) */
+#define XCHAL_EXTINT16_NUM 21 /* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+ EXCEPTIONS and VECTORS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture
+number: 1 == XEA1 (old)
+2 == XEA2 (new)
+0 == XEAX (extern) or TX */
+#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */
+#define XCHAL_HAVE_HALT 0 /* halt architecture option */
+#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */
+#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */
+#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */
+#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */
+#define XCHAL_VECBASE_RESET_VADDR 0x00002000 /* VECBASE reset value */
+#define XCHAL_VECBASE_RESET_PADDR 0x00002000
+#define XCHAL_RESET_VECBASE_OVERLAP 0
+
+#define XCHAL_RESET_VECTOR0_VADDR 0xFE000000
+#define XCHAL_RESET_VECTOR0_PADDR 0xFE000000
+#define XCHAL_RESET_VECTOR1_VADDR 0x00001000
+#define XCHAL_RESET_VECTOR1_PADDR 0x00001000
+#define XCHAL_RESET_VECTOR_VADDR 0xFE000000
+#define XCHAL_RESET_VECTOR_PADDR 0xFE000000
+#define XCHAL_USER_VECOFS 0x00000340
+#define XCHAL_USER_VECTOR_VADDR 0x00002340
+#define XCHAL_USER_VECTOR_PADDR 0x00002340
+#define XCHAL_KERNEL_VECOFS 0x00000300
+#define XCHAL_KERNEL_VECTOR_VADDR 0x00002300
+#define XCHAL_KERNEL_VECTOR_PADDR 0x00002300
+#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x000023C0
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x000023C0
+#define XCHAL_WINDOW_OF4_VECOFS 0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS 0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS 0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS 0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS 0x00000140
+#define XCHAL_WINDOW_VECTORS_VADDR 0x00002000
+#define XCHAL_WINDOW_VECTORS_PADDR 0x00002000
+#define XCHAL_INTLEVEL2_VECOFS 0x00000180
+#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x00002180
+#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00002180
+#define XCHAL_INTLEVEL3_VECOFS 0x000001C0
+#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x000021C0
+#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x000021C0
+#define XCHAL_INTLEVEL4_VECOFS 0x00000200
+#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x00002200
+#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x00002200
+#define XCHAL_INTLEVEL5_VECOFS 0x00000240
+#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x00002240
+#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x00002240
+#define XCHAL_INTLEVEL6_VECOFS 0x00000280
+#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x00002280
+#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x00002280
+#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS
+#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR
+#define XCHAL_NMI_VECOFS 0x000002C0
+#define XCHAL_NMI_VECTOR_VADDR 0x000022C0
+#define XCHAL_NMI_VECTOR_PADDR 0x000022C0
+#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS
+#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+ DEBUG
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */
+#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+ MMU
+ ----------------------------------------------------------------------*/
+
+/* See core-matmap.h header file for more details. */
+
+#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */
+#define XCHAL_SPANNING_WAY 6 /* TLB spanning way number */
+#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU 1 /* full MMU (with page table
+[autorefill] and protection)
+usable for an MMU-based OS */
+/* If none of the above last 4 are set, it's a custom TLB configuration. */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2 2 /* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS 8 /* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS 4 /* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS 2 /* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
diff --git a/target-xtensa/core-dc233c/gdb-config.c b/target-xtensa/core-dc233c/gdb-config.c
new file mode 100644
index 0000000000..b632341b28
--- /dev/null
+++ b/target-xtensa/core-dc233c/gdb-config.c
@@ -0,0 +1,145 @@
+/* Configuration for the Xtensa architecture for GDB, the GNU debugger.
+
+ Copyright (c) 2003-2010 Tensilica Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/* idx ofs bi sz al targno flags cp typ group name */
+XTREG(0, 0, 32, 4, 4, 0x0020, 0x0006, -2, 9, 0x0100, pc, 0, 0, 0, 0, 0, 0)
+XTREG(1, 4, 32, 4, 4, 0x0100, 0x0006, -2, 1, 0x0002, ar0, 0, 0, 0, 0, 0, 0)
+XTREG(2, 8, 32, 4, 4, 0x0101, 0x0006, -2, 1, 0x0002, ar1, 0, 0, 0, 0, 0, 0)
+XTREG(3, 12, 32, 4, 4, 0x0102, 0x0006, -2, 1, 0x0002, ar2, 0, 0, 0, 0, 0, 0)
+XTREG(4, 16, 32, 4, 4, 0x0103, 0x0006, -2, 1, 0x0002, ar3, 0, 0, 0, 0, 0, 0)
+XTREG(5, 20, 32, 4, 4, 0x0104, 0x0006, -2, 1, 0x0002, ar4, 0, 0, 0, 0, 0, 0)
+XTREG(6, 24, 32, 4, 4, 0x0105, 0x0006, -2, 1, 0x0002, ar5, 0, 0, 0, 0, 0, 0)
+XTREG(7, 28, 32, 4, 4, 0x0106, 0x0006, -2, 1, 0x0002, ar6, 0, 0, 0, 0, 0, 0)
+XTREG(8, 32, 32, 4, 4, 0x0107, 0x0006, -2, 1, 0x0002, ar7, 0, 0, 0, 0, 0, 0)
+XTREG(9, 36, 32, 4, 4, 0x0108, 0x0006, -2, 1, 0x0002, ar8, 0, 0, 0, 0, 0, 0)
+XTREG(10, 40, 32, 4, 4, 0x0109, 0x0006, -2, 1, 0x0002, ar9, 0, 0, 0, 0, 0, 0)
+XTREG(11, 44, 32, 4, 4, 0x010a, 0x0006, -2, 1, 0x0002, ar10, 0, 0, 0, 0, 0, 0)
+XTREG(12, 48, 32, 4, 4, 0x010b, 0x0006, -2, 1, 0x0002, ar11, 0, 0, 0, 0, 0, 0)
+XTREG(13, 52, 32, 4, 4, 0x010c, 0x0006, -2, 1, 0x0002, ar12, 0, 0, 0, 0, 0, 0)
+XTREG(14, 56, 32, 4, 4, 0x010d, 0x0006, -2, 1, 0x0002, ar13, 0, 0, 0, 0, 0, 0)
+XTREG(15, 60, 32, 4, 4, 0x010e, 0x0006, -2, 1, 0x0002, ar14, 0, 0, 0, 0, 0, 0)
+XTREG(16, 64, 32, 4, 4, 0x010f, 0x0006, -2, 1, 0x0002, ar15, 0, 0, 0, 0, 0, 0)
+XTREG(17, 68, 32, 4, 4, 0x0110, 0x0006, -2, 1, 0x0002, ar16, 0, 0, 0, 0, 0, 0)
+XTREG(18, 72, 32, 4, 4, 0x0111, 0x0006, -2, 1, 0x0002, ar17, 0, 0, 0, 0, 0, 0)
+XTREG(19, 76, 32, 4, 4, 0x0112, 0x0006, -2, 1, 0x0002, ar18, 0, 0, 0, 0, 0, 0)
+XTREG(20, 80, 32, 4, 4, 0x0113, 0x0006, -2, 1, 0x0002, ar19, 0, 0, 0, 0, 0, 0)
+XTREG(21, 84, 32, 4, 4, 0x0114, 0x0006, -2, 1, 0x0002, ar20, 0, 0, 0, 0, 0, 0)
+XTREG(22, 88, 32, 4, 4, 0x0115, 0x0006, -2, 1, 0x0002, ar21, 0, 0, 0, 0, 0, 0)
+XTREG(23, 92, 32, 4, 4, 0x0116, 0x0006, -2, 1, 0x0002, ar22, 0, 0, 0, 0, 0, 0)
+XTREG(24, 96, 32, 4, 4, 0x0117, 0x0006, -2, 1, 0x0002, ar23, 0, 0, 0, 0, 0, 0)
+XTREG(25, 100, 32, 4, 4, 0x0118, 0x0006, -2, 1, 0x0002, ar24, 0, 0, 0, 0, 0, 0)
+XTREG(26, 104, 32, 4, 4, 0x0119, 0x0006, -2, 1, 0x0002, ar25, 0, 0, 0, 0, 0, 0)
+XTREG(27, 108, 32, 4, 4, 0x011a, 0x0006, -2, 1, 0x0002, ar26, 0, 0, 0, 0, 0, 0)
+XTREG(28, 112, 32, 4, 4, 0x011b, 0x0006, -2, 1, 0x0002, ar27, 0, 0, 0, 0, 0, 0)
+XTREG(29, 116, 32, 4, 4, 0x011c, 0x0006, -2, 1, 0x0002, ar28, 0, 0, 0, 0, 0, 0)
+XTREG(30, 120, 32, 4, 4, 0x011d, 0x0006, -2, 1, 0x0002, ar29, 0, 0, 0, 0, 0, 0)
+XTREG(31, 124, 32, 4, 4, 0x011e, 0x0006, -2, 1, 0x0002, ar30, 0, 0, 0, 0, 0, 0)
+XTREG(32, 128, 32, 4, 4, 0x011f, 0x0006, -2, 1, 0x0002, ar31, 0, 0, 0, 0, 0, 0)
+XTREG(33, 132, 32, 4, 4, 0x0200, 0x0006, -2, 2, 0x1100, lbeg, 0, 0, 0, 0, 0, 0)
+XTREG(34, 136, 32, 4, 4, 0x0201, 0x0006, -2, 2, 0x1100, lend, 0, 0, 0, 0, 0, 0)
+XTREG(35, 140, 32, 4, 4, 0x0202, 0x0006, -2, 2, 0x1100, lcount, 0, 0, 0, 0, 0, 0)
+XTREG(36, 144, 6, 4, 4, 0x0203, 0x0006, -2, 2, 0x1100, sar, 0, 0, 0, 0, 0, 0)
+XTREG(37, 148, 32, 4, 4, 0x0205, 0x0006, -2, 2, 0x1100, litbase, 0, 0, 0, 0, 0, 0)
+XTREG(38, 152, 3, 4, 4, 0x0248, 0x0006, -2, 2, 0x1002, windowbase, 0, 0, 0, 0, 0, 0)
+XTREG(39, 156, 8, 4, 4, 0x0249, 0x0006, -2, 2, 0x1002, windowstart, 0, 0, 0, 0, 0, 0)
+XTREG(40, 160, 32, 4, 4, 0x02b0, 0x0002, -2, 2, 0x1000, sr176, 0, 0, 0, 0, 0, 0)
+XTREG(41, 164, 32, 4, 4, 0x02d0, 0x0002, -2, 2, 0x1000, sr208, 0, 0, 0, 0, 0, 0)
+XTREG(42, 168, 19, 4, 4, 0x02e6, 0x0006, -2, 2, 0x1100, ps, 0, 0, 0, 0, 0, 0)
+XTREG(43, 172, 32, 4, 4, 0x03e7, 0x0006, -2, 3, 0x0110, threadptr, 0, 0, 0, 0, 0, 0)
+XTREG(44, 176, 32, 4, 4, 0x020c, 0x0006, -1, 2, 0x1100, scompare1, 0, 0, 0, 0, 0, 0)
+XTREG(45, 180, 32, 4, 4, 0x0210, 0x0006, -1, 2, 0x1100, acclo, 0, 0, 0, 0, 0, 0)
+XTREG(46, 184, 8, 4, 4, 0x0211, 0x0006, -1, 2, 0x1100, acchi, 0, 0, 0, 0, 0, 0)
+XTREG(47, 188, 32, 4, 4, 0x0220, 0x0006, -1, 2, 0x1100, m0, 0, 0, 0, 0, 0, 0)
+XTREG(48, 192, 32, 4, 4, 0x0221, 0x0006, -1, 2, 0x1100, m1, 0, 0, 0, 0, 0, 0)
+XTREG(49, 196, 32, 4, 4, 0x0222, 0x0006, -1, 2, 0x1100, m2, 0, 0, 0, 0, 0, 0)
+XTREG(50, 200, 32, 4, 4, 0x0223, 0x0006, -1, 2, 0x1100, m3, 0, 0, 0, 0, 0, 0)
+XTREG(51, 204, 32, 4, 4, 0x03e6, 0x000e, -1, 3, 0x0110, expstate, 0, 0, 0, 0, 0, 0)
+XTREG(52, 208, 32, 4, 4, 0x0253, 0x0007, -2, 2, 0x1000, ptevaddr, 0, 0, 0, 0, 0, 0)
+XTREG(53, 212, 32, 4, 4, 0x0259, 0x000d, -2, 2, 0x1000, mmid, 0, 0, 0, 0, 0, 0)
+XTREG(54, 216, 32, 4, 4, 0x025a, 0x0007, -2, 2, 0x1000, rasid, 0, 0, 0, 0, 0, 0)
+XTREG(55, 220, 25, 4, 4, 0x025b, 0x0007, -2, 2, 0x1000, itlbcfg, 0, 0, 0, 0, 0, 0)
+XTREG(56, 224, 25, 4, 4, 0x025c, 0x0007, -2, 2, 0x1000, dtlbcfg, 0, 0, 0, 0, 0, 0)
+XTREG(57, 228, 2, 4, 4, 0x0260, 0x0007, -2, 2, 0x1000, ibreakenable, 0, 0, 0, 0, 0, 0)
+XTREG(58, 232, 6, 4, 4, 0x0263, 0x0007, -2, 2, 0x1000, atomctl, 0, 0, 0, 0, 0, 0)
+XTREG(59, 236, 32, 4, 4, 0x0268, 0x0007, -2, 2, 0x1000, ddr, 0, 0, 0, 0, 0, 0)
+XTREG(60, 240, 32, 4, 4, 0x0280, 0x0007, -2, 2, 0x1000, ibreaka0, 0, 0, 0, 0, 0, 0)
+XTREG(61, 244, 32, 4, 4, 0x0281, 0x0007, -2, 2, 0x1000, ibreaka1, 0, 0, 0, 0, 0, 0)
+XTREG(62, 248, 32, 4, 4, 0x0290, 0x0007, -2, 2, 0x1000, dbreaka0, 0, 0, 0, 0, 0, 0)
+XTREG(63, 252, 32, 4, 4, 0x0291, 0x0007, -2, 2, 0x1000, dbreaka1, 0, 0, 0, 0, 0, 0)
+XTREG(64, 256, 32, 4, 4, 0x02a0, 0x0007, -2, 2, 0x1000, dbreakc0, 0, 0, 0, 0, 0, 0)
+XTREG(65, 260, 32, 4, 4, 0x02a1, 0x0007, -2, 2, 0x1000, dbreakc1, 0, 0, 0, 0, 0, 0)
+XTREG(66, 264, 32, 4, 4, 0x02b1, 0x0007, -2, 2, 0x1000, epc1, 0, 0, 0, 0, 0, 0)
+XTREG(67, 268, 32, 4, 4, 0x02b2, 0x0007, -2, 2, 0x1000, epc2, 0, 0, 0, 0, 0, 0)
+XTREG(68, 272, 32, 4, 4, 0x02b3, 0x0007, -2, 2, 0x1000, epc3, 0, 0, 0, 0, 0, 0)
+XTREG(69, 276, 32, 4, 4, 0x02b4, 0x0007, -2, 2, 0x1000, epc4, 0, 0, 0, 0, 0, 0)
+XTREG(70, 280, 32, 4, 4, 0x02b5, 0x0007, -2, 2, 0x1000, epc5, 0, 0, 0, 0, 0, 0)
+XTREG(71, 284, 32, 4, 4, 0x02b6, 0x0007, -2, 2, 0x1000, epc6, 0, 0, 0, 0, 0, 0)
+XTREG(72, 288, 32, 4, 4, 0x02b7, 0x0007, -2, 2, 0x1000, epc7, 0, 0, 0, 0, 0, 0)
+XTREG(73, 292, 32, 4, 4, 0x02c0, 0x0007, -2, 2, 0x1000, depc, 0, 0, 0, 0, 0, 0)
+XTREG(74, 296, 19, 4, 4, 0x02c2, 0x0007, -2, 2, 0x1000, eps2, 0, 0, 0, 0, 0, 0)
+XTREG(75, 300, 19, 4, 4, 0x02c3, 0x0007, -2, 2, 0x1000, eps3, 0, 0, 0, 0, 0, 0)
+XTREG(76, 304, 19, 4, 4, 0x02c4, 0x0007, -2, 2, 0x1000, eps4, 0, 0, 0, 0, 0, 0)
+XTREG(77, 308, 19, 4, 4, 0x02c5, 0x0007, -2, 2, 0x1000, eps5, 0, 0, 0, 0, 0, 0)
+XTREG(78, 312, 19, 4, 4, 0x02c6, 0x0007, -2, 2, 0x1000, eps6, 0, 0, 0, 0, 0, 0)
+XTREG(79, 316, 19, 4, 4, 0x02c7, 0x0007, -2, 2, 0x1000, eps7, 0, 0, 0, 0, 0, 0)
+XTREG(80, 320, 32, 4, 4, 0x02d1, 0x0007, -2, 2, 0x1000, excsave1, 0, 0, 0, 0, 0, 0)
+XTREG(81, 324, 32, 4, 4, 0x02d2, 0x0007, -2, 2, 0x1000, excsave2, 0, 0, 0, 0, 0, 0)
+XTREG(82, 328, 32, 4, 4, 0x02d3, 0x0007, -2, 2, 0x1000, excsave3, 0, 0, 0, 0, 0, 0)
+XTREG(83, 332, 32, 4, 4, 0x02d4, 0x0007, -2, 2, 0x1000, excsave4, 0, 0, 0, 0, 0, 0)
+XTREG(84, 336, 32, 4, 4, 0x02d5, 0x0007, -2, 2, 0x1000, excsave5, 0, 0, 0, 0, 0, 0)
+XTREG(85, 340, 32, 4, 4, 0x02d6, 0x0007, -2, 2, 0x1000, excsave6, 0, 0, 0, 0, 0, 0)
+XTREG(86, 344, 32, 4, 4, 0x02d7, 0x0007, -2, 2, 0x1000, excsave7, 0, 0, 0, 0, 0, 0)
+XTREG(87, 348, 8, 4, 4, 0x02e0, 0x0007, -2, 2, 0x1000, cpenable, 0, 0, 0, 0, 0, 0)
+XTREG(88, 352, 22, 4, 4, 0x02e2, 0x000b, -2, 2, 0x1000, interrupt, 0, 0, 0, 0, 0, 0)
+XTREG(89, 356, 22, 4, 4, 0x02e2, 0x000d, -2, 2, 0x1000, intset, 0, 0, 0, 0, 0, 0)
+XTREG(90, 360, 22, 4, 4, 0x02e3, 0x000d, -2, 2, 0x1000, intclear, 0, 0, 0, 0, 0, 0)
+XTREG(91, 364, 22, 4, 4, 0x02e4, 0x0007, -2, 2, 0x1000, intenable, 0, 0, 0, 0, 0, 0)
+XTREG(92, 368, 32, 4, 4, 0x02e7, 0x0007, -2, 2, 0x1000, vecbase, 0, 0, 0, 0, 0, 0)
+XTREG(93, 372, 6, 4, 4, 0x02e8, 0x0007, -2, 2, 0x1000, exccause, 0, 0, 0, 0, 0, 0)
+XTREG(94, 376, 12, 4, 4, 0x02e9, 0x0003, -2, 2, 0x1000, debugcause, 0, 0, 0, 0, 0, 0)
+XTREG(95, 380, 32, 4, 4, 0x02ea, 0x000f, -2, 2, 0x1000, ccount, 0, 0, 0, 0, 0, 0)
+XTREG(96, 384, 32, 4, 4, 0x02eb, 0x0003, -2, 2, 0x1000, prid, 0, 0, 0, 0, 0, 0)
+XTREG(97, 388, 32, 4, 4, 0x02ec, 0x000f, -2, 2, 0x1000, icount, 0, 0, 0, 0, 0, 0)
+XTREG(98, 392, 4, 4, 4, 0x02ed, 0x0007, -2, 2, 0x1000, icountlevel, 0, 0, 0, 0, 0, 0)
+XTREG(99, 396, 32, 4, 4, 0x02ee, 0x0007, -2, 2, 0x1000, excvaddr, 0, 0, 0, 0, 0, 0)
+XTREG(100, 400, 32, 4, 4, 0x02f0, 0x000f, -2, 2, 0x1000, ccompare0, 0, 0, 0, 0, 0, 0)
+XTREG(101, 404, 32, 4, 4, 0x02f1, 0x000f, -2, 2, 0x1000, ccompare1, 0, 0, 0, 0, 0, 0)
+XTREG(102, 408, 32, 4, 4, 0x02f2, 0x000f, -2, 2, 0x1000, ccompare2, 0, 0, 0, 0, 0, 0)
+XTREG(103, 412, 32, 4, 4, 0x02f4, 0x0007, -2, 2, 0x1000, misc0, 0, 0, 0, 0, 0, 0)
+XTREG(104, 416, 32, 4, 4, 0x02f5, 0x0007, -2, 2, 0x1000, misc1, 0, 0, 0, 0, 0, 0)
+XTREG(105, 420, 32, 4, 4, 0x0000, 0x0006, -2, 8, 0x0100, a0, 0, 0, 0, 0, 0, 0)
+XTREG(106, 424, 32, 4, 4, 0x0001, 0x0006, -2, 8, 0x0100, a1, 0, 0, 0, 0, 0, 0)
+XTREG(107, 428, 32, 4, 4, 0x0002, 0x0006, -2, 8, 0x0100, a2, 0, 0, 0, 0, 0, 0)
+XTREG(108, 432, 32, 4, 4, 0x0003, 0x0006, -2, 8, 0x0100, a3, 0, 0, 0, 0, 0, 0)
+XTREG(109, 436, 32, 4, 4, 0x0004, 0x0006, -2, 8, 0x0100, a4, 0, 0, 0, 0, 0, 0)
+XTREG(110, 440, 32, 4, 4, 0x0005, 0x0006, -2, 8, 0x0100, a5, 0, 0, 0, 0, 0, 0)
+XTREG(111, 444, 32, 4, 4, 0x0006, 0x0006, -2, 8, 0x0100, a6, 0, 0, 0, 0, 0, 0)
+XTREG(112, 448, 32, 4, 4, 0x0007, 0x0006, -2, 8, 0x0100, a7, 0, 0, 0, 0, 0, 0)
+XTREG(113, 452, 32, 4, 4, 0x0008, 0x0006, -2, 8, 0x0100, a8, 0, 0, 0, 0, 0, 0)
+XTREG(114, 456, 32, 4, 4, 0x0009, 0x0006, -2, 8, 0x0100, a9, 0, 0, 0, 0, 0, 0)
+XTREG(115, 460, 32, 4, 4, 0x000a, 0x0006, -2, 8, 0x0100, a10, 0, 0, 0, 0, 0, 0)
+XTREG(116, 464, 32, 4, 4, 0x000b, 0x0006, -2, 8, 0x0100, a11, 0, 0, 0, 0, 0, 0)
+XTREG(117, 468, 32, 4, 4, 0x000c, 0x0006, -2, 8, 0x0100, a12, 0, 0, 0, 0, 0, 0)
+XTREG(118, 472, 32, 4, 4, 0x000d, 0x0006, -2, 8, 0x0100, a13, 0, 0, 0, 0, 0, 0)
+XTREG(119, 476, 32, 4, 4, 0x000e, 0x0006, -2, 8, 0x0100, a14, 0, 0, 0, 0, 0, 0)
+XTREG(120, 480, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15, 0, 0, 0, 0, 0, 0)
diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c
index c11d9708e7..e36b0de9d5 100644
--- a/target-xtensa/core-fsf.c
+++ b/target-xtensa/core-fsf.c
@@ -1,3 +1,30 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include "cpu.h"
#include "exec-all.h"
#include "gdbstub.h"
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
new file mode 100644
index 0000000000..1fd2f274a1
--- /dev/null
+++ b/target-xtensa/cpu-qom.h
@@ -0,0 +1,80 @@
+/*
+ * QEMU Xtensa CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef QEMU_XTENSA_CPU_QOM_H
+#define QEMU_XTENSA_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_XTENSA_CPU "xtensa-cpu"
+
+#define XTENSA_CPU_CLASS(class) \
+ OBJECT_CLASS_CHECK(XtensaCPUClass, (class), TYPE_XTENSA_CPU)
+#define XTENSA_CPU(obj) \
+ OBJECT_CHECK(XtensaCPU, (obj), TYPE_XTENSA_CPU)
+#define XTENSA_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(XtensaCPUClass, (obj), TYPE_XTENSA_CPU)
+
+/**
+ * XtensaCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * An Xtensa CPU model.
+ */
+typedef struct XtensaCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} XtensaCPUClass;
+
+/**
+ * XtensaCPU:
+ * @env: #CPUXtensaState
+ *
+ * An Xtensa CPU.
+ */
+typedef struct XtensaCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUXtensaState env;
+} XtensaCPU;
+
+static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
+{
+ return XTENSA_CPU(container_of(env, XtensaCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
+
+
+#endif
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
new file mode 100644
index 0000000000..97deacb478
--- /dev/null
+++ b/target-xtensa/cpu.c
@@ -0,0 +1,88 @@
+/*
+ * QEMU Xtensa CPU
+ *
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cpu-qom.h"
+#include "qemu-common.h"
+
+
+/* CPUClass::reset() */
+static void xtensa_cpu_reset(CPUState *s)
+{
+ XtensaCPU *cpu = XTENSA_CPU(s);
+ XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu);
+ CPUXtensaState *env = &cpu->env;
+
+ xcc->parent_reset(s);
+
+ env->exception_taken = 0;
+ env->pc = env->config->exception_vector[EXC_RESET];
+ env->sregs[LITBASE] &= ~1;
+ env->sregs[PS] = xtensa_option_enabled(env->config,
+ XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
+ env->sregs[VECBASE] = env->config->vecbase;
+ env->sregs[IBREAKENABLE] = 0;
+
+ env->pending_irq_level = 0;
+ reset_mmu(env);
+}
+
+static void xtensa_cpu_initfn(Object *obj)
+{
+ XtensaCPU *cpu = XTENSA_CPU(obj);
+ CPUXtensaState *env = &cpu->env;
+
+ cpu_exec_init(env);
+}
+
+static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
+{
+ CPUClass *cc = CPU_CLASS(oc);
+ XtensaCPUClass *xcc = XTENSA_CPU_CLASS(cc);
+
+ xcc->parent_reset = cc->reset;
+ cc->reset = xtensa_cpu_reset;
+}
+
+static const TypeInfo xtensa_cpu_type_info = {
+ .name = TYPE_XTENSA_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(XtensaCPU),
+ .instance_init = xtensa_cpu_initfn,
+ .abstract = false,
+ .class_size = sizeof(XtensaCPUClass),
+ .class_init = xtensa_cpu_class_init,
+};
+
+static void xtensa_cpu_register_types(void)
+{
+ type_register_static(&xtensa_cpu_type_info);
+}
+
+type_init(xtensa_cpu_register_types)
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index a7bcf52220..6d0ea7c038 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -375,6 +375,7 @@ void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
int xtensa_get_physical_addr(CPUXtensaState *env,
uint32_t vaddr, int is_write, int mmu_idx,
uint32_t *paddr, uint32_t *page_size, unsigned *access);
+void reset_mmu(CPUXtensaState *env);
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env);
void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
@@ -470,6 +471,7 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
}
#include "cpu-all.h"
+#include "cpu-qom.h"
#include "exec-all.h"
static inline int cpu_has_work(CPUXtensaState *env)
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index dab135c4a9..2094227843 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -33,20 +33,9 @@
#include "hw/loader.h"
#endif
-static void reset_mmu(CPUXtensaState *env);
-
void cpu_state_reset(CPUXtensaState *env)
{
- env->exception_taken = 0;
- env->pc = env->config->exception_vector[EXC_RESET];
- env->sregs[LITBASE] &= ~1;
- env->sregs[PS] = xtensa_option_enabled(env->config,
- XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
- env->sregs[VECBASE] = env->config->vecbase;
- env->sregs[IBREAKENABLE] = 0;
-
- env->pending_irq_level = 0;
- reset_mmu(env);
+ cpu_reset(ENV_GET_CPU(env));
}
static struct XtensaConfigList *xtensa_cores;
@@ -95,6 +84,7 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
{
static int tcg_inited;
static int debug_handler_inited;
+ XtensaCPU *cpu;
CPUXtensaState *env;
const XtensaConfig *config = NULL;
XtensaConfigList *core = xtensa_cores;
@@ -109,9 +99,9 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
return NULL;
}
- env = g_malloc0(sizeof(*env));
+ cpu = XTENSA_CPU(object_new(TYPE_XTENSA_CPU));
+ env = &cpu->env;
env->config = config;
- cpu_exec_init(env);
if (!tcg_inited) {
tcg_inited = 1;
@@ -334,7 +324,7 @@ static void reset_tlb_region_way0(CPUXtensaState *env,
}
}
-static void reset_mmu(CPUXtensaState *env)
+void reset_mmu(CPUXtensaState *env)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
env->sregs[RASID] = 0x04030201;
diff --git a/target-xtensa/helpers.h b/target-xtensa/helper.h
index 48a741e46d..48a741e46d 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helper.h
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index cdef0db52e..364dc19bc0 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -27,11 +27,11 @@
#include "cpu.h"
#include "dyngen-exec.h"
-#include "helpers.h"
+#include "helper.h"
#include "host-utils.h"
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
- void *retaddr);
+ uintptr_t retaddr);
#define ALIGNED_ONLY
#define MMUSUFFIX _mmu
@@ -48,10 +48,9 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
#define SHIFT 3
#include "softmmu_template.h"
-static void do_restore_state(void *pc_ptr)
+static void do_restore_state(uintptr_t pc)
{
TranslationBlock *tb;
- uint32_t pc = (uint32_t)(intptr_t)pc_ptr;
tb = tb_find_pc(pc);
if (tb) {
@@ -60,7 +59,7 @@ static void do_restore_state(void *pc_ptr)
}
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
- void *retaddr)
+ uintptr_t retaddr)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
!xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
@@ -71,7 +70,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
}
void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_idx,
- void *retaddr)
+ uintptr_t retaddr)
{
CPUXtensaState *saved_env = env;
@@ -99,6 +98,18 @@ void tlb_fill(CPUXtensaState *env1, target_ulong vaddr, int is_write, int mmu_id
env = saved_env;
}
+static void tb_invalidate_virtual_addr(CPUXtensaState *env, uint32_t vaddr)
+{
+ uint32_t paddr;
+ uint32_t page_size;
+ unsigned access;
+ int ret = xtensa_get_physical_addr(env, vaddr, 2, 0,
+ &paddr, &page_size, &access);
+ if (ret == 0) {
+ tb_invalidate_phys_addr(paddr);
+ }
+}
+
void HELPER(exception)(uint32_t excp)
{
env->exception_index = excp;
@@ -358,8 +369,7 @@ void HELPER(movsp)(uint32_t pc)
void HELPER(wsr_lbeg)(uint32_t v)
{
if (env->sregs[LBEG] != v) {
- tb_invalidate_phys_page_range(
- env->sregs[LEND] - 1, env->sregs[LEND], 0);
+ tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
env->sregs[LBEG] = v;
}
}
@@ -367,11 +377,9 @@ void HELPER(wsr_lbeg)(uint32_t v)
void HELPER(wsr_lend)(uint32_t v)
{
if (env->sregs[LEND] != v) {
- tb_invalidate_phys_page_range(
- env->sregs[LEND] - 1, env->sregs[LEND], 0);
+ tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
env->sregs[LEND] = v;
- tb_invalidate_phys_page_range(
- env->sregs[LEND] - 1, env->sregs[LEND], 0);
+ tb_invalidate_virtual_addr(env, env->sregs[LEND] - 1);
}
}
@@ -692,8 +700,7 @@ void HELPER(wsr_ibreakenable)(uint32_t v)
for (i = 0; i < env->config->nibreak; ++i) {
if (change & (1 << i)) {
- tb_invalidate_phys_page_range(
- env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
+ tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
}
}
env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
@@ -702,9 +709,8 @@ void HELPER(wsr_ibreakenable)(uint32_t v)
void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
{
if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
- tb_invalidate_phys_page_range(
- env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
- tb_invalidate_phys_page_range(v, v + 1, 0);
+ tb_invalidate_virtual_addr(env, env->sregs[IBREAKA + i]);
+ tb_invalidate_virtual_addr(env, v);
}
env->sregs[IBREAKA + i] = v;
}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e0ff72b3f8..6900123983 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -37,9 +37,9 @@
#include "qemu-log.h"
#include "sysemu.h"
-#include "helpers.h"
+#include "helper.h"
#define GEN_HELPER 1
-#include "helpers.h"
+#include "helper.h"
typedef struct DisasContext {
const XtensaConfig *config;
@@ -183,7 +183,7 @@ void xtensa_translate_init(void)
}
}
#define GEN_HELPER 2
-#include "helpers.h"
+#include "helper.h"
}
static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
@@ -459,11 +459,13 @@ static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
{
gen_helper_wsr_lbeg(s);
+ gen_jumpi_check_loop_end(dc, 0);
}
static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
{
gen_helper_wsr_lend(s);
+ gen_jumpi_check_loop_end(dc, 0);
}
static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 871a7e74f5..da17bba39d 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -63,10 +63,15 @@ static const int tcg_target_reg_alloc_order[] = {
static const int tcg_target_call_iarg_regs[] = {
#if TCG_TARGET_REG_BITS == 64
+#if defined(_WIN64)
+ TCG_REG_RCX,
+ TCG_REG_RDX,
+#else
TCG_REG_RDI,
TCG_REG_RSI,
TCG_REG_RDX,
TCG_REG_RCX,
+#endif
TCG_REG_R8,
TCG_REG_R9,
#else
@@ -176,10 +181,10 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
ct->ct |= TCG_CT_REG;
if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set32(ct->u.regs, 0, 0xffff);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
+ tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
+ tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
#ifdef CONFIG_TCG_PASS_AREG0
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX);
+ tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
#endif
} else {
tcg_regset_set32(ct->u.regs, 0, 0xff);
@@ -1300,9 +1305,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
use the ADDR32 prefix. For now, do nothing. */
if (offset != GUEST_BASE) {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
- tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
- base = TCG_REG_RDI, offset = 0;
+ tcg_out_movi(s, TCG_TYPE_I64,
+ tcg_target_call_iarg_regs[0], GUEST_BASE);
+ tgen_arithr(s, ARITH_ADD + P_REXW,
+ tcg_target_call_iarg_regs[0], base);
+ base = tcg_target_call_iarg_regs[0];
+ offset = 0;
}
}
@@ -1434,8 +1442,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#endif
#else
tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
- TCG_REG_RSI, data_reg);
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
+ tcg_target_call_iarg_regs[1], data_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index);
stack_adjust = 0;
#ifdef CONFIG_TCG_PASS_AREG0
/* XXX/FIXME: suboptimal */
@@ -1474,9 +1482,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
use the ADDR32 prefix. For now, do nothing. */
if (offset != GUEST_BASE) {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
- tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
- base = TCG_REG_RDI, offset = 0;
+ tcg_out_movi(s, TCG_TYPE_I64,
+ tcg_target_call_iarg_regs[0], GUEST_BASE);
+ tgen_arithr(s, ARITH_ADD + P_REXW,
+ tcg_target_call_iarg_regs[0], base);
+ base = tcg_target_call_iarg_regs[0];
+ offset = 0;
}
}
@@ -1977,6 +1988,10 @@ static int tcg_target_callee_save_regs[] = {
#if TCG_TARGET_REG_BITS == 64
TCG_REG_RBP,
TCG_REG_RBX,
+#if defined(_WIN64)
+ TCG_REG_RDI,
+ TCG_REG_RSI,
+#endif
TCG_REG_R12,
TCG_REG_R13,
TCG_REG_R14, /* Currently used for the global env. */
@@ -2064,8 +2079,10 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
if (TCG_TARGET_REG_BITS == 64) {
+#if !defined(_WIN64)
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
+#endif
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
@@ -2102,7 +2119,9 @@ typedef struct {
DebugFrameFDE fde;
} DebugFrame;
-#if TCG_TARGET_REG_BITS == 64
+#if !defined(__ELF__)
+ /* Host machine without ELF. */
+#elif TCG_TARGET_REG_BITS == 64
#define ELF_HOST_MACHINE EM_X86_64
static DebugFrame debug_frame = {
.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
@@ -2156,6 +2175,7 @@ static DebugFrame debug_frame = {
};
#endif
+#if defined(ELF_HOST_MACHINE)
void tcg_register_jit(void *buf, size_t buf_size)
{
/* We're expecting a 2 byte uleb128 encoded value. */
@@ -2166,3 +2186,4 @@ void tcg_register_jit(void *buf, size_t buf_size)
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}
+#endif
diff --git a/tests/Makefile b/tests/Makefile
index a98a848ec9..baf1d70ee8 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -92,8 +92,6 @@ check-help:
@echo "Default options are -k and (for make V=1) --verbose; they can be"
@echo "changed with variable GTESTER_OPTIONS."
-.SECONDARY:
-
SPEED = quick
GTESTER_OPTIONS = -k $(if $(V),--verbose,-q)
diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 7e1e619d23..0ff0ccfb8c 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -72,5 +72,8 @@ run-test_fail.tst: test_fail.tst
debug-%.tst: %.tst
$(SIM) $(SIMDEBUG) $(SIMFLAGS) ./$<
+host-debug-%.tst: %.tst
+ gdb --args $(SIM) $(SIMFLAGS) ./$<
+
clean:
$(RM) -fr $(TESTCASES) $(CRT)
diff --git a/tests/tcg/xtensa/macros.inc b/tests/tcg/xtensa/macros.inc
index 2d4515e14f..23bf3e96c8 100644
--- a/tests/tcg/xtensa/macros.inc
+++ b/tests/tcg/xtensa/macros.inc
@@ -29,7 +29,24 @@ main:
exit
.endm
+.macro print text
+.data
+97: .ascii "\text\n"
+98:
+ .align 4
+.text
+ movi a2, 4
+ movi a3, 2
+ movi a4, 97b
+ movi a5, 98b
+ sub a5, a5, a4
+ simcall
+.endm
+
.macro test name
+ //print test_\name
+test_\name:
+.global test_\name
.endm
.macro test_end
diff --git a/tests/tcg/xtensa/test_break.S b/tests/tcg/xtensa/test_break.S
index 8a8db8033b..7574cbefc8 100644
--- a/tests/tcg/xtensa/test_break.S
+++ b/tests/tcg/xtensa/test_break.S
@@ -91,6 +91,40 @@ test ibreak
assert eq, a2, a3
test_end
+test ibreak_remove
+ set_vector debug_vector, 3f
+ rsil a2, debug_level - 1
+ movi a2, 2f
+ wsr a2, ibreaka0
+ movi a3, 1
+1:
+ wsr a3, ibreakenable
+ isync
+2:
+ beqz a3, 4f
+ test_fail
+3:
+ assert eqi, a3, 1
+ rsr a2, ps
+ movi a3, 0x1f
+ and a2, a2, a3
+ movi a3, 0x10 | debug_level
+ assert eq, a2, a3
+ rsr a2, epc6
+ movi a3, 2b
+ assert eq, a2, a3
+ rsr a2, debugcause
+ movi a3, 0x2
+ assert eq, a2, a3
+
+ movi a2, 0x40000
+ wsr a2, ps
+ isync
+ movi a3, 0
+ j 1b
+4:
+test_end
+
test ibreak_priority
set_vector debug_vector, 2f
rsil a2, debug_level - 1
diff --git a/tests/tcg/xtensa/test_loop.S b/tests/tcg/xtensa/test_loop.S
index a5ea933913..5cead47a27 100644
--- a/tests/tcg/xtensa/test_loop.S
+++ b/tests/tcg/xtensa/test_loop.S
@@ -74,4 +74,54 @@ test loop_excm
assert eqi, a2, 1
test_end
+test lbeg_invalidation
+ movi a2, 0
+ movi a3, 1
+ movi a4, 1f
+ movi a5, 3f
+ wsr a3, lcount
+ wsr a4, lbeg
+ wsr a5, lend
+ isync
+ j 1f
+.align 4
+1:
+ addi a2, a2, 1
+ j 2f
+.align 4
+2:
+ addi a2, a2, 2
+ movi a3, 2b
+ wsr a3, lbeg
+ isync
+ nop
+3:
+ assert eqi, a2, 5
+test_end
+
+test lend_invalidation
+ movi a2, 0
+ movi a3, 5
+ movi a4, 1f
+ movi a5, 2f
+ wsr a3, lcount
+ wsr a4, lbeg
+ wsr a5, lend
+ isync
+ j 1f
+.align 4
+1:
+ addi a2, a2, 1
+2:
+ beqi a3, 3, 1f
+ assert eqi, a2, 6
+ movi a3, 3
+ wsr a3, lcount
+ wsr a4, lend
+ isync
+ j 1b
+1:
+ assert eqi, a2, 7
+test_end
+
test_suite_end
diff --git a/user-exec.c b/user-exec.c
index cd905ff189..be6bc4f64c 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -82,7 +82,7 @@ void cpu_resume_from_signal(CPUArchState *env1, void *puc)
the effective address of the memory exception. 'is_write' is 1 if a
write caused the exception and otherwise 0'. 'old_set' is the
signal set which should be restored */
-static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
int is_write, sigset_t *old_set,
void *puc)
{
diff --git a/xen-all.c b/xen-all.c
index 3e6de417ec..a08eec0931 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -59,6 +59,9 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
}
# define FMT_ioreq_size "u"
#endif
+#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
+#define HVM_PARAM_BUFIOREQ_EVTCHN 26
+#endif
#define BUFFER_IO_MAX_DELAY 100
@@ -77,6 +80,8 @@ typedef struct XenIOState {
QEMUTimer *buffered_io_timer;
/* the evtchn port for polling the notification, */
evtchn_port_t *ioreq_local_port;
+ /* evtchn local port for buffered io */
+ evtchn_port_t bufioreq_local_port;
/* the evtchn fd for polling */
XenEvtchn xce_handle;
/* which vcpu we are serving */
@@ -122,6 +127,11 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
}
}
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+ xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
+}
+
static void xen_suspend_notifier(Notifier *notifier, void *data)
{
xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
@@ -624,6 +634,12 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
evtchn_port_t port;
port = xc_evtchn_pending(state->xce_handle);
+ if (port == state->bufioreq_local_port) {
+ qemu_mod_timer(state->buffered_io_timer,
+ BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+ return NULL;
+ }
+
if (port != -1) {
for (i = 0; i < smp_cpus; i++) {
if (state->ioreq_local_port[i] == port) {
@@ -772,16 +788,18 @@ static void handle_ioreq(ioreq_t *req)
}
}
-static void handle_buffered_iopage(XenIOState *state)
+static int handle_buffered_iopage(XenIOState *state)
{
buf_ioreq_t *buf_req = NULL;
ioreq_t req;
int qw;
if (!state->buffered_io_page) {
- return;
+ return 0;
}
+ memset(&req, 0x00, sizeof(req));
+
while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
buf_req = &state->buffered_io_page->buf_ioreq[
state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
@@ -806,15 +824,21 @@ static void handle_buffered_iopage(XenIOState *state)
xen_mb();
state->buffered_io_page->read_pointer += qw ? 2 : 1;
}
+
+ return req.count;
}
static void handle_buffered_io(void *opaque)
{
XenIOState *state = opaque;
- handle_buffered_iopage(state);
- qemu_mod_timer(state->buffered_io_timer,
- BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+ if (handle_buffered_iopage(state)) {
+ qemu_mod_timer(state->buffered_io_timer,
+ BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+ } else {
+ qemu_del_timer(state->buffered_io_timer);
+ xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
+ }
}
static void cpu_handle_ioreq(void *opaque)
@@ -944,7 +968,6 @@ static void xen_main_loop_prepare(XenIOState *state)
state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
state);
- qemu_mod_timer(state->buffered_io_timer, qemu_get_clock_ms(rt_clock));
if (evtchn_fd != -1) {
qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
@@ -1045,6 +1068,7 @@ int xen_hvm_init(void)
{
int i, rc;
unsigned long ioreq_pfn;
+ unsigned long bufioreq_evtchn;
XenIOState *state;
state = g_malloc0(sizeof (XenIOState));
@@ -1097,6 +1121,20 @@ int xen_hvm_init(void)
state->ioreq_local_port[i] = rc;
}
+ rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
+ &bufioreq_evtchn);
+ if (rc < 0) {
+ fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
+ return -1;
+ }
+ rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+ (uint32_t)bufioreq_evtchn);
+ if (rc == -1) {
+ fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
+ return -1;
+ }
+ state->bufioreq_local_port = rc;
+
/* Init RAM management */
xen_map_cache_init(xen_phys_offset_to_gaddr, state);
xen_ram_init(ram_size);
diff --git a/xen-mapcache.c b/xen-mapcache.c
index a456479363..59ba085b62 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -216,12 +216,14 @@ tryagain:
}
/* size is always a multiple of MCACHE_BUCKET_SIZE */
- if ((address_offset + (__size % MCACHE_BUCKET_SIZE)) > MCACHE_BUCKET_SIZE)
- __size += MCACHE_BUCKET_SIZE;
- if (__size % MCACHE_BUCKET_SIZE)
- __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE);
- if (!__size)
+ if (size) {
+ __size = size + address_offset;
+ if (__size % MCACHE_BUCKET_SIZE) {
+ __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE);
+ }
+ } else {
__size = MCACHE_BUCKET_SIZE;
+ }
entry = &mapcache->entry[address_index % mapcache->nr_buckets];
@@ -385,6 +387,9 @@ void xen_invalidate_map_cache(void)
if (entry->vaddr_base == NULL) {
continue;
}
+ if (entry->lock > 0) {
+ continue;
+ }
if (munmap(entry->vaddr_base, entry->size) != 0) {
perror("unmap fails");
diff --git a/xen-stub.c b/xen-stub.c
index 9ea02d435e..8ff2b79ac6 100644
--- a/xen-stub.c
+++ b/xen-stub.c
@@ -29,6 +29,10 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
{
}
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+}
+
void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
{
}
diff --git a/xtensa-semi.c b/xtensa-semi.c
index 5754b7782a..b7c8c34564 100644
--- a/xtensa-semi.c
+++ b/xtensa-semi.c
@@ -31,7 +31,7 @@
#include <stddef.h>
#include "cpu.h"
#include "dyngen-exec.h"
-#include "helpers.h"
+#include "helper.h"
#include "qemu-log.h"
enum {