aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/block/aio.h64
-rw-r--r--include/block/block_int.h8
-rw-r--r--include/block/blockjob.h2
-rw-r--r--include/block/coroutine.h12
-rw-r--r--include/elf.h6
-rw-r--r--include/exec/cpu-all.h8
-rw-r--r--include/exec/cpu-defs.h2
-rw-r--r--include/exec/exec-all.h31
-rw-r--r--include/exec/gdbstub.h47
-rw-r--r--include/exec/poison.h1
-rw-r--r--include/exec/softmmu_defs.h46
-rw-r--r--include/exec/softmmu_template.h309
-rw-r--r--include/hw/acpi/acpi.h2
-rw-r--r--include/hw/arm/arm.h5
-rw-r--r--include/hw/char/escc.h1
-rw-r--r--include/hw/char/lm32_juart.h (renamed from include/hw/lm32/lm32_juart.h)8
-rw-r--r--include/hw/i386/ioapic.h1
-rw-r--r--include/hw/i386/pc.h22
-rw-r--r--include/hw/isa/isa.h3
-rw-r--r--include/hw/loader.h1
-rw-r--r--include/hw/mips/mips.h3
-rw-r--r--include/hw/pci-host/q35.h2
-rw-r--r--include/hw/pci-host/spapr.h6
-rw-r--r--include/hw/pci/pci_bus.h7
-rw-r--r--include/hw/pci/pci_ids.h5
-rw-r--r--include/hw/pci/pcie_port.h14
-rw-r--r--include/hw/ppc/spapr.h39
-rw-r--r--include/hw/ppc/spapr_vio.h5
-rw-r--r--include/hw/ppc/xics.h74
-rw-r--r--include/hw/qdev-core.h30
-rw-r--r--include/hw/qdev-properties.h3
-rw-r--r--include/hw/sysbus.h9
-rw-r--r--include/hw/timer/m48t59.h3
-rw-r--r--include/hw/virtio/virtio-blk.h1
-rw-r--r--include/hw/virtio/virtio.h1
-rw-r--r--include/migration/migration.h2
-rw-r--r--include/qapi/opts-visitor.h6
-rw-r--r--include/qapi/qmp/qdict.h1
-rw-r--r--include/qapi/qmp/qobject.h1
-rw-r--r--include/qapi/visitor-impl.h6
-rw-r--r--include/qapi/visitor.h6
-rw-r--r--include/qemu/option.h3
-rw-r--r--include/qemu/ratelimit.h2
-rw-r--r--include/qemu/thread-posix.h2
-rw-r--r--include/qemu/timer.h676
-rw-r--r--include/qemu/typedefs.h3
-rw-r--r--include/qom/cpu.h15
-rw-r--r--include/qom/object.h3
-rw-r--r--include/sysemu/char.h1
-rw-r--r--include/sysemu/dump.h4
-rw-r--r--include/sysemu/kvm.h2
-rw-r--r--include/sysemu/memory_mapping.h30
-rw-r--r--include/sysemu/sysemu.h3
-rw-r--r--include/ui/qemu-spice.h2
54 files changed, 1191 insertions, 358 deletions
diff --git a/include/block/aio.h b/include/block/aio.h
index cc77771c46..2efdf416cf 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -14,10 +14,12 @@
#ifndef QEMU_AIO_H
#define QEMU_AIO_H
+#include "qemu/typedefs.h"
#include "qemu-common.h"
#include "qemu/queue.h"
#include "qemu/event_notifier.h"
#include "qemu/thread.h"
+#include "qemu/timer.h"
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
@@ -42,7 +44,7 @@ typedef struct AioHandler AioHandler;
typedef void QEMUBHFunc(void *opaque);
typedef void IOHandler(void *opaque);
-typedef struct AioContext {
+struct AioContext {
GSource source;
/* The list of registered AIO handlers */
@@ -72,10 +74,10 @@ typedef struct AioContext {
/* Thread pool for performing work and receiving completion callbacks */
struct ThreadPool *thread_pool;
-} AioContext;
-/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
-typedef int (AioFlushEventNotifierHandler)(EventNotifier *e);
+ /* TimerLists for calling timers - one per clock type */
+ QEMUTimerListGroup tlg;
+};
/**
* aio_context_new: Allocate a new AioContext.
@@ -198,9 +200,6 @@ bool aio_pending(AioContext *ctx);
bool aio_poll(AioContext *ctx, bool blocking);
#ifdef CONFIG_POSIX
-/* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
-typedef int (AioFlushHandler)(void *opaque);
-
/* Register a file descriptor and associated callbacks. Behaves very similarly
* to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will
* be invoked when using qemu_aio_wait().
@@ -212,7 +211,6 @@ void aio_set_fd_handler(AioContext *ctx,
int fd,
IOHandler *io_read,
IOHandler *io_write,
- AioFlushHandler *io_flush,
void *opaque);
#endif
@@ -225,8 +223,7 @@ void aio_set_fd_handler(AioContext *ctx,
*/
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
- EventNotifierHandler *io_read,
- AioFlushEventNotifierHandler *io_flush);
+ EventNotifierHandler *io_read);
/* Return a GSource that lets the main loop poll the file descriptors attached
* to this AioContext.
@@ -240,15 +237,56 @@ struct ThreadPool *aio_get_thread_pool(AioContext *ctx);
bool qemu_aio_wait(void);
void qemu_aio_set_event_notifier(EventNotifier *notifier,
- EventNotifierHandler *io_read,
- AioFlushEventNotifierHandler *io_flush);
+ EventNotifierHandler *io_read);
#ifdef CONFIG_POSIX
void qemu_aio_set_fd_handler(int fd,
IOHandler *io_read,
IOHandler *io_write,
- AioFlushHandler *io_flush,
void *opaque);
#endif
+/**
+ * aio_timer_new:
+ * @ctx: the aio context
+ * @type: the clock type
+ * @scale: the scale
+ * @cb: the callback to call on timer expiry
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Allocate a new timer attached to the context @ctx.
+ * The function is responsible for memory allocation.
+ *
+ * The preferred interface is aio_timer_init. Use that
+ * unless you really need dynamic memory allocation.
+ *
+ * Returns: a pointer to the new timer
+ */
+static inline QEMUTimer *aio_timer_new(AioContext *ctx, QEMUClockType type,
+ int scale,
+ QEMUTimerCB *cb, void *opaque)
+{
+ return timer_new_tl(ctx->tlg.tl[type], scale, cb, opaque);
+}
+
+/**
+ * aio_timer_init:
+ * @ctx: the aio context
+ * @ts: the timer
+ * @type: the clock type
+ * @scale: the scale
+ * @cb: the callback to call on timer expiry
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Initialise a new timer attached to the context @ctx.
+ * The caller is responsible for memory allocation.
+ */
+static inline void aio_timer_init(AioContext *ctx,
+ QEMUTimer *ts, QEMUClockType type,
+ int scale,
+ QEMUTimerCB *cb, void *opaque)
+{
+ timer_init(ts, ctx->tlg.tl[type], scale, cb, opaque);
+}
+
#endif
diff --git a/include/block/block_int.h b/include/block/block_int.h
index c6ac871e21..8012e253c9 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -34,6 +34,7 @@
#include "monitor/monitor.h"
#include "qemu/hbitmap.h"
#include "block/snapshot.h"
+#include "qemu/main-loop.h"
#define BLOCK_FLAG_ENCRYPT 1
#define BLOCK_FLAG_COMPAT6 4
@@ -281,6 +282,9 @@ struct BlockDriverState {
/* Whether the disk can expand beyond total_sectors */
int growable;
+ /* Whether produces zeros when read beyond eof */
+ bool zero_beyond_eof;
+
/* the memory alignment required for the buffers handled by this driver */
int buffer_alignment;
@@ -404,6 +408,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
* @bs: Block device to operate on.
* @target: Block device to write to.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
+ * @sync_mode: What parts of the disk image should be copied to the destination.
* @on_source_error: The action to take upon error reading from the source.
* @on_target_error: The action to take upon error writing to the target.
* @cb: Completion function for the job.
@@ -413,7 +418,8 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
* until the job is cancelled or manually completed.
*/
void backup_start(BlockDriverState *bs, BlockDriverState *target,
- int64_t speed, BlockdevOnError on_source_error,
+ int64_t speed, MirrorSyncMode sync_mode,
+ BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
BlockDriverCompletionFunc *cb, void *opaque,
Error **errp);
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index c290d07bba..d530409ff5 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -141,7 +141,7 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
* Put the job to sleep (assuming that it wasn't canceled) for @ns
* nanoseconds. Canceling the job will interrupt the wait immediately.
*/
-void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns);
+void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns);
/**
* block_job_completed:
diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index 377805a3b0..4232569c53 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -16,6 +16,7 @@
#define QEMU_COROUTINE_H
#include <stdbool.h>
+#include "qemu/typedefs.h"
#include "qemu/queue.h"
#include "qemu/timer.h"
@@ -130,12 +131,17 @@ void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue);
*
* Returns true if a coroutine was restarted, false if the queue is empty.
*/
-bool qemu_co_queue_next(CoQueue *queue);
+bool coroutine_fn qemu_co_queue_next(CoQueue *queue);
/**
* Restarts all coroutines in the CoQueue and leaves the queue empty.
*/
-void qemu_co_queue_restart_all(CoQueue *queue);
+void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue);
+
+/**
+ * Enter the next coroutine in the queue
+ */
+bool qemu_co_enter_next(CoQueue *queue);
/**
* Checks if the CoQueue is empty.
@@ -207,7 +213,7 @@ void qemu_co_rwlock_unlock(CoRwlock *lock);
* Note this function uses timers and hence only works when a main loop is in
* use. See main-loop.h and do not use from qemu-tool programs.
*/
-void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns);
+void coroutine_fn co_sleep_ns(QEMUClockType type, int64_t ns);
/**
* Yield until a file descriptor becomes readable
diff --git a/include/elf.h b/include/elf.h
index cf0d3e2bd6..58bfbf8817 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1348,11 +1348,17 @@ typedef struct elf64_shdr {
/* Notes used in ET_CORE */
#define NT_PRSTATUS 1
+#define NT_FPREGSET 2
#define NT_PRFPREG 2
#define NT_PRPSINFO 3
#define NT_TASKSTRUCT 4
#define NT_AUXV 6
#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
+#define NT_S390_PREFIX 0x305 /* s390 prefix register */
+#define NT_S390_CTRS 0x304 /* s390 control registers */
+#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
+#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
+#define NT_S390_TIMER 0x301 /* s390 timer register */
/* Note header in a PT_NOTE section */
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index f2800ec682..a407b50f4a 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -210,11 +210,15 @@ extern unsigned long reserved_va;
})
#endif
-#define h2g(x) ({ \
+#define h2g_nocheck(x) ({ \
unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
+ (abi_ulong)__ret; \
+})
+
+#define h2g(x) ({ \
/* Check if given address fits target address space */ \
assert(h2g_valid(x)); \
- (abi_ulong)__ret; \
+ h2g_nocheck(x); \
})
#define saddr(x) g2h(x)
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index b5b93db842..a5c028c536 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -154,8 +154,6 @@ typedef struct CPUWatchpoint {
memory was accessed */ \
CPU_COMMON_TLB \
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
- /* buffer for temporaries in the code generator */ \
- long temp_buf[CPU_TEMP_BUF_NLONGS]; \
\
int64_t icount_extra; /* Instructions until next timer event. */ \
/* Number of cycles left, with interrupt flag in high bit. \
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index b2162a4ec4..ffb69a4c70 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -326,18 +326,7 @@ extern uintptr_t tci_tb_ptr;
(6) jump to corresponding code of the next of fast path
*/
# if defined(__i386__) || defined(__x86_64__)
-/* To avoid broken disassembling, long jmp is used for embedding fast path pc,
- so that the destination is the next code of fast path, though this jmp is
- never executed.
-
- call MMU helper
- jmp POST_PROC (2byte) <- GETRA()
- jmp NEXT_CODE (5byte)
- POST_PROCESS ... <- GETRA() + 7
- */
-# define GETRA() ((uintptr_t)__builtin_return_address(0))
-# define GETPC_LDST() ((uintptr_t)(GETRA() + 7 + \
- *(int32_t *)((void *)GETRA() + 3) - 1))
+# define GETPC_EXT() GETPC()
# elif defined (_ARCH_PPC) && !defined (_ARCH_PPC64)
# define GETRA() ((uintptr_t)__builtin_return_address(0))
# define GETPC_LDST() ((uintptr_t) ((*(int32_t *)(GETRA() - 4)) - 1))
@@ -358,11 +347,27 @@ static inline uintptr_t tcg_getpc_ldst(uintptr_t ra)
not the start of the next opcode */
return ra;
}
+# elif defined(__aarch64__)
+# define GETRA() ((uintptr_t)__builtin_return_address(0))
+# define GETPC_LDST() tcg_getpc_ldst(GETRA())
+static inline uintptr_t tcg_getpc_ldst(uintptr_t ra)
+{
+ int32_t b;
+ ra += 4; /* skip one instruction */
+ b = *(int32_t *)ra; /* load the branch insn */
+ b = (b << 6) >> (6 - 2); /* extract the displacement */
+ ra += b; /* apply the displacement */
+ ra -= 4; /* return a pointer into the current opcode,
+ not the start of the next opcode */
+ return ra;
+}
# else
# error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!"
# endif
bool is_tcg_gen_code(uintptr_t pc_ptr);
-# define GETPC_EXT() (is_tcg_gen_code(GETRA()) ? GETPC_LDST() : GETPC())
+# ifndef GETPC_EXT
+# define GETPC_EXT() (is_tcg_gen_code(GETRA()) ? GETPC_LDST() : GETPC())
+# endif
#else
# define GETPC_EXT() GETPC()
#endif
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 1bd00aea23..a608a26c30 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -32,13 +32,50 @@ void gdb_register_coprocessor(CPUState *cpu,
static inline int cpu_index(CPUState *cpu)
{
-#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
+#if defined(CONFIG_USER_ONLY)
return cpu->host_tid;
#else
return cpu->cpu_index + 1;
#endif
}
+/* The GDB remote protocol transfers values in target byte order. This means
+ * we can use the raw memory access routines to access the value buffer.
+ * Conveniently, these also handle the case where the buffer is mis-aligned.
+ */
+
+static inline int gdb_get_reg8(uint8_t *mem_buf, uint8_t val)
+{
+ stb_p(mem_buf, val);
+ return 1;
+}
+
+static inline int gdb_get_reg16(uint8_t *mem_buf, uint16_t val)
+{
+ stw_p(mem_buf, val);
+ return 2;
+}
+
+static inline int gdb_get_reg32(uint8_t *mem_buf, uint32_t val)
+{
+ stl_p(mem_buf, val);
+ return 4;
+}
+
+static inline int gdb_get_reg64(uint8_t *mem_buf, uint64_t val)
+{
+ stq_p(mem_buf, val);
+ return 8;
+}
+
+#if TARGET_LONG_BITS == 64
+#define gdb_get_regl(buf, val) gdb_get_reg64(buf, val)
+#define ldtul_p(addr) ldq_p(addr)
+#else
+#define gdb_get_regl(buf, val) gdb_get_reg32(buf, val)
+#define ldtul_p(addr) ldl_p(addr)
+#endif
+
#endif
#ifdef CONFIG_USER_ONLY
@@ -47,6 +84,14 @@ int gdbserver_start(int);
int gdbserver_start(const char *port);
#endif
+/**
+ * gdb_has_xml:
+ * This is an ugly hack to cope with both new and old gdb.
+ * If gdb sends qXfer:features:read then assume we're talking to a newish
+ * gdb that understands target descriptions.
+ */
+extern bool gdb_has_xml;
+
/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
extern const char *const xml_builtin[][2];
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 2341a75041..a4b1eca24f 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -36,7 +36,6 @@
#pragma GCC poison TARGET_PAGE_ALIGN
#pragma GCC poison CPUArchState
-#pragma GCC poison env
#pragma GCC poison lduw_phys
#pragma GCC poison ldl_phys
diff --git a/include/exec/softmmu_defs.h b/include/exec/softmmu_defs.h
index 1f25e33ce4..e55e7178c6 100644
--- a/include/exec/softmmu_defs.h
+++ b/include/exec/softmmu_defs.h
@@ -9,29 +9,41 @@
#ifndef SOFTMMU_DEFS_H
#define SOFTMMU_DEFS_H
+uint8_t helper_ret_ldb_mmu(CPUArchState *env, target_ulong addr,
+ int mmu_idx, uintptr_t retaddr);
+uint16_t helper_ret_ldw_mmu(CPUArchState *env, target_ulong addr,
+ int mmu_idx, uintptr_t retaddr);
+uint32_t helper_ret_ldl_mmu(CPUArchState *env, target_ulong addr,
+ int mmu_idx, uintptr_t retaddr);
+uint64_t helper_ret_ldq_mmu(CPUArchState *env, target_ulong addr,
+ int mmu_idx, uintptr_t retaddr);
+
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+ int mmu_idx, uintptr_t retaddr);
+void helper_ret_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+ int mmu_idx, uintptr_t retaddr);
+void helper_ret_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+ int mmu_idx, uintptr_t retaddr);
+void helper_ret_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+ int mmu_idx, uintptr_t retaddr);
+
uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
- int mmu_idx);
uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
- int mmu_idx);
uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
- int mmu_idx);
uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
- int mmu_idx);
+
+void helper_stb_mmu(CPUArchState *env, target_ulong addr,
+ uint8_t val, int mmu_idx);
+void helper_stw_mmu(CPUArchState *env, target_ulong addr,
+ uint16_t val, int mmu_idx);
+void helper_stl_mmu(CPUArchState *env, target_ulong addr,
+ uint32_t val, int mmu_idx);
+void helper_stq_mmu(CPUArchState *env, target_ulong addr,
+ uint64_t val, int mmu_idx);
uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stb_cmmu(CPUArchState *env, target_ulong addr, uint8_t val,
-int mmu_idx);
uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stw_cmmu(CPUArchState *env, target_ulong addr, uint16_t val,
- int mmu_idx);
uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stl_cmmu(CPUArchState *env, target_ulong addr, uint32_t val,
- int mmu_idx);
uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
-void helper_stq_cmmu(CPUArchState *env, target_ulong addr, uint64_t val,
- int mmu_idx);
-#endif
+
+#endif /* SOFTMMU_DEFS_H */
diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h
index 8584902cbe..eaca9e1035 100644
--- a/include/exec/softmmu_template.h
+++ b/include/exec/softmmu_template.h
@@ -54,10 +54,6 @@
#define ADDR_READ addr_read
#endif
-static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env,
- target_ulong addr,
- int mmu_idx,
- uintptr_t retaddr);
static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
hwaddr physaddr,
target_ulong addr,
@@ -78,123 +74,86 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
}
/* handle all cases except unaligned access which span two pages */
+#ifdef SOFTMMU_CODE_ACCESS
+static
+#endif
DATA_TYPE
-glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
- int mmu_idx)
+glue(glue(helper_ret_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env,
+ target_ulong addr, int mmu_idx,
+ uintptr_t retaddr)
{
- DATA_TYPE res;
- int index;
- target_ulong tlb_addr;
- hwaddr ioaddr;
- uintptr_t retaddr;
+ int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+ target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+ uintptr_t haddr;
- /* test if there is match for unaligned or IO access */
- /* XXX: could done more in memory macro in a non portable way */
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
- if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- if (tlb_addr & ~TARGET_PAGE_MASK) {
- /* IO access */
- if ((addr & (DATA_SIZE - 1)) != 0)
- goto do_unaligned_access;
- retaddr = GETPC_EXT();
- ioaddr = env->iotlb[mmu_idx][index];
- res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
- } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
- /* slow unaligned access (it spans two pages or IO) */
- do_unaligned_access:
- retaddr = GETPC_EXT();
+ /* If the TLB entry is for a different page, reload and try again. */
+ if ((addr & TARGET_PAGE_MASK)
+ != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
#ifdef ALIGNED_ONLY
+ if ((addr & (DATA_SIZE - 1)) != 0) {
do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
-#endif
- res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr,
- 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_EXT();
- do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
- }
-#endif
- 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 */
- retaddr = GETPC_EXT();
-#ifdef ALIGNED_ONLY
- if ((addr & (DATA_SIZE - 1)) != 0)
- do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
#endif
tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
- goto redo;
+ tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
}
- return res;
-}
-/* handle all unaligned cases */
-static DATA_TYPE
-glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env,
- target_ulong addr,
- int mmu_idx,
- uintptr_t retaddr)
-{
- DATA_TYPE res, res1, res2;
- int index, shift;
- hwaddr ioaddr;
- target_ulong tlb_addr, addr1, addr2;
+ /* Handle an IO access. */
+ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+ hwaddr ioaddr;
+ if ((addr & (DATA_SIZE - 1)) != 0) {
+ goto do_unaligned_access;
+ }
+ ioaddr = env->iotlb[mmu_idx][index];
+ return glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+ }
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
- if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- if (tlb_addr & ~TARGET_PAGE_MASK) {
- /* IO access */
- if ((addr & (DATA_SIZE - 1)) != 0)
- goto do_unaligned_access;
- ioaddr = env->iotlb[mmu_idx][index];
- res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
- } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
- do_unaligned_access:
- /* slow unaligned access (it spans two pages) */
- addr1 = addr & ~(DATA_SIZE - 1);
- addr2 = addr1 + DATA_SIZE;
- res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr1,
- mmu_idx, retaddr);
- res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr2,
- mmu_idx, retaddr);
- shift = (addr & (DATA_SIZE - 1)) * 8;
+ /* Handle slow unaligned access (it spans two pages or IO). */
+ if (DATA_SIZE > 1
+ && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+ >= TARGET_PAGE_SIZE)) {
+ target_ulong addr1, addr2;
+ DATA_TYPE res1, res2, res;
+ unsigned shift;
+ do_unaligned_access:
+#ifdef ALIGNED_ONLY
+ do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+#endif
+ addr1 = addr & ~(DATA_SIZE - 1);
+ addr2 = addr1 + DATA_SIZE;
+ res1 = glue(glue(helper_ret_ld, SUFFIX), MMUSUFFIX)(env, addr1,
+ mmu_idx, retaddr);
+ res2 = glue(glue(helper_ret_ld, SUFFIX), MMUSUFFIX)(env, addr2,
+ mmu_idx, retaddr);
+ shift = (addr & (DATA_SIZE - 1)) * 8;
#ifdef TARGET_WORDS_BIGENDIAN
- res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
+ res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
#else
- res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
+ res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
#endif
- res = (DATA_TYPE)res;
- } else {
- /* unaligned/aligned access in the same page */
- 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 */
- tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
- goto redo;
+ return res;
+ }
+
+ /* Handle aligned access or unaligned access in the same page. */
+#ifdef ALIGNED_ONLY
+ if ((addr & (DATA_SIZE - 1)) != 0) {
+ do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
}
- return res;
+#endif
+
+ haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ return glue(glue(ld, USUFFIX), _raw)((uint8_t *)haddr);
}
-#ifndef SOFTMMU_CODE_ACCESS
+DATA_TYPE
+glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
+ int mmu_idx)
+{
+ return glue(glue(helper_ret_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx,
+ GETPC_EXT());
+}
-static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
- target_ulong addr,
- DATA_TYPE val,
- int mmu_idx,
- uintptr_t retaddr);
+#ifndef SOFTMMU_CODE_ACCESS
static inline void glue(io_write, SUFFIX)(CPUArchState *env,
hwaddr physaddr,
@@ -214,107 +173,79 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
io_mem_write(mr, physaddr, val, 1 << SHIFT);
}
-void glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
- target_ulong addr, DATA_TYPE val,
- int mmu_idx)
+void
+glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
+ target_ulong addr, DATA_TYPE val,
+ int mmu_idx, uintptr_t retaddr)
{
- hwaddr ioaddr;
- target_ulong tlb_addr;
- uintptr_t retaddr;
- int index;
+ int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+ target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+ uintptr_t haddr;
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
- if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- if (tlb_addr & ~TARGET_PAGE_MASK) {
- /* IO access */
- if ((addr & (DATA_SIZE - 1)) != 0)
- goto do_unaligned_access;
- retaddr = GETPC_EXT();
- ioaddr = env->iotlb[mmu_idx][index];
- glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
- } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
- do_unaligned_access:
- retaddr = GETPC_EXT();
+ /* If the TLB entry is for a different page, reload and try again. */
+ if ((addr & TARGET_PAGE_MASK)
+ != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
#ifdef ALIGNED_ONLY
+ if ((addr & (DATA_SIZE - 1)) != 0) {
do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
-#endif
- glue(glue(slow_st, SUFFIX), MMUSUFFIX)(env, addr, val,
- 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_EXT();
- do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
- }
-#endif
- 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 */
- retaddr = GETPC_EXT();
-#ifdef ALIGNED_ONLY
- if ((addr & (DATA_SIZE - 1)) != 0)
- do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
#endif
tlb_fill(env, addr, 1, mmu_idx, retaddr);
- goto redo;
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
}
-}
-/* handles all unaligned cases */
-static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
- target_ulong addr,
- DATA_TYPE val,
- int mmu_idx,
- uintptr_t retaddr)
-{
- hwaddr ioaddr;
- target_ulong tlb_addr;
- int index, i;
+ /* Handle an IO access. */
+ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
+ hwaddr ioaddr;
+ if ((addr & (DATA_SIZE - 1)) != 0) {
+ goto do_unaligned_access;
+ }
+ ioaddr = env->iotlb[mmu_idx][index];
+ glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
+ return;
+ }
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
- if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- if (tlb_addr & ~TARGET_PAGE_MASK) {
- /* IO access */
- if ((addr & (DATA_SIZE - 1)) != 0)
- goto do_unaligned_access;
- ioaddr = env->iotlb[mmu_idx][index];
- glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
- } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
- do_unaligned_access:
- /* XXX: not efficient, but simple */
- /* Note: relies on the fact that tlb_fill() does not remove the
- * previous page from the TLB cache. */
- for(i = DATA_SIZE - 1; i >= 0; i--) {
+ /* Handle slow unaligned access (it spans two pages or IO). */
+ if (DATA_SIZE > 1
+ && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
+ >= TARGET_PAGE_SIZE)) {
+ int i;
+ do_unaligned_access:
+#ifdef ALIGNED_ONLY
+ do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
+#endif
+ /* XXX: not efficient, but simple */
+ /* Note: relies on the fact that tlb_fill() does not remove the
+ * previous page from the TLB cache. */
+ for (i = DATA_SIZE - 1; i >= 0; i--) {
#ifdef TARGET_WORDS_BIGENDIAN
- glue(slow_stb, MMUSUFFIX)(env, addr + i,
- val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
- mmu_idx, retaddr);
+ uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
#else
- glue(slow_stb, MMUSUFFIX)(env, addr + i,
- val >> (i * 8),
- mmu_idx, retaddr);
+ uint8_t val8 = val >> (i * 8);
#endif
- }
- } else {
- /* aligned/unaligned access in the same page */
- uintptr_t addend = env->tlb_table[mmu_idx][index].addend;
- glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t)
- (addr + addend), val);
+ glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
+ mmu_idx, retaddr);
}
- } else {
- /* the page is not in the TLB : fill it */
- tlb_fill(env, addr, 1, mmu_idx, retaddr);
- goto redo;
+ return;
+ }
+
+ /* Handle aligned access or unaligned access in the same page. */
+#ifdef ALIGNED_ONLY
+ if ((addr & (DATA_SIZE - 1)) != 0) {
+ do_unaligned_access(env, addr, 1, mmu_idx, retaddr);
}
+#endif
+
+ haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ glue(glue(st, SUFFIX), _raw)((uint8_t *)haddr, val);
+}
+
+void
+glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
+ DATA_TYPE val, int mmu_idx)
+{
+ glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, val, mmu_idx,
+ GETPC_EXT());
}
#endif /* !defined(SOFTMMU_CODE_ACCESS) */
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 635be7be10..51733d3390 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -136,7 +136,7 @@ void acpi_pm_tmr_reset(ACPIREGS *ar);
#include "qemu/timer.h"
static inline int64_t acpi_pm_tmr_get_clock(void)
{
- return muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY,
+ return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY,
get_ticks_per_sec());
}
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index bae87c6273..ecbbba871e 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -14,11 +14,6 @@
#include "exec/memory.h"
#include "hw/irq.h"
-/* The CPU is also modelled as an interrupt controller. */
-#define ARM_PIC_CPU_IRQ 0
-#define ARM_PIC_CPU_FIQ 1
-qemu_irq *arm_pic_init_cpu(ARMCPU *cpu);
-
/* armv7m.c */
qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
int flash_size, int sram_size,
diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h
index bda3213317..2742d70ea0 100644
--- a/include/hw/char/escc.h
+++ b/include/hw/char/escc.h
@@ -2,6 +2,7 @@
#define HW_ESCC_H 1
/* escc.c */
+#define TYPE_ESCC "escc"
#define ESCC_SIZE 4
MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
CharDriverState *chrA, CharDriverState *chrB,
diff --git a/include/hw/lm32/lm32_juart.h b/include/hw/char/lm32_juart.h
index 67fc5866ea..70dc416e9f 100644
--- a/include/hw/lm32/lm32_juart.h
+++ b/include/hw/char/lm32_juart.h
@@ -1,7 +1,9 @@
-#ifndef QEMU_HW_LM32_JUART_H
-#define QEMU_HW_LM32_JUART_H
+#ifndef QEMU_HW_CHAR_LM32_JUART_H
+#define QEMU_HW_CHAR_LM32_JUART_H
-#include "qemu-common.h"
+#include "hw/qdev.h"
+
+#define TYPE_LM32_JUART "lm32-juart"
uint32_t lm32_juart_get_jtx(DeviceState *d);
uint32_t lm32_juart_get_jrx(DeviceState *d);
diff --git a/include/hw/i386/ioapic.h b/include/hw/i386/ioapic.h
index 86e63dac74..6245388c5d 100644
--- a/include/hw/i386/ioapic.h
+++ b/include/hw/i386/ioapic.h
@@ -21,6 +21,7 @@
#define HW_IOAPIC_H
#define IOAPIC_NUM_PINS 24
+#define IO_APIC_DEFAULT_ADDRESS 0xfec00000
void ioapic_eoi_broadcast(int vector);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 7fb97b08a2..f79d4782c1 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -18,8 +18,8 @@ typedef struct PcPciInfo {
} PcPciInfo;
struct PcGuestInfo {
- PcPciInfo pci_info;
bool has_pci_info;
+ bool isapc_ram_fw;
FWCfgState *fw_cfg;
};
@@ -101,6 +101,16 @@ void pc_acpi_init(const char *default_dsdt);
PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
ram_addr_t above_4g_mem_size);
+#define PCI_HOST_PROP_PCI_HOLE_START "pci-hole-start"
+#define PCI_HOST_PROP_PCI_HOLE_END "pci-hole-end"
+#define PCI_HOST_PROP_PCI_HOLE64_START "pci-hole64-start"
+#define PCI_HOST_PROP_PCI_HOLE64_END "pci-hole64-end"
+#define PCI_HOST_PROP_PCI_HOLE64_SIZE "pci-hole64-size"
+#define DEFAULT_PCI_HOLE64_SIZE (1ULL << 31)
+
+void pc_init_pci64_hole(PcPciInfo *pci_info, uint64_t pci_hole64_start,
+ uint64_t pci_hole64_size);
+
FWCfgState *pc_memory_init(MemoryRegion *system_memory,
const char *kernel_filename,
const char *kernel_cmdline,
@@ -150,8 +160,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
ram_addr_t ram_size,
hwaddr pci_hole_start,
hwaddr pci_hole_size,
- hwaddr pci_hole64_start,
- hwaddr pci_hole64_size,
+ ram_addr_t above_4g_mem_size,
MemoryRegion *pci_memory,
MemoryRegion *ram_memory);
@@ -192,7 +201,8 @@ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd)
}
/* pc_sysfw.c */
-void pc_system_firmware_init(MemoryRegion *rom_memory);
+void pc_system_firmware_init(MemoryRegion *rom_memory,
+ bool isapc_ram_fw);
/* pvpanic.c */
void pvpanic_init(ISABus *bus);
@@ -235,6 +245,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
.driver = "virtio-net-pci",\
.property = "any_layout",\
.value = "off",\
+ },{\
+ .driver = TYPE_X86_CPU,\
+ .property = "pmu",\
+ .value = "on",\
}
#define PC_COMPAT_1_4 \
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index e1bf96ca69..495bcf3a08 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -92,9 +92,6 @@ static inline ISABus *isa_bus_from_device(ISADevice *d)
extern hwaddr isa_mem_base;
-void isa_mmio_setup(MemoryRegion *mr, hwaddr size);
-void isa_mmio_init(hwaddr base, hwaddr size);
-
/* dma.c */
int DMA_get_channel_mode (int nchan);
int DMA_read_memory (int nchan, void *buf, int pos, int size);
diff --git a/include/hw/loader.h b/include/hw/loader.h
index eb9c9a3612..61457360f6 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -36,6 +36,7 @@ void pstrcpy_targphys(const char *name,
hwaddr dest, int buf_size,
const char *source);
+extern bool rom_file_in_ram;
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex);
diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h
index 291e85f6b9..2a7a9c9f42 100644
--- a/include/hw/mips/mips.h
+++ b/include/hw/mips/mips.h
@@ -2,6 +2,9 @@
#define HW_MIPS_H
/* Definitions for mips board emulation. */
+/* Kernels can be configured with 64KB pages */
+#define INITRD_PAGE_MASK (~((1 << 16) - 1))
+
#include "exec/memory.h"
/* gt64xxx.c */
diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h
index 3cb631eeae..6eb7ab676f 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -55,9 +55,11 @@ typedef struct MCHPCIState {
MemoryRegion smram_region;
MemoryRegion pci_hole;
MemoryRegion pci_hole_64bit;
+ PcPciInfo pci_info;
uint8_t smm_enabled;
ram_addr_t below_4g_mem_size;
ram_addr_t above_4g_mem_size;
+ uint64_t pci_hole64_size;
PcGuestInfo *guest_info;
} MCHPCIState;
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 1e23dbfb4a..93f9511325 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -52,14 +52,14 @@ typedef struct sPAPRPHBState {
sPAPRTCETable *tcet;
AddressSpace iommu_as;
- struct {
+ struct spapr_pci_lsi {
uint32_t irq;
} lsi_table[PCI_NUM_PINS];
- struct {
+ struct spapr_pci_msi {
uint32_t config_addr;
uint32_t irq;
- int nvec;
+ uint32_t nvec;
} msi_table[SPAPR_MSIX_MAX_DEVS];
QLIST_ENTRY(sPAPRPHBState) list;
diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
index 66762f6d5e..9df17885ec 100644
--- a/include/hw/pci/pci_bus.h
+++ b/include/hw/pci/pci_bus.h
@@ -53,8 +53,13 @@ struct PCIBridgeWindows {
MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS];
};
+#define TYPE_PCI_BRIDGE "base-pci-bridge"
+#define PCI_BRIDGE(obj) OBJECT_CHECK(PCIBridge, (obj), TYPE_PCI_BRIDGE)
+
struct PCIBridge {
- PCIDevice dev;
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
/* private member */
PCIBus sec_bus;
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index d7933bfd16..3ddaf6aad5 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -143,8 +143,9 @@
#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0
-#define PCI_VENDOR_ID_XEN 0x5853
-#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
+#define PCI_VENDOR_ID_XEN 0x5853
+#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001
+#define PCI_DEVICE_ID_XEN_PVDEVICE 0x0002
#define PCI_VENDOR_ID_NEC 0x1033
#define PCI_DEVICE_ID_NEC_UPD720200 0x0194
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index d89aa615c5..e167bf7520 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -24,8 +24,13 @@
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
+#define TYPE_PCIE_PORT "pcie-port"
+#define PCIE_PORT(obj) OBJECT_CHECK(PCIEPort, (obj), TYPE_PCIE_PORT)
+
struct PCIEPort {
- PCIBridge br;
+ /*< private >*/
+ PCIBridge parent_obj;
+ /*< public >*/
/* pci express switch port */
uint8_t port;
@@ -33,8 +38,13 @@ struct PCIEPort {
void pcie_port_init_reg(PCIDevice *d);
+#define TYPE_PCIE_SLOT "pcie-slot"
+#define PCIE_SLOT(obj) OBJECT_CHECK(PCIESlot, (obj), TYPE_PCIE_SLOT)
+
struct PCIESlot {
- PCIEPort port;
+ /*< private >*/
+ PCIEPort parent_obj;
+ /*< public >*/
/* pci express switch port with slot */
uint8_t chassis;
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index de95480734..9fc197286c 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -7,30 +7,36 @@
struct VIOsPAPRBus;
struct sPAPRPHBState;
struct sPAPRNVRAM;
-struct icp_state;
+
+#define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL
typedef struct sPAPREnvironment {
struct VIOsPAPRBus *vio_bus;
QLIST_HEAD(, sPAPRPHBState) phbs;
struct sPAPRNVRAM *nvram;
- struct icp_state *icp;
+ XICSState *icp;
hwaddr ram_limit;
void *htab;
- long htab_shift;
+ uint32_t htab_shift;
hwaddr rma_size;
int vrma_adjust;
hwaddr fdt_addr, rtas_addr;
long rtas_size;
void *fdt_skel;
target_ulong entry_point;
- int next_irq;
- int rtc_offset;
+ uint32_t next_irq;
+ uint64_t rtc_offset;
char *cpu_model;
bool has_graphics;
uint32_t epow_irq;
Notifier epow_notifier;
+
+ /* Migration state */
+ int htab_save_index;
+ bool htab_first_pass;
+ int htab_fd;
} sPAPREnvironment;
#define H_SUCCESS 0
@@ -334,10 +340,6 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
#define SPAPR_TCE_PAGE_SIZE (1ULL << SPAPR_TCE_PAGE_SHIFT)
#define SPAPR_TCE_PAGE_MASK (SPAPR_TCE_PAGE_SIZE - 1)
-typedef struct sPAPRTCE {
- uint64_t tce;
-} sPAPRTCE;
-
#define SPAPR_VIO_BASE_LIOBN 0x00000000
#define SPAPR_PCI_BASE_LIOBN 0x80000000
@@ -345,14 +347,27 @@ typedef struct sPAPRTCE {
typedef struct sPAPRTCETable sPAPRTCETable;
-void spapr_iommu_init(void);
+#define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
+#define SPAPR_TCE_TABLE(obj) \
+ OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)
+
+struct sPAPRTCETable {
+ DeviceState parent;
+ uint32_t liobn;
+ uint32_t window_size;
+ uint32_t nb_table;
+ uint64_t *table;
+ bool bypass;
+ int fd;
+ MemoryRegion iommu;
+ QLIST_ENTRY(sPAPRTCETable) list;
+};
+
void spapr_events_init(sPAPREnvironment *spapr);
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
size_t window_size);
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
-void spapr_tce_free(sPAPRTCETable *tcet);
-void spapr_tce_reset(sPAPRTCETable *tcet);
void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass);
int spapr_dma_dt(void *fdt, int node_off, const char *propname,
uint32_t liobn, uint64_t window, uint32_t size);
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index 36093270e6..46edc2a20c 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -134,4 +134,9 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus);
void spapr_vio_quiesce(void);
+extern const VMStateDescription vmstate_spapr_vio;
+
+#define VMSTATE_SPAPR_VIO(_f, _s) \
+ VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, VIOsPAPRDevice)
+
#endif /* _HW_SPAPR_VIO_H */
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 6bce0424df..66364c5faf 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -27,15 +27,77 @@
#if !defined(__XICS_H__)
#define __XICS_H__
+#include "hw/sysbus.h"
+
+#define TYPE_XICS "xics"
+#define XICS(obj) OBJECT_CHECK(XICSState, (obj), TYPE_XICS)
+
#define XICS_IPI 0x2
-#define XICS_IRQ_BASE 0x10
+#define XICS_BUID 0x1
+#define XICS_IRQ_BASE (XICS_BUID << 12)
+
+/*
+ * We currently only support one BUID which is our interrupt base
+ * (the kernel implementation supports more but we don't exploit
+ * that yet)
+ */
+typedef struct XICSState XICSState;
+typedef struct ICPState ICPState;
+typedef struct ICSState ICSState;
+typedef struct ICSIRQState ICSIRQState;
+
+struct XICSState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ uint32_t nr_servers;
+ uint32_t nr_irqs;
+ ICPState *ss;
+ ICSState *ics;
+};
+
+#define TYPE_ICP "icp"
+#define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP)
+
+struct ICPState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+ uint32_t xirr;
+ uint8_t pending_priority;
+ uint8_t mfrr;
+ qemu_irq output;
+};
+
+#define TYPE_ICS "ics"
+#define ICS(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS)
+
+struct ICSState {
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+ uint32_t nr_irqs;
+ uint32_t offset;
+ qemu_irq *qirqs;
+ bool *islsi;
+ ICSIRQState *irqs;
+ XICSState *icp;
+};
-struct icp_state;
+struct ICSIRQState {
+ uint32_t server;
+ uint8_t priority;
+ uint8_t saved_priority;
+#define XICS_STATUS_ASSERTED 0x1
+#define XICS_STATUS_SENT 0x2
+#define XICS_STATUS_REJECTED 0x4
+#define XICS_STATUS_MASKED_PENDING 0x8
+ uint8_t status;
+};
-qemu_irq xics_get_qirq(struct icp_state *icp, int irq);
-void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi);
+qemu_irq xics_get_qirq(XICSState *icp, int irq);
+void xics_set_irq_type(XICSState *icp, int irq, bool lsi);
-struct icp_state *xics_system_init(int nr_servers, int nr_irqs);
-void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu);
+void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
#endif /* __XICS_H__ */
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 7fbffcbaad..46972f4961 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -4,6 +4,7 @@
#include "qemu/queue.h"
#include "qemu/option.h"
#include "qemu/typedefs.h"
+#include "qemu/bitmap.h"
#include "qom/object.h"
#include "hw/irq.h"
#include "qapi/error.h"
@@ -17,6 +18,34 @@ enum {
#define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE)
#define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE)
+typedef enum DeviceCategory {
+ DEVICE_CATEGORY_BRIDGE,
+ DEVICE_CATEGORY_USB,
+ DEVICE_CATEGORY_STORAGE,
+ DEVICE_CATEGORY_NETWORK,
+ DEVICE_CATEGORY_INPUT,
+ DEVICE_CATEGORY_DISPLAY,
+ DEVICE_CATEGORY_SOUND,
+ DEVICE_CATEGORY_MISC,
+ DEVICE_CATEGORY_MAX
+} DeviceCategory;
+
+static inline const char *qdev_category_get_name(DeviceCategory category)
+{
+ static const char *category_names[DEVICE_CATEGORY_MAX] = {
+ [DEVICE_CATEGORY_BRIDGE] = "Controller/Bridge/Hub",
+ [DEVICE_CATEGORY_USB] = "USB",
+ [DEVICE_CATEGORY_STORAGE] = "Storage",
+ [DEVICE_CATEGORY_NETWORK] = "Network",
+ [DEVICE_CATEGORY_INPUT] = "Input",
+ [DEVICE_CATEGORY_DISPLAY] = "Display",
+ [DEVICE_CATEGORY_SOUND] = "Sound",
+ [DEVICE_CATEGORY_MISC] = "Misc",
+ };
+
+ return category_names[category];
+};
+
typedef int (*qdev_initfn)(DeviceState *dev);
typedef int (*qdev_event)(DeviceState *dev);
typedef void (*qdev_resetfn)(DeviceState *dev);
@@ -80,6 +109,7 @@ typedef struct DeviceClass {
ObjectClass parent_class;
/*< public >*/
+ DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX);
const char *fw_name;
const char *desc;
Property *props;
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 39448b716c..692f82e935 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -15,6 +15,7 @@ extern PropertyInfo qdev_prop_uint64;
extern PropertyInfo qdev_prop_hex8;
extern PropertyInfo qdev_prop_hex32;
extern PropertyInfo qdev_prop_hex64;
+extern PropertyInfo qdev_prop_size;
extern PropertyInfo qdev_prop_string;
extern PropertyInfo qdev_prop_chr;
extern PropertyInfo qdev_prop_ptr;
@@ -116,6 +117,8 @@ extern PropertyInfo qdev_prop_arraylen;
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
+#define DEFINE_PROP_SIZE(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_size, uint64_t)
#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h
index 8c17165cf2..bb50a877cc 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -42,7 +42,10 @@ typedef struct SysBusDeviceClass {
} SysBusDeviceClass;
struct SysBusDevice {
- DeviceState qdev;
+ /*< private >*/
+ DeviceState parent_obj;
+ /*< public >*/
+
int num_irq;
qemu_irq irqs[QDEV_MAX_IRQ];
qemu_irq *irqp[QDEV_MAX_IRQ];
@@ -55,10 +58,6 @@ struct SysBusDevice {
pio_addr_t pio[QDEV_MAX_PIO];
};
-/* Macros to compensate for lack of type inheritance in C. */
-#define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev)
-
-void *sysbus_new(void);
void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory);
MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n);
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
diff --git a/include/hw/timer/m48t59.h b/include/hw/timer/m48t59.h
index 59337faaad..8217522291 100644
--- a/include/hw/timer/m48t59.h
+++ b/include/hw/timer/m48t59.h
@@ -21,6 +21,9 @@ int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
uint32_t initrd_image, uint32_t initrd_size,
uint32_t NVRAM_image,
int width, int height, int depth);
+
+#define TYPE_SYSBUS_M48T59 "m48t59"
+
typedef struct M48t59State M48t59State;
void m48t59_write (void *private, uint32_t addr, uint32_t val);
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index fc71853eb4..b87cf490b1 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -125,6 +125,7 @@ typedef struct VirtIOBlock {
unsigned short sector_mask;
VMChangeStateEntry *change;
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+ Notifier migration_state_notifier;
struct VirtIOBlockDataPlane *dataplane;
#endif
} VirtIOBlock;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index d7e9e0fc8a..a90522d6d6 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -237,6 +237,7 @@ hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n);
hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n);
uint16_t virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n);
void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx);
+void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n);
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
uint16_t virtio_get_queue_index(VirtQueue *vq);
int virtio_queue_get_id(VirtQueue *vq);
diff --git a/include/migration/migration.h b/include/migration/migration.h
index 08c772d4dc..140e6b471c 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -90,7 +90,7 @@ int migrate_fd_close(MigrationState *s);
void add_migration_state_change_notifier(Notifier *notify);
void remove_migration_state_change_notifier(Notifier *notify);
-bool migration_is_active(MigrationState *);
+bool migration_in_setup(MigrationState *);
bool migration_has_finished(MigrationState *);
bool migration_has_failed(MigrationState *);
MigrationState *migrate_get_current(void);
diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h
index 5939eeebc7..fd48c14ec8 100644
--- a/include/qapi/opts-visitor.h
+++ b/include/qapi/opts-visitor.h
@@ -16,6 +16,12 @@
#include "qapi/visitor.h"
#include "qemu/option.h"
+/* Inclusive upper bound on the size of any flattened range. This is a safety
+ * (= anti-annoyance) measure; wrong ranges should not cause long startup
+ * delays nor exhaust virtual memory.
+ */
+#define OPTS_VISITOR_RANGE_MAX 65536
+
typedef struct OptsVisitor OptsVisitor;
/* Contrarily to qemu-option.c::parse_option_number(), OptsVisitor's "int"
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 685b2e3fcb..d6855d112e 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -65,5 +65,6 @@ int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value);
const char *qdict_get_try_str(const QDict *qdict, const char *key);
QDict *qdict_clone_shallow(const QDict *src);
+void qdict_flatten(QDict *qdict);
#endif /* QDICT_H */
diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
index 9124649ed2..d0bbc7c4a6 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -44,6 +44,7 @@ typedef enum {
QTYPE_QFLOAT,
QTYPE_QBOOL,
QTYPE_QERROR,
+ QTYPE_MAX,
} qtype_code;
struct QObject;
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 5159964863..f3fa420245 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -22,12 +22,18 @@ struct Visitor
const char *name, size_t size, Error **errp);
void (*end_struct)(Visitor *v, Error **errp);
+ void (*start_implicit_struct)(Visitor *v, void **obj, size_t size,
+ Error **errp);
+ void (*end_implicit_struct)(Visitor *v, Error **errp);
+
void (*start_list)(Visitor *v, const char *name, Error **errp);
GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
void (*end_list)(Visitor *v, Error **errp);
void (*type_enum)(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name, Error **errp);
+ void (*get_next_type)(Visitor *v, int *kind, const int *qobjects,
+ const char *name, Error **errp);
void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 28c21d8338..48a2a2edfd 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -13,6 +13,7 @@
#ifndef QAPI_VISITOR_CORE_H
#define QAPI_VISITOR_CORE_H
+#include "qapi/qmp/qobject.h"
#include "qapi/error.h"
#include <stdlib.h>
@@ -33,12 +34,17 @@ void visit_end_handle(Visitor *v, Error **errp);
void visit_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp);
void visit_end_struct(Visitor *v, Error **errp);
+void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
+ Error **errp);
+void visit_end_implicit_struct(Visitor *v, Error **errp);
void visit_start_list(Visitor *v, const char *name, Error **errp);
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
void visit_end_list(Visitor *v, Error **errp);
void visit_start_optional(Visitor *v, bool *present, const char *name,
Error **errp);
void visit_end_optional(Visitor *v, Error **errp);
+void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
+ const char *name, Error **errp);
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name, Error **errp);
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
diff --git a/include/qemu/option.h b/include/qemu/option.h
index a83c700323..7a58e477d9 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -73,6 +73,8 @@ QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
QEMUOptionParameter *list);
QEMUOptionParameter *parse_option_parameters(const char *param,
QEMUOptionParameter *list, QEMUOptionParameter *dest);
+void parse_option_size(const char *name, const char *value,
+ uint64_t *ret, Error **errp);
void free_option_parameters(QEMUOptionParameter *list);
void print_option_parameters(QEMUOptionParameter *list);
void print_option_help(QEMUOptionParameter *list);
@@ -120,6 +122,7 @@ bool qemu_opt_has_help_opt(QemuOpts *opts);
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
+int qemu_opt_unset(QemuOpts *opts, const char *name);
int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
Error **errp);
diff --git a/include/qemu/ratelimit.h b/include/qemu/ratelimit.h
index d1610f135b..d413a4a696 100644
--- a/include/qemu/ratelimit.h
+++ b/include/qemu/ratelimit.h
@@ -23,7 +23,7 @@ typedef struct {
static inline int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n)
{
- int64_t now = qemu_get_clock_ns(rt_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
if (limit->next_slice_time < now) {
limit->next_slice_time = now + limit->slice_ns;
diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h
index 0f30dccb53..361566abc4 100644
--- a/include/qemu/thread-posix.h
+++ b/include/qemu/thread-posix.h
@@ -15,7 +15,7 @@ struct QemuSemaphore {
#if defined(__APPLE__) || defined(__NetBSD__)
pthread_mutex_t lock;
pthread_cond_t cond;
- int count;
+ unsigned int count;
#else
sem_t sem;
#endif
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 9dd206ce7f..e4934dd61b 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -1,8 +1,8 @@
#ifndef QEMU_TIMER_H
#define QEMU_TIMER_H
+#include "qemu/typedefs.h"
#include "qemu-common.h"
-#include "qemu/main-loop.h"
#include "qemu/notify.h"
/* timers */
@@ -11,80 +11,643 @@
#define SCALE_US 1000
#define SCALE_NS 1
-typedef struct QEMUClock QEMUClock;
+/**
+ * QEMUClockType:
+ *
+ * The following clock types are available:
+ *
+ * @QEMU_CLOCK_REALTIME: Real time clock
+ *
+ * The real time clock should be used only for stuff which does not
+ * change the virtual machine state, as it is run even if the virtual
+ * machine is stopped. The real time clock has a frequency of 1000
+ * Hz.
+ *
+ * @QEMU_CLOCK_VIRTUAL: virtual clock
+ *
+ * The virtual clock is only run during the emulation. It is stopped
+ * when the virtual machine is stopped. Virtual timers use a high
+ * precision clock, usually cpu cycles (use ticks_per_sec).
+ *
+ * @QEMU_CLOCK_HOST: host clock
+ *
+ * The host clock should be use for device models that emulate accurate
+ * real time sources. It will continue to run when the virtual machine
+ * is suspended, and it will reflect system time changes the host may
+ * undergo (e.g. due to NTP). The host clock has the same precision as
+ * the virtual clock.
+ */
+
+typedef enum {
+ QEMU_CLOCK_REALTIME = 0,
+ QEMU_CLOCK_VIRTUAL = 1,
+ QEMU_CLOCK_HOST = 2,
+ QEMU_CLOCK_MAX
+} QEMUClockType;
+
+typedef struct QEMUTimerList QEMUTimerList;
+
+struct QEMUTimerListGroup {
+ QEMUTimerList *tl[QEMU_CLOCK_MAX];
+};
+
typedef void QEMUTimerCB(void *opaque);
+typedef void QEMUTimerListNotifyCB(void *opaque);
+
+struct QEMUTimer {
+ int64_t expire_time; /* in nanoseconds */
+ QEMUTimerList *timer_list;
+ QEMUTimerCB *cb;
+ void *opaque;
+ QEMUTimer *next;
+ int scale;
+};
+
+extern QEMUTimerListGroup main_loop_tlg;
+
+/*
+ * QEMUClockType
+ */
+
+/*
+ * qemu_clock_get_ns;
+ * @type: the clock type
+ *
+ * Get the nanosecond value of a clock with
+ * type @type
+ *
+ * Returns: the clock value in nanoseconds
+ */
+int64_t qemu_clock_get_ns(QEMUClockType type);
+
+/**
+ * qemu_clock_get_ms;
+ * @type: the clock type
+ *
+ * Get the millisecond value of a clock with
+ * type @type
+ *
+ * Returns: the clock value in milliseconds
+ */
+static inline int64_t qemu_clock_get_ms(QEMUClockType type)
+{
+ return qemu_clock_get_ns(type) / SCALE_MS;
+}
+
+/**
+ * qemu_clock_get_us;
+ * @type: the clock type
+ *
+ * Get the microsecond value of a clock with
+ * type @type
+ *
+ * Returns: the clock value in microseconds
+ */
+static inline int64_t qemu_clock_get_us(QEMUClockType type)
+{
+ return qemu_clock_get_ns(type) / SCALE_US;
+}
+
+/**
+ * qemu_clock_has_timers:
+ * @type: the clock type
+ *
+ * Determines whether a clock's default timer list
+ * has timers attached
+ *
+ * Returns: true if the clock's default timer list
+ * has timers attached
+ */
+bool qemu_clock_has_timers(QEMUClockType type);
+
+/**
+ * qemu_clock_expired:
+ * @type: the clock type
+ *
+ * Determines whether a clock's default timer list
+ * has an expired clock.
+ *
+ * Returns: true if the clock's default timer list has
+ * an expired timer
+ */
+bool qemu_clock_expired(QEMUClockType type);
+
+/**
+ * qemu_clock_use_for_deadline:
+ * @type: the clock type
+ *
+ * Determine whether a clock should be used for deadline
+ * calculations. Some clocks, for instance vm_clock with
+ * use_icount set, do not count in nanoseconds. Such clocks
+ * are not used for deadline calculations, and are presumed
+ * to interrupt any poll using qemu_notify/aio_notify
+ * etc.
+ *
+ * Returns: true if the clock runs in nanoseconds and
+ * should be used for a deadline.
+ */
+bool qemu_clock_use_for_deadline(QEMUClockType type);
+
+/**
+ * qemu_clock_deadline_ns_all:
+ * @type: the clock type
+ *
+ * Calculate the deadline across all timer lists associated
+ * with a clock (as opposed to just the default one)
+ * in nanoseconds, or -1 if no timer is set to expire.
+ *
+ * Returns: time until expiry in nanoseconds or -1
+ */
+int64_t qemu_clock_deadline_ns_all(QEMUClockType type);
+
+/**
+ * qemu_clock_get_main_loop_timerlist:
+ * @type: the clock type
+ *
+ * Return the default timer list assocatiated with a clock.
+ *
+ * Returns: the default timer list
+ */
+QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type);
-/* The real time clock should be used only for stuff which does not
- change the virtual machine state, as it is run even if the virtual
- machine is stopped. The real time clock has a frequency of 1000
- Hz. */
-extern QEMUClock *rt_clock;
-
-/* The virtual clock is only run during the emulation. It is stopped
- when the virtual machine is stopped. Virtual timers use a high
- precision clock, usually cpu cycles (use ticks_per_sec). */
-extern QEMUClock *vm_clock;
-
-/* The host clock should be use for device models that emulate accurate
- real time sources. It will continue to run when the virtual machine
- is suspended, and it will reflect system time changes the host may
- undergo (e.g. due to NTP). The host clock has the same precision as
- the virtual clock. */
-extern QEMUClock *host_clock;
-
-int64_t qemu_get_clock_ns(QEMUClock *clock);
-int64_t qemu_clock_has_timers(QEMUClock *clock);
-int64_t qemu_clock_expired(QEMUClock *clock);
-int64_t qemu_clock_deadline(QEMUClock *clock);
-void qemu_clock_enable(QEMUClock *clock, bool enabled);
-void qemu_clock_warp(QEMUClock *clock);
-
-void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
-void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
+/**
+ * qemu_clock_nofify:
+ * @type: the clock type
+ *
+ * Call the notifier callback connected with the default timer
+ * list linked to the clock, or qemu_notify() if none.
+ */
+void qemu_clock_notify(QEMUClockType type);
+
+/**
+ * qemu_clock_enable:
+ * @type: the clock type
+ * @enabled: true to enable, false to disable
+ *
+ * Enable or disable a clock
+ */
+void qemu_clock_enable(QEMUClockType type, bool enabled);
+
+/**
+ * qemu_clock_warp:
+ * @type: the clock type
+ *
+ * Warp a clock to a new value
+ */
+void qemu_clock_warp(QEMUClockType type);
+
+/**
+ * qemu_clock_register_reset_notifier:
+ * @type: the clock type
+ * @notifier: the notifier function
+ *
+ * Register a notifier function to call when the clock
+ * concerned is reset.
+ */
+void qemu_clock_register_reset_notifier(QEMUClockType type,
+ Notifier *notifier);
+
+/**
+ * qemu_clock_unregister_reset_notifier:
+ * @type: the clock type
+ * @notifier: the notifier function
+ *
+ * Unregister a notifier function to call when the clock
+ * concerned is reset.
+ */
+void qemu_clock_unregister_reset_notifier(QEMUClockType type,
Notifier *notifier);
-QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
- QEMUTimerCB *cb, void *opaque);
-void qemu_free_timer(QEMUTimer *ts);
-void qemu_del_timer(QEMUTimer *ts);
-void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
-void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
-bool qemu_timer_pending(QEMUTimer *ts);
-bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
-uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
-
-void qemu_run_timers(QEMUClock *clock);
-void qemu_run_all_timers(void);
-void configure_alarms(char const *opt);
-void init_clocks(void);
-int init_timer_alarm(void);
+/**
+ * qemu_clock_run_timers:
+ * @type: clock on which to operate
+ *
+ * Run all the timers associated with the default timer list
+ * of a clock.
+ *
+ * Returns: true if any timer ran.
+ */
+bool qemu_clock_run_timers(QEMUClockType type);
-int64_t cpu_get_ticks(void);
-void cpu_enable_ticks(void);
-void cpu_disable_ticks(void);
+/**
+ * qemu_clock_run_all_timers:
+ *
+ * Run all the timers associated with the default timer list
+ * of every clock.
+ *
+ * Returns: true if any timer ran.
+ */
+bool qemu_clock_run_all_timers(void);
+
+/*
+ * QEMUTimerList
+ */
+
+/**
+ * timerlist_new:
+ * @type: the clock type to associate with the timerlist
+ * @cb: the callback to call on notification
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timerlist associated with the clock of
+ * type @type.
+ *
+ * Returns: a pointer to the QEMUTimerList created
+ */
+QEMUTimerList *timerlist_new(QEMUClockType type,
+ QEMUTimerListNotifyCB *cb, void *opaque);
+
+/**
+ * timerlist_free:
+ * @timer_list: the timer list to free
+ *
+ * Frees a timer_list. It must have no active timers.
+ */
+void timerlist_free(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_has_timers:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine whether a timer list has active timers
+ *
+ * Returns: true if the timer list has timers.
+ */
+bool timerlist_has_timers(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_expired:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine whether a timer list has any timers which
+ * are expired.
+ *
+ * Returns: true if the timer list has timers which
+ * have expired.
+ */
+bool timerlist_expired(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_deadline_ns:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine the deadline for a timer_list, i.e.
+ * the number of nanoseconds until the first timer
+ * expires. Return -1 if there are no timers.
+ *
+ * Returns: the number of nanoseconds until the earliest
+ * timer expires -1 if none
+ */
+int64_t timerlist_deadline_ns(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_get_clock:
+ * @timer_list: the timer list to operate on
+ *
+ * Determine the clock type associated with a timer list.
+ *
+ * Returns: the clock type associated with the
+ * timer list.
+ */
+QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_run_timers:
+ * @timer_list: the timer list to use
+ *
+ * Call all expired timers associated with the timer list.
+ *
+ * Returns: true if any timer expired
+ */
+bool timerlist_run_timers(QEMUTimerList *timer_list);
+
+/**
+ * timerlist_notify:
+ * @timer_list: the timer list to use
+ *
+ * call the notifier callback associated with the timer list.
+ */
+void timerlist_notify(QEMUTimerList *timer_list);
+
+/*
+ * QEMUTimerListGroup
+ */
+
+/**
+ * timerlistgroup_init:
+ * @tlg: the timer list group
+ * @cb: the callback to call when a notify is required
+ * @opaque: the opaque pointer to be passed to the callback.
+ *
+ * Initialise a timer list group. This must already be
+ * allocated in memory and zeroed. The notifier callback is
+ * called whenever a clock in the timer list group is
+ * reenabled or whenever a timer associated with any timer
+ * list is modified. If @cb is specified as null, qemu_notify()
+ * is used instead.
+ */
+void timerlistgroup_init(QEMUTimerListGroup *tlg,
+ QEMUTimerListNotifyCB *cb, void *opaque);
+
+/**
+ * timerlistgroup_deinit:
+ * @tlg: the timer list group
+ *
+ * Deinitialise a timer list group. This must already be
+ * initialised. Note the memory is not freed.
+ */
+void timerlistgroup_deinit(QEMUTimerListGroup *tlg);
+
+/**
+ * timerlistgroup_run_timers:
+ * @tlg: the timer list group
+ *
+ * Run the timers associated with a timer list group.
+ * This will run timers on multiple clocks.
+ *
+ * Returns: true if any timer callback ran
+ */
+bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg);
+
+/**
+ * timerlistgroup_deadline_ns:
+ * @tlg: the timer list group
+ *
+ * Determine the deadline of the soonest timer to
+ * expire associated with any timer list linked to
+ * the timer list group. Only clocks suitable for
+ * deadline calculation are included.
+ *
+ * Returns: the deadline in nanoseconds or -1 if no
+ * timers are to expire.
+ */
+int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg);
+
+/*
+ * QEMUTimer
+ */
+
+/**
+ * timer_init:
+ * @ts: the timer to be initialised
+ * @timer_list: the timer list to attach the timer to
+ * @scale: the scale value for the tiemr
+ * @cb: the callback to be called when the timer expires
+ * @opaque: the opaque pointer to be passed to the callback
+ *
+ * Initialise a new timer and associate it with @timer_list.
+ * The caller is responsible for allocating the memory.
+ *
+ * You need not call an explicit deinit call. Simply make
+ * sure it is not on a list with timer_del.
+ */
+void timer_init(QEMUTimer *ts,
+ QEMUTimerList *timer_list, int scale,
+ QEMUTimerCB *cb, void *opaque);
+
+/**
+ * timer_new_tl:
+ * @timer_list: the timer list to attach the timer to
+ * @scale: the scale value for the tiemr
+ * @cb: the callback to be called when the timer expires
+ * @opaque: the opaque pointer to be passed to the callback
+ *
+ * Creeate a new timer and associate it with @timer_list.
+ * The memory is allocated by the function.
+ *
+ * This is not the preferred interface unless you know you
+ * are going to call timer_free. Use timer_init instead.
+ *
+ * Returns: a pointer to the timer
+ */
+static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list,
+ int scale,
+ QEMUTimerCB *cb,
+ void *opaque)
+{
+ QEMUTimer *ts = g_malloc0(sizeof(QEMUTimer));
+ timer_init(ts, timer_list, scale, cb, opaque);
+ return ts;
+}
-static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
- void *opaque)
+/**
+ * timer_new:
+ * @type: the clock type to use
+ * @scale: the scale value for the tiemr
+ * @cb: the callback to be called when the timer expires
+ * @opaque: the opaque pointer to be passed to the callback
+ *
+ * Creeate a new timer and associate it with the default
+ * timer list for the clock type @type.
+ *
+ * Returns: a pointer to the timer
+ */
+static inline QEMUTimer *timer_new(QEMUClockType type, int scale,
+ QEMUTimerCB *cb, void *opaque)
{
- return qemu_new_timer(clock, SCALE_NS, cb, opaque);
+ return timer_new_tl(main_loop_tlg.tl[type], scale, cb, opaque);
}
-static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb,
- void *opaque)
+/**
+ * timer_new_ns:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with nanosecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb,
+ void *opaque)
{
- return qemu_new_timer(clock, SCALE_MS, cb, opaque);
+ return timer_new(type, SCALE_NS, cb, opaque);
}
-static inline int64_t qemu_get_clock_ms(QEMUClock *clock)
+/**
+ * timer_new_us:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with microsecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *timer_new_us(QEMUClockType type, QEMUTimerCB *cb,
+ void *opaque)
{
- return qemu_get_clock_ns(clock) / SCALE_MS;
+ return timer_new(type, SCALE_US, cb, opaque);
}
+/**
+ * timer_new_ms:
+ * @clock: the clock to associate with the timer
+ * @callback: the callback to call when the timer expires
+ * @opaque: the opaque pointer to pass to the callback
+ *
+ * Create a new timer with millisecond scale on the default timer list
+ * associated with the clock.
+ *
+ * Returns: a pointer to the newly created timer
+ */
+static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb,
+ void *opaque)
+{
+ return timer_new(type, SCALE_MS, cb, opaque);
+}
+
+/**
+ * timer_free:
+ * @ts: the timer
+ *
+ * Free a timer (it must not be on the active list)
+ */
+void timer_free(QEMUTimer *ts);
+
+/**
+ * timer_del:
+ * @ts: the timer
+ *
+ * Delete a timer from the active list.
+ */
+void timer_del(QEMUTimer *ts);
+
+/**
+ * timer_mod_ns:
+ * @ts: the timer
+ * @expire_time: the expiry time in nanoseconds
+ *
+ * Modify a timer to expire at @expire_time
+ */
+void timer_mod_ns(QEMUTimer *ts, int64_t expire_time);
+
+/**
+ * timer_mod:
+ * @ts: the timer
+ * @expire_time: the expire time in the units associated with the timer
+ *
+ * Modify a timer to expiry at @expire_time, taking into
+ * account the scale associated with the timer.
+ */
+void timer_mod(QEMUTimer *ts, int64_t expire_timer);
+
+/**
+ * timer_pending:
+ * @ts: the timer
+ *
+ * Determines whether a timer is pending (i.e. is on the
+ * active list of timers, whether or not it has not yet expired).
+ *
+ * Returns: true if the timer is pending
+ */
+bool timer_pending(QEMUTimer *ts);
+
+/**
+ * timer_expired:
+ * @ts: the timer
+ *
+ * Determines whether a timer has expired.
+ *
+ * Returns: true if the timer has expired
+ */
+bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
+
+/**
+ * timer_expire_time_ns:
+ * @ts: the timer
+ *
+ * Determine the expiry time of a timer
+ *
+ * Returns: the expiry time in nanoseconds
+ */
+uint64_t timer_expire_time_ns(QEMUTimer *ts);
+
+/**
+ * timer_get:
+ * @f: the file
+ * @ts: the timer
+ *
+ * Read a timer @ts from a file @f
+ */
+void timer_get(QEMUFile *f, QEMUTimer *ts);
+
+/**
+ * timer_put:
+ * @f: the file
+ * @ts: the timer
+ */
+void timer_put(QEMUFile *f, QEMUTimer *ts);
+
+/*
+ * General utility functions
+ */
+
+/**
+ * qemu_timeout_ns_to_ms:
+ * @ns: nanosecond timeout value
+ *
+ * Convert a nanosecond timeout value (or -1) to
+ * a millisecond value (or -1), always rounding up.
+ *
+ * Returns: millisecond timeout value
+ */
+int qemu_timeout_ns_to_ms(int64_t ns);
+
+/**
+ * qemu_poll_ns:
+ * @fds: Array of file descriptors
+ * @nfds: number of file descriptors
+ * @timeout: timeout in nanoseconds
+ *
+ * Perform a poll like g_poll but with a timeout in nanoseconds.
+ * See g_poll documentation for further details.
+ *
+ * Returns: number of fds ready
+ */
+int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout);
+
+/**
+ * qemu_soonest_timeout:
+ * @timeout1: first timeout in nanoseconds (or -1 for infinite)
+ * @timeout2: second timeout in nanoseconds (or -1 for infinite)
+ *
+ * Calculates the soonest of two timeout values. -1 means infinite, which
+ * is later than any other value.
+ *
+ * Returns: soonest timeout value in nanoseconds (or -1 for infinite)
+ */
+static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
+{
+ /* we can abuse the fact that -1 (which means infinite) is a maximal
+ * value when cast to unsigned. As this is disgusting, it's kept in
+ * one inline function.
+ */
+ return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
+}
+
+/**
+ * initclocks:
+ *
+ * Initialise the clock & timer infrastructure
+ */
+void init_clocks(void);
+
+int64_t cpu_get_ticks(void);
+void cpu_enable_ticks(void);
+void cpu_disable_ticks(void);
+
static inline int64_t get_ticks_per_sec(void)
{
return 1000000000LL;
}
+/*
+ * Low level clock functions
+ */
+
/* real time host monotonic timer */
static inline int64_t get_clock_realtime(void)
{
@@ -128,9 +691,6 @@ static inline int64_t get_clock(void)
}
#endif
-void qemu_get_timer(QEMUFile *f, QEMUTimer *ts);
-void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
-
/* icount */
int64_t cpu_get_icount(void);
int64_t cpu_get_clock(void);
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index ac9f8d41a3..3205540059 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -4,9 +4,12 @@
/* A load of opaque types so that device init declarations don't have to
pull in all the real definitions. */
typedef struct QEMUTimer QEMUTimer;
+typedef struct QEMUTimerListGroup QEMUTimerListGroup;
typedef struct QEMUFile QEMUFile;
typedef struct QEMUBH QEMUBH;
+typedef struct AioContext AioContext;
+
struct Monitor;
typedef struct Monitor Monitor;
typedef struct MigrationParams MigrationParams;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index daf1835c1a..3e4993661a 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -80,7 +80,11 @@ struct TranslationBlock;
* @synchronize_from_tb: Callback for synchronizing state from a TCG
* #TranslationBlock.
* @get_phys_page_debug: Callback for obtaining a physical address.
+ * @gdb_read_register: Callback for letting GDB read a register.
+ * @gdb_write_register: Callback for letting GDB write a register.
* @vmsd: State description for migration.
+ * @gdb_num_core_regs: Number of core registers accessible to GDB.
+ * @gdb_core_xml_file: File name for core registers GDB XML description.
*
* Represents a CPU family or model.
*/
@@ -108,8 +112,9 @@ typedef struct CPUClass {
void (*set_pc)(CPUState *cpu, vaddr value);
void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
+ int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg);
+ int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
- const struct VMStateDescription *vmsd;
int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
int cpuid, void *opaque);
int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
@@ -118,6 +123,10 @@ typedef struct CPUClass {
int cpuid, void *opaque);
int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);
+
+ const struct VMStateDescription *vmsd;
+ int gdb_num_core_regs;
+ const char *gdb_core_xml_file;
} CPUClass;
struct KVMState;
@@ -142,6 +151,8 @@ struct kvm_run;
* @env_ptr: Pointer to subclass-specific CPUArchState field.
* @current_tb: Currently executing TB.
* @gdb_regs: Additional GDB registers.
+ * @gdb_num_regs: Number of total registers accessible to GDB.
+ * @gdb_num_g_regs: Number of registers in GDB 'g' packets.
* @next_cpu: Next CPU sharing TB cache.
* @kvm_fd: vCPU file descriptor for KVM.
*
@@ -177,6 +188,8 @@ struct CPUState {
void *env_ptr; /* CPUArchState */
struct TranslationBlock *current_tb;
struct GDBRegisterState *gdb_regs;
+ int gdb_num_regs;
+ int gdb_num_g_regs;
CPUState *next_cpu;
int kvm_fd;
diff --git a/include/qom/object.h b/include/qom/object.h
index 23fc048088..9b69065b7a 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -398,6 +398,8 @@ struct Object
* @instance_init: This function is called to initialize an object. The parent
* class will have already been initialized so the type is only responsible
* for initializing its own members.
+ * @instance_post_init: This function is called to finish initialization of
+ * an object, after all @instance_init functions were called.
* @instance_finalize: This function is called during object destruction. This
* is called before the parent @instance_finalize function has been called.
* An object should only free the members that are unique to its type in this
@@ -433,6 +435,7 @@ struct TypeInfo
size_t instance_size;
void (*instance_init)(Object *obj);
+ void (*instance_post_init)(Object *obj);
void (*instance_finalize)(Object *obj);
bool abstract;
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index e65e4a4844..8053130a97 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -77,6 +77,7 @@ struct CharDriverState {
int explicit_fe_open;
int explicit_be_open;
int avail_connections;
+ int is_mux;
QemuOpts *opts;
QTAILQ_ENTRY(CharDriverState) next;
};
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index b8c770f8d9..19fafb2cf9 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -20,7 +20,9 @@ typedef struct ArchDumpInfo {
int d_class; /* ELFCLASS32 or ELFCLASS64 */
} ArchDumpInfo;
-int cpu_get_dump_info(ArchDumpInfo *info);
+struct GuestPhysBlockList; /* memory_mapping.h */
+int cpu_get_dump_info(ArchDumpInfo *info,
+ const struct GuestPhysBlockList *guest_phys_blocks);
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
#endif
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index ce3efaf210..8e7668524b 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -174,7 +174,7 @@ int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
target_ulong len, int type);
void kvm_remove_all_breakpoints(CPUState *cpu);
-int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap);
+int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap);
#ifndef _WIN32
int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset);
#endif
diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h
index 6dfb68ddcd..a75d59a55d 100644
--- a/include/sysemu/memory_mapping.h
+++ b/include/sysemu/memory_mapping.h
@@ -17,6 +17,25 @@
#include "qemu/queue.h"
#include "qemu/typedefs.h"
+typedef struct GuestPhysBlock {
+ /* visible to guest, reflects PCI hole, etc */
+ hwaddr target_start;
+
+ /* implies size */
+ hwaddr target_end;
+
+ /* points into host memory */
+ uint8_t *host_addr;
+
+ QTAILQ_ENTRY(GuestPhysBlock) next;
+} GuestPhysBlock;
+
+/* point-in-time snapshot of guest-visible physical mappings */
+typedef struct GuestPhysBlockList {
+ unsigned num;
+ QTAILQ_HEAD(GuestPhysBlockHead, GuestPhysBlock) head;
+} GuestPhysBlockList;
+
/* The physical and virtual address in the memory mapping are contiguous. */
typedef struct MemoryMapping {
hwaddr phys_addr;
@@ -45,10 +64,17 @@ void memory_mapping_list_free(MemoryMappingList *list);
void memory_mapping_list_init(MemoryMappingList *list);
-void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp);
+void guest_phys_blocks_free(GuestPhysBlockList *list);
+void guest_phys_blocks_init(GuestPhysBlockList *list);
+void guest_phys_blocks_append(GuestPhysBlockList *list);
+
+void qemu_get_guest_memory_mapping(MemoryMappingList *list,
+ const GuestPhysBlockList *guest_phys_blocks,
+ Error **errp);
/* get guest's memory mapping without do paging(virtual address is 0). */
-void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list,
+ const GuestPhysBlockList *guest_phys_blocks);
void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
int64_t length);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 3caeb66eb2..b1aa059102 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -103,7 +103,6 @@ typedef enum {
extern int vga_interface_type;
#define xenfb_enabled (vga_interface_type == VGA_XENFB)
-#define qxl_enabled (vga_interface_type == VGA_QXL)
extern int graphic_width;
extern int graphic_height;
@@ -125,7 +124,7 @@ extern int boot_menu;
extern uint8_t *boot_splash_filedata;
extern size_t boot_splash_filedata_size;
extern uint8_t qemu_extra_params_fw[2];
-extern QEMUClock *rtc_clock;
+extern QEMUClockType rtc_clock;
#define MAX_NODES 64
#define MAX_CPUMASK_BITS 255
diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h
index eba6d77d1d..c6c756b23d 100644
--- a/include/ui/qemu-spice.h
+++ b/include/ui/qemu-spice.h
@@ -27,6 +27,7 @@
#include "monitor/monitor.h"
extern int using_spice;
+extern int spice_displays;
void qemu_spice_init(void);
void qemu_spice_input_init(void);
@@ -57,6 +58,7 @@ static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
#include "monitor/monitor.h"
#define using_spice 0
+#define spice_displays 0
static inline int qemu_spice_set_passwd(const char *passwd,
bool fail_if_connected,
bool disconnect_if_connected)